Merge branch 'master' into upstream-merge-27344
@@ -63624,6 +63624,7 @@
|
||||
dir = 8
|
||||
},
|
||||
/obj/effect/turf_decal/bot,
|
||||
/obj/machinery/portable_atmospherics/canister/freon,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/engineering)
|
||||
"cqt" = (
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
//rune colors, for easy reference
|
||||
#define RUNE_COLOR_TALISMAN "#0000FF"
|
||||
#define RUNE_COLOR_TELEPORT "#551A8B"
|
||||
#define RUNE_COLOR_OFFER "#FFFFFF"
|
||||
#define RUNE_COLOR_DARKRED "#7D1717"
|
||||
#define RUNE_COLOR_MEDIUMRED "#C80000"
|
||||
#define RUNE_COLOR_RED "#FF0000"
|
||||
#define RUNE_COLOR_EMP "#4D94FF"
|
||||
#define RUNE_COLOR_SUMMON "#00FF00"
|
||||
@@ -27,6 +27,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
#define BLOCK_GAS_SMOKE_EFFECT 4096 // blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY!
|
||||
#define THICKMATERIAL 8192 //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body.
|
||||
#define DROPDEL 16384 // When dropped, it calls qdel on itself
|
||||
#define PREVENT_CLICK_UNDER 32768 //Prevent clicking things below it on the same turf eg. doors/ fulltile windows
|
||||
|
||||
/* Secondary atom flags, access using the SECONDARY_FLAG macros */
|
||||
|
||||
|
||||
@@ -407,3 +407,7 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
|
||||
|
||||
//Error handler defines
|
||||
#define ERROR_USEFUL_LEN 2
|
||||
|
||||
#define NO_FIELD 0
|
||||
#define FIELD_TURF 1
|
||||
#define FIELD_EDGE 2
|
||||
|
||||
@@ -340,6 +340,20 @@ Proc for attack log creation, because really why not
|
||||
qdel(progbar)
|
||||
|
||||
|
||||
//some additional checks as a callback for for do_afters that want to break on losing health or on the mob taking action
|
||||
/mob/proc/break_do_after_checks(list/checked_health, check_clicks)
|
||||
if(check_clicks && next_move > world.time)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//pass a list in the format list("health" = mob's health var) to check health during this
|
||||
/mob/living/break_do_after_checks(list/checked_health, check_clicks)
|
||||
if(islist(checked_health))
|
||||
if(health < checked_health["health"])
|
||||
return FALSE
|
||||
checked_health["health"] = health
|
||||
return ..()
|
||||
|
||||
/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1, datum/callback/extra_checks = null)
|
||||
if(!user)
|
||||
return 0
|
||||
|
||||
@@ -13,4 +13,5 @@ GLOBAL_VAR_INIT(sac_image, null)
|
||||
GLOBAL_VAR_INIT(cult_vote_called, FALSE)
|
||||
GLOBAL_VAR_INIT(cult_mastered, FALSE)
|
||||
GLOBAL_VAR_INIT(reckoning_complete, FALSE)
|
||||
GLOBAL_VAR_INIT(sac_complete, FALSE)
|
||||
GLOBAL_VAR_INIT(sac_complete, FALSE)
|
||||
GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
|
||||
@@ -92,6 +92,9 @@
|
||||
if(next_move > world.time) // in the year 2000...
|
||||
return
|
||||
|
||||
if(A.IsObscured())
|
||||
return
|
||||
|
||||
if(istype(loc,/obj/mecha))
|
||||
var/obj/mecha/M = loc
|
||||
return M.click_action(A,src,params)
|
||||
@@ -141,6 +144,24 @@
|
||||
else
|
||||
RangedAttack(A,params)
|
||||
|
||||
//Is the atom obscured by a PREVENT_CLICK_UNDER object above it
|
||||
/atom/proc/IsObscured()
|
||||
if(!isturf(loc)) //This only makes sense for things directly on turfs for now
|
||||
return FALSE
|
||||
var/turf/T = get_turf_pixel(src)
|
||||
if(!T)
|
||||
return FALSE
|
||||
for(var/atom/movable/AM in T)
|
||||
if(AM.flags & PREVENT_CLICK_UNDER && AM.density && AM.layer > layer)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/turf/IsObscured()
|
||||
for(var/atom/movable/AM in src)
|
||||
if(AM.flags & PREVENT_CLICK_UNDER && AM.density)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/atom/movable/proc/CanReach(atom/target,obj/item/tool,view_only = FALSE)
|
||||
if(isturf(target) || isturf(target.loc) || DirectAccess(target)) //Directly accessible atoms
|
||||
if(Adjacent(target) || (tool && CheckToolReach(src, target, tool.reach))) //Adjacent or reaching attacks
|
||||
|
||||
@@ -287,9 +287,9 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
GLOB.blood_target = null
|
||||
else
|
||||
blood_target = GLOB.blood_target
|
||||
if(Cviewer)
|
||||
if(Cviewer.seeking && Cviewer.master)
|
||||
blood_target = Cviewer.master
|
||||
if(Cviewer && Cviewer.seeking && Cviewer.master)
|
||||
blood_target = Cviewer.master
|
||||
desc = "Your blood sense is leading you to [Cviewer.master]"
|
||||
if(!blood_target)
|
||||
if(!GLOB.sac_complete)
|
||||
if(icon_state == "runed_sense0")
|
||||
@@ -301,22 +301,21 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
desc = "Nar-Sie demands that [GLOB.sac_mind] be sacrificed before the summoning ritual can begin."
|
||||
add_overlay(GLOB.sac_image)
|
||||
else
|
||||
if(SSticker.mode.eldergod)
|
||||
desc = "The sacrifice is complete, prepare to summon Nar-Sie!"
|
||||
else
|
||||
desc = "The summoning is complete, glory to Nar-Sie!"
|
||||
if(icon_state == "runed_sense1")
|
||||
return
|
||||
animate(src, transform = null, time = 1, loop = 0)
|
||||
angle = 0
|
||||
cut_overlays()
|
||||
icon_state = "runed_sense1"
|
||||
desc = "The sacrifice is complete, bring the wrath of Nar-Sie upon the crew!"
|
||||
add_overlay(narnar)
|
||||
return
|
||||
var/turf/P = get_turf(blood_target)
|
||||
var/turf/Q = get_turf(mob_viewer)
|
||||
var/area/A = get_area(P)
|
||||
if(P.z != Q.z) //The target is on a different Z level, we cannot sense that far.
|
||||
icon_state = "runed_sense2"
|
||||
desc = "[blood_target] is no longer in your sector, you cannot sense its presence here."
|
||||
return
|
||||
desc = "You are currently tracking [blood_target] in [A.name]."
|
||||
var/target_angle = Get_Angle(Q, P)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
SUBSYSTEM_DEF(fields)
|
||||
name = "Fields"
|
||||
wait = 2
|
||||
priority = 40
|
||||
flags = SS_KEEP_TIMING
|
||||
var/list/datum/proximity_monitor/advanced/running = list()
|
||||
var/list/datum/proximity_monitor/advanced/currentrun = list()
|
||||
|
||||
/datum/controller/subsystem/fields/fire(resumed = 0)
|
||||
if(!resumed)
|
||||
src.currentrun = running.Copy()
|
||||
var/list/currentrun = src.currentrun
|
||||
while(currentrun.len)
|
||||
var/datum/proximity_monitor/advanced/F = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(!F.requires_processing)
|
||||
continue
|
||||
F.process()
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/fields/proc/register_new_field(datum/proximity_monitor/advanced/F)
|
||||
running += F
|
||||
|
||||
/datum/controller/subsystem/fields/proc/unregister_field(datum/proximity_monitor/advanced/F)
|
||||
running -= F
|
||||
@@ -284,7 +284,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
//Now animate the cinematic
|
||||
switch(station_missed)
|
||||
if(NUKE_NEAR_MISS) //nuke was nearby but (mostly) missed
|
||||
if( mode && !override )
|
||||
if(mode && !override )
|
||||
override = mode.name
|
||||
switch( override )
|
||||
if("nuclear emergency") //Nuke wasn't on station when it blew up
|
||||
@@ -294,6 +294,17 @@ SUBSYSTEM_DEF(ticker)
|
||||
station_explosion_detonation(bomb)
|
||||
flick("station_intact_fade_red",cinematic)
|
||||
cinematic.icon_state = "summary_nukefail"
|
||||
if("cult")
|
||||
cinematic.icon_state = null
|
||||
flick("intro_cult",cinematic)
|
||||
sleep(25)
|
||||
world << sound('sound/magic/enter_blood.ogg')
|
||||
sleep(28)
|
||||
world << sound('sound/machines/terminal_off.ogg')
|
||||
sleep(20)
|
||||
flick("station_corrupted",cinematic)
|
||||
world << sound('sound/effects/ghost.ogg')
|
||||
actually_blew_up = FALSE
|
||||
if("gang war") //Gang Domination (just show the override screen)
|
||||
cinematic.icon_state = "intro_malf_still"
|
||||
flick("intro_malf",cinematic)
|
||||
@@ -342,6 +353,13 @@ SUBSYSTEM_DEF(ticker)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
station_explosion_detonation(bomb) //TODO: no idea what this case could be
|
||||
cinematic.icon_state = "summary_selfdes"
|
||||
if("cult") //Station nuked (nuke,explosion,summary)
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
station_explosion_detonation(bomb) //TODO: no idea what this case could be
|
||||
cinematic.icon_state = "summary_cult"
|
||||
if("no_core") //Nuke failed to detonate as it had no core
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
var/obj/machinery/holopad/H = I
|
||||
if(!QDELETED(H) && H.is_operational())
|
||||
dialed_holopads += H
|
||||
H.say("Incoming call.")
|
||||
LAZYADD(H.holo_calls, src)
|
||||
|
||||
if(!dialed_holopads.len)
|
||||
@@ -42,12 +43,16 @@
|
||||
|
||||
//cleans up ALL references :)
|
||||
/datum/holocall/Destroy()
|
||||
QDEL_NULL(eye)
|
||||
|
||||
user.reset_perspective()
|
||||
if(user.client)
|
||||
for(var/datum/camerachunk/chunk in eye.visibleCameraChunks)
|
||||
user.client.images -= chunk.obscured
|
||||
user.remote_control = null
|
||||
QDEL_NULL(eye)
|
||||
|
||||
user = null
|
||||
hologram.HC = null
|
||||
if(hologram)
|
||||
hologram.HC = null
|
||||
hologram = null
|
||||
calling_holopad.outgoing_call = null
|
||||
|
||||
|
||||
@@ -1330,7 +1330,7 @@
|
||||
obj_count++
|
||||
|
||||
/datum/mind/proc/find_syndicate_uplink()
|
||||
var/list/L = current.get_contents()
|
||||
var/list/L = current.GetAllContents()
|
||||
for (var/obj/item/I in L)
|
||||
if (I.hidden_uplink)
|
||||
return I.hidden_uplink
|
||||
|
||||
@@ -387,4 +387,4 @@
|
||||
return list("operation_time" = 0, "new_obj_type" = /obj/effect/temp_visual/ratvar/beam/itemconsume, "power_cost" = -(CLOCKCULT_POWER_UNIT*0.04), "spawn_dir" = SOUTH)
|
||||
|
||||
/obj/item/clockwork/alloy_shards/small/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
|
||||
return list("operation_time" = 0, "new_obj_type" = /obj/effect/temp_visual/ratvar/beam/itemconsume, "power_cost" = -(CLOCKCULT_POWER_UNIT*0.02), "spawn_dir" = SOUTH)
|
||||
return list("operation_time" = 0, "new_obj_type" = /obj/effect/temp_visual/ratvar/beam/itemconsume, "power_cost" = -(CLOCKCULT_POWER_UNIT*0.02), "spawn_dir" = SOUTH)
|
||||
@@ -162,14 +162,15 @@
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
var/randomsinglesprite = FALSE
|
||||
var/randomspritemax = 2
|
||||
var/sprite_shift = 9
|
||||
|
||||
/obj/item/clockwork/alloy_shards/Initialize()
|
||||
. = ..()
|
||||
if(randomsinglesprite)
|
||||
replace_name_desc()
|
||||
icon_state = "[icon_state][rand(1, randomspritemax)]"
|
||||
pixel_x = rand(-9, 9)
|
||||
pixel_y = rand(-9, 9)
|
||||
pixel_x = rand(-sprite_shift, sprite_shift)
|
||||
pixel_y = rand(-sprite_shift, sprite_shift)
|
||||
|
||||
/obj/item/clockwork/alloy_shards/proc/replace_name_desc()
|
||||
name = "replicant alloy shard"
|
||||
@@ -177,16 +178,21 @@
|
||||
clockwork_desc = "A broken shard of replicant alloy. Can be proselytized for additional power."
|
||||
|
||||
/obj/item/clockwork/alloy_shards/large
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
randomsinglesprite = TRUE
|
||||
icon_state = "shard_large"
|
||||
sprite_shift = 9
|
||||
|
||||
/obj/item/clockwork/alloy_shards/medium
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
randomsinglesprite = TRUE
|
||||
icon_state = "shard_medium"
|
||||
sprite_shift = 10
|
||||
|
||||
/obj/item/clockwork/alloy_shards/medium/gear_bit
|
||||
randomspritemax = 4
|
||||
icon_state = "gear_bit"
|
||||
sprite_shift = 12
|
||||
|
||||
/obj/item/clockwork/alloy_shards/medium/gear_bit/replace_name_desc()
|
||||
name = "gear bit"
|
||||
@@ -200,9 +206,11 @@
|
||||
name = "complex gear bit"
|
||||
|
||||
/obj/item/clockwork/alloy_shards/small
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
randomsinglesprite = TRUE
|
||||
randomspritemax = 3
|
||||
icon_state = "shard_small"
|
||||
sprite_shift = 12
|
||||
|
||||
/obj/item/clockwork/alloy_shards/pinion_lock
|
||||
name = "pinion lock"
|
||||
|
||||
@@ -178,21 +178,24 @@
|
||||
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, no_table_check)
|
||||
/obj/item/clockwork/clockwork_proselytizer/proc/proselytize(atom/target, mob/living/user, silent, no_table_check)
|
||||
if(!target || !user)
|
||||
return FALSE
|
||||
if(repairing)
|
||||
to_chat(user, "<span class='warning'>You are currently repairing [repairing] with [src]!</span>")
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You are currently repairing [repairing] with [src]!</span>")
|
||||
return FALSE
|
||||
if(recharging)
|
||||
to_chat(user, "<span class='warning'>You are currently recharging [src] from the [recharging.sigil_name]!</span>")
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You are currently recharging [src] from the [recharging.sigil_name]!</span>")
|
||||
return FALSE
|
||||
var/list/proselytize_values = target.proselytize_vals(user, src) //relevant values for proselytizing stuff, given as an associated list
|
||||
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)
|
||||
to_chat(user, "<span class='warning'>[target] cannot be proselytized!</span>")
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>[target] cannot be proselytized!</span>")
|
||||
if(!no_table_check)
|
||||
return TRUE
|
||||
return FALSE
|
||||
@@ -207,19 +210,22 @@
|
||||
|
||||
var/target_type = target.type
|
||||
|
||||
if(!proselytize_checks(proselytize_values, target, target_type, user))
|
||||
if(!proselytize_checks(proselytize_values, target, target_type, user, silent))
|
||||
return FALSE
|
||||
|
||||
proselytize_values["operation_time"] *= speed_multiplier
|
||||
|
||||
playsound(target, 'sound/machines/click.ogg', 50, 1)
|
||||
if(proselytize_values["operation_time"])
|
||||
user.visible_message("<span class='warning'>[user]'s [name] begins tearing apart [target]!</span>", "<span class='brass'>You begin proselytizing [target]...</span>")
|
||||
if(!silent)
|
||||
user.visible_message("<span class='warning'>[user]'s [name] begins tearing apart [target]!</span>", "<span class='brass'>You begin proselytizing [target]...</span>")
|
||||
if(!do_after(user, proselytize_values["operation_time"], target = target, extra_checks = CALLBACK(src, .proc/proselytize_checks, proselytize_values, target, target_type, user, TRUE)))
|
||||
return FALSE
|
||||
user.visible_message("<span class='warning'>[user]'s [name] covers [target] in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
|
||||
if(!silent)
|
||||
user.visible_message("<span class='warning'>[user]'s [name] covers [target] in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user]'s [name] tears apart [target], covering it in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
|
||||
if(!silent)
|
||||
user.visible_message("<span class='warning'>[user]'s [name] tears apart [target], covering it in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
|
||||
|
||||
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
var/new_thing_type = proselytize_values["new_obj_type"]
|
||||
@@ -227,11 +233,12 @@
|
||||
var/turf/T = target
|
||||
T.ChangeTurf(new_thing_type)
|
||||
else
|
||||
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()
|
||||
else
|
||||
var/atom/A = new new_thing_type(get_turf(target))
|
||||
A.setDir(proselytize_values["spawn_dir"])
|
||||
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()
|
||||
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
|
||||
qdel(target)
|
||||
modify_stored_power(-proselytize_values["power_cost"])
|
||||
@@ -239,8 +246,13 @@
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//The following three procs are heavy wizardry.
|
||||
//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) || !target || QDELETED(target) || !user)
|
||||
if(!islist(proselytize_values) || QDELETED(target) || QDELETED(user))
|
||||
return FALSE
|
||||
if(repairing || recharging)
|
||||
return FALSE
|
||||
@@ -259,11 +271,8 @@
|
||||
return TRUE
|
||||
|
||||
//The repair check proc.
|
||||
//Is dark magic. Can probably kill you.
|
||||
//What this proc does is it takes an existing list of values, which it modifies.
|
||||
//This(modifying an existing object) is the only way to get information OUT of a do_after callback, which this is used as.
|
||||
/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.
|
||||
if(!islist(repair_values) || !target || QDELETED(target) || !user)
|
||||
if(!islist(repair_values) || QDELETED(target) || QDELETED(user))
|
||||
return FALSE
|
||||
if(isliving(target)) //standard checks for if we can affect the target
|
||||
var/mob/living/L = target
|
||||
@@ -302,9 +311,9 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//checked constantly while charging from a sigil
|
||||
//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)
|
||||
if(!islist(charge_values) || !sigil || QDELETED(sigil) || !user)
|
||||
if(!islist(charge_values) || QDELETED(sigil) || QDELETED(user))
|
||||
return FALSE
|
||||
if(can_use_power(RATVAR_POWER_CHECK))
|
||||
return FALSE
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert")
|
||||
var/area/A = get_area(src)
|
||||
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [A.name] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
|
||||
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency..proc/request, null, 0, 0)
|
||||
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 0, null, FALSE, 0)
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
|
||||
GLOB.ratvar_awakens--
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/action/innate/cult/master/IsAvailable()
|
||||
if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER))
|
||||
if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER) || GLOB.cult_narsie)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/worn_overlays(isinhands)
|
||||
. = list()
|
||||
if(!isinhands && current_charges)
|
||||
. += mutable_appearance('icons/effects/effects.dmi', "shield-cult", MOB_LAYER + 0.01)
|
||||
. += mutable_appearance('icons/effects/cult_effects.dmi', "shield-cult", MOB_LAYER + 0.01)
|
||||
|
||||
/obj/item/clothing/suit/hooded/cultrobes/berserker
|
||||
name = "flagellant's robes"
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
//after a delay, creates a rune below you. for constructs creating runes.
|
||||
/datum/action/innate/cult/create_rune
|
||||
background_icon_state = "bg_cult"
|
||||
var/obj/effect/rune/rune_type
|
||||
var/cooldown = 0
|
||||
var/base_cooldown = 900
|
||||
var/scribe_time = 100
|
||||
var/damage_interrupt = TRUE
|
||||
var/action_interrupt = TRUE
|
||||
var/obj/effect/overlay/temp/cult/rune_spawn/rune_word_type
|
||||
var/obj/effect/overlay/temp/cult/rune_spawn/rune_innerring_type
|
||||
var/obj/effect/overlay/temp/cult/rune_spawn/rune_center_type
|
||||
var/rune_color
|
||||
|
||||
/datum/action/innate/cult/create_rune/IsAvailable()
|
||||
if(!rune_type || cooldown > world.time)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/cult/create_rune/Activate()
|
||||
var/chosen_keyword
|
||||
if(!isturf(owner.loc))
|
||||
to_chat(owner, "<span class='warning>You need more space to scribe a rune!</span>")
|
||||
return
|
||||
if(initial(rune_type.req_keyword))
|
||||
chosen_keyword = stripped_input(owner, "Enter a keyword for the new rune.", "Words of Power")
|
||||
if(!chosen_keyword)
|
||||
return
|
||||
//the outer ring is always the same across all runes
|
||||
var/obj/effect/overlay/temp/cult/rune_spawn/R1 = new(owner.loc, scribe_time, rune_color)
|
||||
//the rest are not always the same, so we need types for em
|
||||
var/obj/effect/overlay/temp/cult/rune_spawn/R2
|
||||
if(rune_word_type)
|
||||
R2 = new rune_word_type(owner.loc, scribe_time, rune_color)
|
||||
var/obj/effect/overlay/temp/cult/rune_spawn/R3
|
||||
if(rune_innerring_type)
|
||||
R3 = new rune_innerring_type(owner.loc, scribe_time, rune_color)
|
||||
var/obj/effect/overlay/temp/cult/rune_spawn/R4
|
||||
if(rune_center_type)
|
||||
R4 = new rune_center_type(owner.loc, scribe_time, rune_color)
|
||||
|
||||
cooldown = base_cooldown + world.time
|
||||
owner.update_action_buttons_icon()
|
||||
addtimer(CALLBACK(owner, /mob.proc/update_action_buttons_icon), base_cooldown)
|
||||
var/list/health
|
||||
if(damage_interrupt && isliving(owner))
|
||||
var/mob/living/L = owner
|
||||
health = list("health" = L.health)
|
||||
if(do_after(owner, scribe_time, target = owner, extra_checks = CALLBACK(owner, /mob.proc/break_do_after_checks, health, action_interrupt)))
|
||||
var/obj/effect/rune/new_rune = new rune_type(owner.loc)
|
||||
new_rune.keyword = chosen_keyword
|
||||
else
|
||||
qdel(R1)
|
||||
if(R2)
|
||||
qdel(R2)
|
||||
if(R3)
|
||||
qdel(R3)
|
||||
if(R4)
|
||||
qdel(R4)
|
||||
cooldown = 0
|
||||
owner.update_action_buttons_icon()
|
||||
|
||||
//teleport rune
|
||||
/datum/action/innate/cult/create_rune/tele
|
||||
button_icon_state = "telerune"
|
||||
rune_type = /obj/effect/rune/teleport
|
||||
rune_word_type = /obj/effect/overlay/temp/cult/rune_spawn/rune2
|
||||
rune_innerring_type = /obj/effect/overlay/temp/cult/rune_spawn/rune2/inner
|
||||
rune_center_type = /obj/effect/overlay/temp/cult/rune_spawn/rune2/center
|
||||
rune_color = RUNE_COLOR_TELEPORT
|
||||
@@ -24,7 +24,7 @@ To draw a rune, use an arcane tome.
|
||||
icon_state = "1"
|
||||
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
layer = LOW_OBJ_LAYER
|
||||
color = "#FF0000"
|
||||
color = RUNE_COLOR_RED
|
||||
|
||||
var/invocation = "Aiy ele-mayo!" //This is said by cultists when the rune is invoked.
|
||||
var/req_cultists = 1 //The amount of cultists required around the rune to invoke it. If only 1, any cultist can invoke it.
|
||||
@@ -148,8 +148,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
|
||||
/obj/effect/rune/proc/fail_invoke()
|
||||
//This proc contains the effects of a rune if it is not invoked correctly, through either invalid wording or not enough cultists. By default, it's just a basic fizzle.
|
||||
visible_message("<span class='warning'>The markings pulse with a \
|
||||
small flash of red light, then fall dark.</span>")
|
||||
visible_message("<span class='warning'>The markings pulse with a small flash of red light, then fall dark.</span>")
|
||||
var/oldcolor = color
|
||||
color = rgb(255, 0, 0)
|
||||
animate(src, color = oldcolor, time = 5)
|
||||
@@ -192,7 +191,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
cultist_desc = "transforms paper into powerful magic talismans."
|
||||
invocation = "H'drak v'loso, mir'kanas verbot!"
|
||||
icon_state = "3"
|
||||
color = "#0000FF"
|
||||
color = RUNE_COLOR_TALISMAN
|
||||
|
||||
/obj/effect/rune/imbue/invoke(var/list/invokers)
|
||||
var/mob/living/user = invokers[1] //the first invoker is always the user
|
||||
@@ -247,7 +246,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
cultist_desc = "warps everything above it to another chosen teleport rune."
|
||||
invocation = "Sas'so c'arta forbici!"
|
||||
icon_state = "2"
|
||||
color = "#551A8B"
|
||||
color = RUNE_COLOR_TELEPORT
|
||||
req_keyword = TRUE
|
||||
var/listkey
|
||||
|
||||
@@ -307,10 +306,11 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
A.forceMove(target)
|
||||
if(movedsomething)
|
||||
..()
|
||||
visible_message("<span class='warning'>There is a sharp crack of inrushing air, and everything above the rune disappears!</span>")
|
||||
visible_message("<span class='warning'>There is a sharp crack of inrushing air, and everything above the rune disappears!</span>", null, "<i>You hear a sharp crack.</i>")
|
||||
to_chat(user, "<span class='cult'>You[moveuserlater ? "r vision blurs, and you suddenly appear somewhere else":" send everything above the rune away"].</span>")
|
||||
if(moveuserlater)
|
||||
user.forceMove(target)
|
||||
target.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
|
||||
else
|
||||
fail_invoke()
|
||||
|
||||
@@ -322,7 +322,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
req_cultists_text = "2 for conversion, 3 for living sacrifices and sacrifice targets."
|
||||
invocation = "Mah'weyh pleggh at e'ntrath!"
|
||||
icon_state = "3"
|
||||
color = "#FFFFFF"
|
||||
color = RUNE_COLOR_OFFER
|
||||
req_cultists = 1
|
||||
allow_excess_invokers = TRUE
|
||||
rune_in_use = FALSE
|
||||
@@ -345,7 +345,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
rune_in_use = TRUE
|
||||
visible_message("<span class='warning'>[src] pulses blood red!</span>")
|
||||
var/oldcolor = color
|
||||
color = "#7D1717"
|
||||
color = RUNE_COLOR_DARKRED
|
||||
var/mob/living/L = pick(myriad_targets)
|
||||
var/is_clock = is_servant_of_ratvar(L)
|
||||
var/is_convertable = is_convertable_to_cult(L)
|
||||
@@ -442,7 +442,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
invocation = "TOK-LYR RQA-NAP G'OLT-ULOFT!!"
|
||||
req_cultists = 9
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
color = "#7D1717"
|
||||
color = RUNE_COLOR_DARKRED
|
||||
icon_state = "rune_large"
|
||||
pixel_x = -32 //So the big ol' 96x96 sprite shows up right
|
||||
pixel_y = -32
|
||||
@@ -479,9 +479,9 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
var/turf/T = get_turf(src)
|
||||
sleep(40)
|
||||
if(src)
|
||||
color = "#FF0000"
|
||||
color = RUNE_COLOR_RED
|
||||
SSticker.mode.eldergod = FALSE
|
||||
new /obj/singularity/narsie/large(T) //Causes Nar-Sie to spawn even if the rune has been removed
|
||||
new /obj/singularity/narsie/large/cult(T) //Causes Nar-Sie to spawn even if the rune has been removed
|
||||
|
||||
/obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal.
|
||||
if((istype(I, /obj/item/weapon/tome) && iscultist(user)))
|
||||
@@ -502,7 +502,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
cultist_desc = "requires the corpse of a cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be revived."
|
||||
invocation = "Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!" //Depends on the name of the user - see below
|
||||
icon_state = "1"
|
||||
color = "#C80000"
|
||||
color = RUNE_COLOR_MEDIUMRED
|
||||
var/static/revives_used = 0
|
||||
|
||||
/obj/effect/rune/raise_dead/examine(mob/user)
|
||||
@@ -593,7 +593,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
invocation = "Ta'gh fara'qha fel d'amar det!"
|
||||
icon_state = "5"
|
||||
allow_excess_invokers = 1
|
||||
color = "#4D94FF"
|
||||
color = RUNE_COLOR_EMP
|
||||
|
||||
/obj/effect/rune/emp/invoke(var/list/invokers)
|
||||
var/turf/E = get_turf(src)
|
||||
@@ -623,7 +623,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
cultist_desc = "severs the link between one's spirit and body. This effect is taxing and one's physical body will take damage while this is active."
|
||||
invocation = "Fwe'sh mah erl nyag r'ya!"
|
||||
icon_state = "7"
|
||||
color = "#7D1717"
|
||||
color = RUNE_COLOR_DARKRED
|
||||
rune_in_use = 0 //One at a time, please!
|
||||
construct_invoke = 0
|
||||
var/mob/living/affecting = null
|
||||
@@ -649,9 +649,9 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
var/mob/living/user = invokers[1]
|
||||
..()
|
||||
var/turf/T = get_turf(src)
|
||||
rune_in_use = 1
|
||||
rune_in_use = TRUE
|
||||
affecting = user
|
||||
user.color = "#7D1717"
|
||||
user.add_atom_colour(RUNE_COLOR_DARKRED, ADMIN_COLOUR_PRIORITY)
|
||||
user.visible_message("<span class='warning'>[user] freezes statue-still, glowing an unearthly red.</span>", \
|
||||
"<span class='cult'>You see what lies beyond. All is revealed. While this is a wondrous experience, your physical form will waste away in this state. Hurry...</span>")
|
||||
user.ghostize(1)
|
||||
@@ -659,7 +659,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
if(!affecting)
|
||||
visible_message("<span class='warning'>[src] pulses gently before falling dark.</span>")
|
||||
affecting = null //In case it's assigned to a number or something
|
||||
rune_in_use = 0
|
||||
rune_in_use = FALSE
|
||||
return
|
||||
affecting.apply_damage(0.1, BRUTE)
|
||||
if(!(user in T))
|
||||
@@ -669,9 +669,9 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
if(user.key)
|
||||
user.visible_message("<span class='warning'>[user] slowly relaxes, the glow around [user.p_them()] dimming.</span>", \
|
||||
"<span class='danger'>You are re-united with your physical form. [src] releases its hold over you.</span>")
|
||||
user.color = initial(user.color)
|
||||
user.remove_atom_colour(ADMIN_COLOUR_PRIORITY, RUNE_COLOR_DARKRED)
|
||||
user.Weaken(3)
|
||||
rune_in_use = 0
|
||||
rune_in_use = FALSE
|
||||
affecting = null
|
||||
return
|
||||
if(user.stat == UNCONSCIOUS)
|
||||
@@ -679,14 +679,14 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
var/mob/dead/observer/G = user.get_ghost()
|
||||
to_chat(G, "<span class='cultitalic'>You feel the link between you and your body weakening... you must hurry!</span>")
|
||||
if(user.stat == DEAD)
|
||||
user.color = initial(user.color)
|
||||
rune_in_use = 0
|
||||
user.remove_atom_colour(ADMIN_COLOUR_PRIORITY, RUNE_COLOR_DARKRED)
|
||||
rune_in_use = FALSE
|
||||
affecting = null
|
||||
var/mob/dead/observer/G = user.get_ghost()
|
||||
to_chat(G, "<span class='cultitalic'><b>You suddenly feel your physical form pass on. [src]'s exertion has killed you!</b></span>")
|
||||
return
|
||||
sleep(1)
|
||||
rune_in_use = 0
|
||||
rune_in_use = FALSE
|
||||
|
||||
//Rite of the Corporeal Shield: When invoked, becomes solid and cannot be passed. Invoke again to undo.
|
||||
/obj/effect/rune/wall
|
||||
@@ -694,7 +694,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
cultist_desc = "when invoked, makes a temporary invisible wall to block passage. Can be invoked again to reverse this."
|
||||
invocation = "Khari'd! Eske'te tannin!"
|
||||
icon_state = "1"
|
||||
color = "#C80000"
|
||||
color = RUNE_COLOR_MEDIUMRED
|
||||
CanAtmosPass = ATMOS_PASS_DENSITY
|
||||
var/density_timer
|
||||
var/recharging = FALSE
|
||||
@@ -753,7 +753,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
|
||||
/obj/effect/rune/wall/proc/recharge()
|
||||
recharging = FALSE
|
||||
add_atom_colour("#C80000", FIXED_COLOUR_PRIORITY)
|
||||
add_atom_colour(RUNE_COLOR_MEDIUMRED, FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/obj/effect/rune/wall/proc/update_state()
|
||||
deltimer(density_timer)
|
||||
@@ -764,10 +764,10 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
shimmer.alpha = 60
|
||||
shimmer.color = "#701414"
|
||||
add_overlay(shimmer)
|
||||
add_atom_colour("#FF0000", FIXED_COLOUR_PRIORITY)
|
||||
add_atom_colour(RUNE_COLOR_RED, FIXED_COLOUR_PRIORITY)
|
||||
else
|
||||
cut_overlays()
|
||||
add_atom_colour("#C80000", FIXED_COLOUR_PRIORITY)
|
||||
add_atom_colour(RUNE_COLOR_MEDIUMRED, FIXED_COLOUR_PRIORITY)
|
||||
|
||||
//Rite of Joined Souls: Summons a single cultist.
|
||||
/obj/effect/rune/summon
|
||||
@@ -777,7 +777,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
req_cultists = 2
|
||||
allow_excess_invokers = 1
|
||||
icon_state = "5"
|
||||
color = "#00FF00"
|
||||
color = RUNE_COLOR_SUMMON
|
||||
|
||||
/obj/effect/rune/summon/invoke(var/list/invokers)
|
||||
var/mob/living/user = invokers[1]
|
||||
@@ -822,7 +822,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
cultist_desc = "boils the blood of non-believers who can see the rune, rapidly dealing extreme amounts of damage. Requires 3 invokers."
|
||||
invocation = "Dedo ol'btoh!"
|
||||
icon_state = "4"
|
||||
color = "#C80000"
|
||||
color = RUNE_COLOR_MEDIUMRED
|
||||
light_color = LIGHT_COLOR_LAVA
|
||||
req_cultists = 3
|
||||
construct_invoke = 0
|
||||
@@ -889,7 +889,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
invocation = "Gal'h'rfikk harfrandid mud'gib!" //how the fuck do you pronounce this
|
||||
icon_state = "6"
|
||||
construct_invoke = 0
|
||||
color = "#C80000"
|
||||
color = RUNE_COLOR_MEDIUMRED
|
||||
var/ghost_limit = 5
|
||||
var/ghosts = 0
|
||||
|
||||
@@ -962,4 +962,4 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
"<span class='cultlarge'>Your link to the world fades. Your form breaks apart.</span>")
|
||||
for(var/obj/I in new_human)
|
||||
new_human.dropItemToGround(I, TRUE)
|
||||
new_human.dust()
|
||||
new_human.dust()
|
||||
@@ -49,7 +49,7 @@
|
||||
/obj/item/weapon/paper/talisman/teleport
|
||||
cultist_name = "Talisman of Teleportation"
|
||||
cultist_desc = "A single-use talisman that will teleport a user to a random rune of the same keyword."
|
||||
color = "#551A8B" // purple
|
||||
color = RUNE_COLOR_TELEPORT
|
||||
invocation = "Sas'so c'arta forbici!"
|
||||
health_cost = 5
|
||||
creation_time = 80
|
||||
|
||||
@@ -210,13 +210,16 @@
|
||||
var/datum/action/innate/seek_master/SM = new()
|
||||
SM.Grant(newstruct)
|
||||
newstruct.key = target.key
|
||||
var/obj/screen/alert/bloodsense/BS
|
||||
if(newstruct.mind && ((stoner && iscultist(stoner)) || cultoverride) && SSticker && SSticker.mode)
|
||||
SSticker.mode.add_cultist(newstruct.mind, 0)
|
||||
BS = newstruct.alerts.Find("bloodsense")
|
||||
if(iscultist(stoner) || cultoverride)
|
||||
to_chat(newstruct, "<b>You are still bound to serve the cult[stoner ? " and [stoner]":""], follow their orders and help them complete their goals at all costs.</b>")
|
||||
else if(stoner)
|
||||
to_chat(newstruct, "<b>You are still bound to serve your creator, [stoner], follow their orders and help them complete their goals at all costs.</b>")
|
||||
var/obj/screen/alert/bloodsense/BS = newstruct.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
|
||||
BS = newstruct.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
|
||||
if(BS)
|
||||
BS.Cviewer = newstruct
|
||||
newstruct.cancel_camera()
|
||||
|
||||
|
||||
@@ -25,9 +25,6 @@
|
||||
if(istype(I, /obj/item/stack/spacecash))
|
||||
var/obj/item/stack/spacecash/C = I
|
||||
value = C.value * C.amount
|
||||
if(istype(I, /obj/item/weapon/coin))
|
||||
var/obj/item/weapon/coin/C = I
|
||||
value = C.value
|
||||
if(value)
|
||||
SSshuttle.points += value
|
||||
to_chat(user, "<span class='notice'>You deposit [I]. The station now has [SSshuttle.points] credits.</span>")
|
||||
|
||||
@@ -43,7 +43,8 @@
|
||||
/obj/item/weapon/grenade/chem_grenade/glitter/pink = 1,
|
||||
/obj/item/weapon/grenade/chem_grenade/glitter/blue = 1,
|
||||
/obj/item/weapon/grenade/chem_grenade/glitter/white = 1,
|
||||
/obj/item/toy/eightball = 2)
|
||||
/obj/item/toy/eightball = 2,
|
||||
/obj/item/toy/windupToolbox = 2)
|
||||
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
|
||||
|
||||
@@ -12,6 +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
|
||||
|
||||
var/secondsElectrified = 0
|
||||
var/shockedby = list()
|
||||
|
||||
@@ -26,8 +26,6 @@ Possible to do for anyone motivated enough:
|
||||
|
||||
#define HOLOPAD_PASSIVE_POWER_USAGE 1
|
||||
#define HOLOGRAM_POWER_USAGE 2
|
||||
|
||||
GLOBAL_LIST_EMPTY(holopads)
|
||||
#define HOLOPAD_MODE RANGE_BASED
|
||||
|
||||
/obj/machinery/holopad
|
||||
@@ -295,7 +293,7 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
Hologram.Impersonation = user
|
||||
|
||||
|
||||
Hologram.language_holder = user.get_language_holder()
|
||||
Hologram.copy_known_languages_from(user,replace = TRUE)
|
||||
|
||||
Hologram.mouse_opacity = 0//So you can't click on it.
|
||||
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
var/icon_deny //Icon_state when vending!
|
||||
var/seconds_electrified = 0 //Shock customers like an airlock.
|
||||
var/shoot_inventory = 0 //Fire items at customers! We're broken!
|
||||
var/shoot_inventory_chance = 2
|
||||
var/shut_up = 0 //Stop spouting those godawful pitches!
|
||||
var/extended_inventory = 0 //can we access the hidden inventory?
|
||||
var/scan_id = 1
|
||||
@@ -561,7 +562,7 @@
|
||||
speak(slogan)
|
||||
last_slogan = world.time
|
||||
|
||||
if(shoot_inventory && prob(2))
|
||||
if(shoot_inventory && prob(shoot_inventory_chance))
|
||||
throw_item()
|
||||
|
||||
|
||||
@@ -592,7 +593,7 @@
|
||||
if(!target)
|
||||
return 0
|
||||
|
||||
for(var/datum/data/vending_product/R in product_records)
|
||||
for(var/datum/data/vending_product/R in shuffle(product_records))
|
||||
if(R.amount <= 0) //Try to use a record that actually has something to dump.
|
||||
continue
|
||||
var/dump_path = R.product_path
|
||||
@@ -605,19 +606,22 @@
|
||||
if(!throw_item)
|
||||
return 0
|
||||
|
||||
pre_throw(throw_item)
|
||||
|
||||
throw_item.throw_at(target, 16, 3)
|
||||
visible_message("<span class='danger'>[src] launches [throw_item] at [target]!</span>")
|
||||
return 1
|
||||
|
||||
/obj/machinery/vending/proc/pre_throw(obj/item/I)
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/vending/proc/shock(mob/user, prb)
|
||||
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
|
||||
return FALSE
|
||||
if(!prob(prb))
|
||||
return FALSE
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
do_sparks(5, TRUE, src)
|
||||
var/tmp/check_range = TRUE
|
||||
if(electrocute_mob(user, get_area(src), src, 0.7, check_range))
|
||||
return TRUE
|
||||
@@ -864,6 +868,11 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
|
||||
/obj/item/weapon/storage/fancy/cigarettes/cigars = 1, /obj/item/weapon/storage/fancy/cigarettes/cigars/havana = 1, /obj/item/weapon/storage/fancy/cigarettes/cigars/cohiba = 1)
|
||||
refill_canister = /obj/item/weapon/vending_refill/cigarette
|
||||
|
||||
/obj/machinery/vending/cigarette/pre_throw(obj/item/I)
|
||||
if(istype(I, /obj/item/weapon/lighter))
|
||||
var/obj/item/weapon/lighter/L = I
|
||||
L.set_lit(TRUE)
|
||||
|
||||
/obj/machinery/vending/medical
|
||||
name = "\improper NanoMed Plus"
|
||||
desc = "Medical drug dispenser."
|
||||
@@ -919,6 +928,15 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
|
||||
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/obj/machinery/vending/security/pre_throw(obj/item/I)
|
||||
if(istype(I, /obj/item/weapon/grenade))
|
||||
var/obj/item/weapon/grenade/G = I
|
||||
G.preprime()
|
||||
else if(istype(I, /obj/item/device/flashlight))
|
||||
var/obj/item/device/flashlight/F = I
|
||||
F.on = TRUE
|
||||
F.update_brightness()
|
||||
|
||||
/obj/machinery/vending/hydronutrients
|
||||
name = "\improper NutriMax"
|
||||
desc = "A plant nutrients vendor."
|
||||
|
||||
@@ -18,620 +18,6 @@
|
||||
..()
|
||||
QDEL_IN(src, 10)
|
||||
|
||||
/obj/effect/overlay/temp
|
||||
icon_state = "nothing"
|
||||
anchored = 1
|
||||
layer = ABOVE_MOB_LAYER
|
||||
mouse_opacity = 0
|
||||
var/duration = 10 //in deciseconds
|
||||
var/randomdir = TRUE
|
||||
var/timerid
|
||||
|
||||
/obj/effect/overlay/temp/Destroy()
|
||||
. = ..()
|
||||
deltimer(timerid)
|
||||
|
||||
/obj/effect/overlay/temp/Initialize()
|
||||
. = ..()
|
||||
if(randomdir)
|
||||
setDir(pick(GLOB.cardinal))
|
||||
|
||||
timerid = QDEL_IN(src, duration)
|
||||
|
||||
/obj/effect/overlay/temp/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting
|
||||
randomdir = FALSE
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/Initialize(mapload, set_dir)
|
||||
if(set_dir)
|
||||
setDir(set_dir)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/bloodsplatter
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
duration = 5
|
||||
randomdir = FALSE
|
||||
layer = BELOW_MOB_LAYER
|
||||
var/splatter_type = "splatter"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/bloodsplatter/Initialize(mapload, set_dir)
|
||||
if(set_dir in GLOB.diagonals)
|
||||
icon_state = "[splatter_type][pick(1, 2, 6)]"
|
||||
else
|
||||
icon_state = "[splatter_type][pick(3, 4, 5)]"
|
||||
. = ..()
|
||||
var/target_pixel_x = 0
|
||||
var/target_pixel_y = 0
|
||||
switch(set_dir)
|
||||
if(NORTH)
|
||||
target_pixel_y = 16
|
||||
if(SOUTH)
|
||||
target_pixel_y = -16
|
||||
layer = ABOVE_MOB_LAYER
|
||||
if(EAST)
|
||||
target_pixel_x = 16
|
||||
if(WEST)
|
||||
target_pixel_x = -16
|
||||
if(NORTHEAST)
|
||||
target_pixel_x = 16
|
||||
target_pixel_y = 16
|
||||
if(NORTHWEST)
|
||||
target_pixel_x = -16
|
||||
target_pixel_y = 16
|
||||
if(SOUTHEAST)
|
||||
target_pixel_x = 16
|
||||
target_pixel_y = -16
|
||||
layer = ABOVE_MOB_LAYER
|
||||
if(SOUTHWEST)
|
||||
target_pixel_x = -16
|
||||
target_pixel_y = -16
|
||||
layer = ABOVE_MOB_LAYER
|
||||
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/bloodsplatter/xenosplatter
|
||||
splatter_type = "xsplatter"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/speedbike_trail
|
||||
name = "speedbike trails"
|
||||
icon_state = "ion_fade"
|
||||
layer = BELOW_MOB_LAYER
|
||||
duration = 10
|
||||
randomdir = 0
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/firing_effect
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "firing_effect"
|
||||
duration = 2
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/firing_effect/setDir(newdir)
|
||||
switch(newdir)
|
||||
if(NORTH)
|
||||
layer = BELOW_MOB_LAYER
|
||||
pixel_x = rand(-3,3)
|
||||
pixel_y = rand(4,6)
|
||||
if(SOUTH)
|
||||
pixel_x = rand(-3,3)
|
||||
pixel_y = rand(-1,1)
|
||||
else
|
||||
pixel_x = rand(-1,1)
|
||||
pixel_y = rand(-1,1)
|
||||
..()
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/firing_effect/energy
|
||||
icon_state = "firing_effect_energy"
|
||||
duration = 3
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/firing_effect/magic
|
||||
icon_state = "shieldsparkles"
|
||||
duration = 3
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/ninja
|
||||
name = "ninja shadow"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "uncloak"
|
||||
duration = 9
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/ninja/cloak
|
||||
icon_state = "cloak"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/ninja/shadow
|
||||
icon_state = "shadow"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/ninja/phase
|
||||
name = "ninja energy"
|
||||
icon_state = "phasein"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/ninja/phase/out
|
||||
icon_state = "phaseout"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/wraith
|
||||
name = "blood"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "phase_shift2"
|
||||
duration = 12
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/wraith/out
|
||||
icon_state = "phase_shift"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/tailsweep
|
||||
icon_state = "tailsweep"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/wizard
|
||||
name = "water"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "reappear"
|
||||
duration = 5
|
||||
|
||||
/obj/effect/overlay/temp/wizard/out
|
||||
icon_state = "liquify"
|
||||
duration = 12
|
||||
|
||||
/obj/effect/overlay/temp/monkeyify
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "h2monkey"
|
||||
duration = 22
|
||||
|
||||
/obj/effect/overlay/temp/monkeyify/humanify
|
||||
icon_state = "monkey2h"
|
||||
|
||||
/obj/effect/overlay/temp/borgflash
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "blspell"
|
||||
duration = 5
|
||||
|
||||
/obj/effect/overlay/temp/guardian
|
||||
randomdir = 0
|
||||
|
||||
/obj/effect/overlay/temp/guardian/phase
|
||||
duration = 5
|
||||
icon_state = "phasein"
|
||||
|
||||
/obj/effect/overlay/temp/guardian/phase/out
|
||||
icon_state = "phaseout"
|
||||
|
||||
/obj/effect/overlay/temp/decoy
|
||||
desc = "It's a decoy!"
|
||||
duration = 15
|
||||
|
||||
/obj/effect/overlay/temp/decoy/Initialize(mapload, atom/mimiced_atom)
|
||||
. = ..()
|
||||
alpha = initial(alpha)
|
||||
if(mimiced_atom)
|
||||
name = mimiced_atom.name
|
||||
appearance = mimiced_atom.appearance
|
||||
setDir(mimiced_atom.dir)
|
||||
mouse_opacity = 0
|
||||
|
||||
/obj/effect/overlay/temp/decoy/fading/Initialize(mapload, atom/mimiced_atom)
|
||||
. = ..()
|
||||
animate(src, alpha = 0, time = duration)
|
||||
|
||||
/obj/effect/overlay/temp/decoy/fading/fivesecond
|
||||
duration = 50
|
||||
|
||||
/obj/effect/overlay/temp/small_smoke
|
||||
icon_state = "smoke"
|
||||
duration = 50
|
||||
|
||||
/obj/effect/overlay/temp/fire
|
||||
icon = 'icons/effects/fire.dmi'
|
||||
icon_state = "3"
|
||||
duration = 20
|
||||
|
||||
/obj/effect/overlay/temp/cult
|
||||
randomdir = 0
|
||||
duration = 10
|
||||
|
||||
/obj/effect/overlay/temp/cult/sparks
|
||||
randomdir = 1
|
||||
name = "blood sparks"
|
||||
icon_state = "bloodsparkles"
|
||||
|
||||
/obj/effect/overlay/temp/cult/blood // The traditional teleport
|
||||
name = "blood jaunt"
|
||||
duration = 12
|
||||
icon_state = "bloodin"
|
||||
|
||||
/obj/effect/overlay/temp/cult/blood/out
|
||||
icon_state = "bloodout"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/cult/phase // The veil shifter teleport
|
||||
name = "phase glow"
|
||||
duration = 7
|
||||
icon_state = "cultin"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/cult/phase/out
|
||||
icon_state = "cultout"
|
||||
|
||||
/obj/effect/overlay/temp/cult/sac
|
||||
name = "maw of Nar-Sie"
|
||||
icon_state = "sacconsume"
|
||||
|
||||
/obj/effect/overlay/temp/cult/door
|
||||
name = "unholy glow"
|
||||
icon_state = "doorglow"
|
||||
layer = CLOSED_FIREDOOR_LAYER //above closed doors
|
||||
|
||||
/obj/effect/overlay/temp/cult/door/unruned
|
||||
icon_state = "unruneddoorglow"
|
||||
|
||||
/obj/effect/overlay/temp/cult/turf
|
||||
name = "unholy glow"
|
||||
icon_state = "wallglow"
|
||||
layer = ABOVE_NORMAL_TURF_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/cult/turf/floor
|
||||
icon_state = "floorglow"
|
||||
duration = 5
|
||||
|
||||
|
||||
/obj/effect/overlay/temp/ratvar
|
||||
name = "ratvar's light"
|
||||
icon = 'icons/effects/clockwork_effects.dmi'
|
||||
duration = 8
|
||||
randomdir = 0
|
||||
layer = ABOVE_NORMAL_TURF_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/door
|
||||
icon_state = "ratvardoorglow"
|
||||
layer = CLOSED_DOOR_LAYER //above closed doors
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/door/window
|
||||
icon_state = "ratvarwindoorglow"
|
||||
layer = ABOVE_WINDOW_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam
|
||||
icon_state = "ratvarbeamglow"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam/door
|
||||
layer = CLOSED_DOOR_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam/grille
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam/itemconsume
|
||||
layer = HIGH_OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam/falsewall
|
||||
layer = OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam/catwalk
|
||||
layer = LATTICE_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/wall
|
||||
icon_state = "ratvarwallglow"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/wall/false
|
||||
layer = OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/floor
|
||||
icon_state = "ratvarfloorglow"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/floor/catwalk
|
||||
layer = LATTICE_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/window
|
||||
icon_state = "ratvarwindowglow"
|
||||
layer = ABOVE_OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/window/single
|
||||
icon_state = "ratvarwindowglow_s"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/gear
|
||||
icon_state = "ratvargearglow"
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/grille
|
||||
icon_state = "ratvargrilleglow"
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/grille/broken
|
||||
icon_state = "ratvarbrokengrilleglow"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/mending_mantra
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 20
|
||||
alpha = 200
|
||||
icon_state = "mending_mantra"
|
||||
light_range = 1.5
|
||||
light_color = "#1E8CE1"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/mending_mantra/Initialize(mapload)
|
||||
. = ..()
|
||||
transform = matrix()*2
|
||||
var/matrix/M = transform
|
||||
M.Turn(90)
|
||||
animate(src, alpha = 20, time = duration, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
|
||||
animate(src, transform = M, time = duration, flags = ANIMATION_PARALLEL)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit
|
||||
name = "volt blast"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 5
|
||||
icon_state = "volt_hit"
|
||||
light_range = 1.5
|
||||
light_power = 2
|
||||
light_color = LIGHT_COLOR_ORANGE
|
||||
var/mob/user
|
||||
var/damage = 20
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit/Initialize(mapload, caster, multiplier)
|
||||
if(multiplier)
|
||||
damage *= multiplier
|
||||
duration = max(round(damage * 0.2), 1)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit/true/Initialize(mapload, caster, multiplier)
|
||||
. = ..()
|
||||
user = caster
|
||||
if(user)
|
||||
var/matrix/M = new
|
||||
M.Turn(Get_Angle(src, user))
|
||||
transform = M
|
||||
INVOKE_ASYNC(src, .proc/volthit)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit/proc/volthit()
|
||||
if(user)
|
||||
Beam(get_turf(user), "volt_ray", time=duration, maxdistance=8, beam_type=/obj/effect/ebeam/volt_ray)
|
||||
var/hit_amount = 0
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/living/L in T)
|
||||
if(is_servant_of_ratvar(L))
|
||||
continue
|
||||
var/obj/item/I = L.null_rod_check()
|
||||
if(I)
|
||||
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
|
||||
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
|
||||
continue
|
||||
L.visible_message("<span class='warning'>[L] is struck by a [name]!</span>", "<span class='userdanger'>You're struck by a [name]!</span>")
|
||||
L.apply_damage(damage, BURN, "chest", L.run_armor_check("chest", "laser", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 0, "Your armor was penetrated by [src]!"))
|
||||
add_logs(user, L, "struck with a volt blast")
|
||||
hit_amount++
|
||||
for(var/obj/mecha/M in T)
|
||||
if(M.occupant)
|
||||
if(is_servant_of_ratvar(M.occupant))
|
||||
continue
|
||||
to_chat(M.occupant, "<span class='userdanger'>Your [M.name] is struck by a [name]!</span>")
|
||||
M.visible_message("<span class='warning'>[M] is struck by a [name]!</span>")
|
||||
M.take_damage(damage, BURN, 0, 0)
|
||||
hit_amount++
|
||||
if(hit_amount)
|
||||
playsound(src, 'sound/machines/defib_zap.ogg', damage*hit_amount, 1, -1)
|
||||
else
|
||||
playsound(src, "sparks", 50, 1)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/ocular_warden
|
||||
name = "warden's gaze"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
icon_state = "warden_gaze"
|
||||
duration = 3
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/ocular_warden/Initialize()
|
||||
. = ..()
|
||||
pixel_x = rand(-8, 8)
|
||||
pixel_y = rand(-10, 10)
|
||||
animate(src, alpha = 0, time = 3, easing = EASE_OUT)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/spearbreak
|
||||
icon = 'icons/effects/64x64.dmi'
|
||||
icon_state = "ratvarspearbreak"
|
||||
layer = BELOW_MOB_LAYER
|
||||
pixel_y = -16
|
||||
pixel_x = -16
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/geis_binding
|
||||
icon_state = "geisbinding"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/geis_binding/top
|
||||
icon_state = "geisbinding_top"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component
|
||||
icon = 'icons/obj/clockwork_objects.dmi'
|
||||
icon_state = "belligerent_eye"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 10
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component/Initialize()
|
||||
. = ..()
|
||||
transform = matrix()*0.75
|
||||
pixel_x = rand(-10, 10)
|
||||
pixel_y = rand(-10, -2)
|
||||
animate(src, pixel_y = pixel_y + 10, alpha = 50, time = 10, easing = EASE_OUT)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component/cogwheel
|
||||
icon_state = "vanguard_cogwheel"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component/capacitor
|
||||
icon_state = "geis_capacitor"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component/alloy
|
||||
icon_state = "replicant_alloy"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component/ansible
|
||||
icon_state = "hierophant_ansible"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/sigil
|
||||
name = "glowing circle"
|
||||
icon_state = "sigildull"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/sigil/transgression
|
||||
color = "#FAE48C"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 70
|
||||
light_range = 5
|
||||
light_power = 2
|
||||
light_color = "#FAE48C"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/sigil/transgression/Initialize()
|
||||
. = ..()
|
||||
var/oldtransform = transform
|
||||
animate(src, transform = matrix()*2, time = 5)
|
||||
animate(transform = oldtransform, alpha = 0, time = 65)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/sigil/vitality
|
||||
color = "#1E8CE1"
|
||||
icon_state = "sigilactivepulse"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
light_range = 1.4
|
||||
light_power = 0.5
|
||||
light_color = "#1E8CE1"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/sigil/accession
|
||||
color = "#AF0AAF"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 70
|
||||
icon_state = "sigilactiveoverlay"
|
||||
alpha = 0
|
||||
|
||||
|
||||
/obj/effect/overlay/temp/revenant
|
||||
name = "spooky lights"
|
||||
icon_state = "purplesparkles"
|
||||
|
||||
/obj/effect/overlay/temp/revenant/cracks
|
||||
name = "glowing cracks"
|
||||
icon_state = "purplecrack"
|
||||
duration = 6
|
||||
|
||||
|
||||
/obj/effect/overlay/temp/gravpush
|
||||
name = "gravity wave"
|
||||
icon_state = "shieldsparkles"
|
||||
duration = 5
|
||||
|
||||
/obj/effect/overlay/temp/telekinesis
|
||||
name = "telekinetic force"
|
||||
icon_state = "empdisable"
|
||||
duration = 5
|
||||
|
||||
/obj/effect/overlay/temp/emp
|
||||
name = "emp sparks"
|
||||
icon_state = "empdisable"
|
||||
|
||||
/obj/effect/overlay/temp/emp/pulse
|
||||
name = "emp pulse"
|
||||
icon_state = "emppulse"
|
||||
duration = 8
|
||||
randomdir = 0
|
||||
|
||||
/obj/effect/overlay/temp/gib_animation
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
duration = 15
|
||||
|
||||
/obj/effect/overlay/temp/gib_animation/Initialize(mapload, gib_icon)
|
||||
icon_state = gib_icon // Needs to be before ..() so icon is correct
|
||||
. = ..()
|
||||
|
||||
/obj/effect/overlay/temp/gib_animation/ex_act(severity)
|
||||
return //so the overlay isn't deleted by the explosion that gibbed the mob.
|
||||
|
||||
/obj/effect/overlay/temp/gib_animation/animal
|
||||
icon = 'icons/mob/animal.dmi'
|
||||
|
||||
/obj/effect/overlay/temp/dust_animation
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
duration = 15
|
||||
|
||||
/obj/effect/overlay/temp/dust_animation/Initialize(mapload, dust_icon)
|
||||
icon_state = dust_icon // Before ..() so the correct icon is flick()'d
|
||||
. = ..()
|
||||
|
||||
/obj/effect/overlay/temp/mummy_animation
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "mummy_revive"
|
||||
duration = 20
|
||||
|
||||
/obj/effect/overlay/temp/heal //color is white by default, set to whatever is needed
|
||||
name = "healing glow"
|
||||
icon_state = "heal"
|
||||
duration = 15
|
||||
|
||||
/obj/effect/overlay/temp/heal/Initialize(mapload, colour)
|
||||
if(colour)
|
||||
color = colour
|
||||
. = ..()
|
||||
pixel_x = rand(-12, 12)
|
||||
pixel_y = rand(-9, 0)
|
||||
|
||||
/obj/effect/overlay/temp/kinetic_blast
|
||||
name = "kinetic explosion"
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "kinetic_blast"
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/explosion
|
||||
name = "explosion"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "explosion"
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
duration = 8
|
||||
|
||||
/obj/effect/overlay/temp/explosion/fast
|
||||
icon_state = "explosionfast"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/blob
|
||||
name = "blob"
|
||||
icon_state = "blob_attack"
|
||||
alpha = 140
|
||||
randomdir = 0
|
||||
duration = 6
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect
|
||||
icon_state = "impact_bullet"
|
||||
duration = 5
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/Initialize(mapload, atom/target, obj/item/projectile/P)
|
||||
if(target == P.original) //the projectile hit the target originally clicked
|
||||
pixel_x = P.p_x + target.pixel_x - 16 + rand(-4,4)
|
||||
pixel_y = P.p_y + target.pixel_y - 16 + rand(-4,4)
|
||||
else
|
||||
pixel_x = target.pixel_x + rand(-4,4)
|
||||
pixel_y = target.pixel_y + rand(-4,4)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/red_laser
|
||||
icon_state = "impact_laser"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/red_laser/wall
|
||||
icon_state = "impact_laser_wall"
|
||||
duration = 10
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/blue_laser
|
||||
icon_state = "impact_laser_blue"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/green_laser
|
||||
icon_state = "impact_laser_green"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/purple_laser
|
||||
icon_state = "impact_laser_purple"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/ion
|
||||
icon_state = "shieldsparkles"
|
||||
duration = 6
|
||||
|
||||
/obj/effect/overlay/temp/heart
|
||||
name = "heart"
|
||||
icon = 'icons/mob/animal.dmi'
|
||||
icon_state = "heart"
|
||||
duration = 25
|
||||
|
||||
/obj/effect/overlay/temp/heart/Initialize(mapload)
|
||||
. = ..()
|
||||
pixel_x = rand(-4,4)
|
||||
pixel_y = rand(-4,4)
|
||||
|
||||
animate(src, pixel_y = pixel_y + 32, alpha = 0, time = 25)
|
||||
|
||||
/obj/effect/overlay/palmtree_r
|
||||
name = "Palm tree"
|
||||
icon = 'icons/misc/beach2.dmi'
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
//temporary visual effects(/obj/effect/overlay/temp) used by clockcult stuff
|
||||
/obj/effect/overlay/temp/ratvar
|
||||
name = "ratvar's light"
|
||||
icon = 'icons/effects/clockwork_effects.dmi'
|
||||
duration = 8
|
||||
randomdir = 0
|
||||
layer = ABOVE_NORMAL_TURF_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/door
|
||||
icon_state = "ratvardoorglow"
|
||||
layer = CLOSED_DOOR_LAYER //above closed doors
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/door/window
|
||||
icon_state = "ratvarwindoorglow"
|
||||
layer = ABOVE_WINDOW_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam
|
||||
icon_state = "ratvarbeamglow"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam/door
|
||||
layer = CLOSED_DOOR_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam/grille
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam/itemconsume
|
||||
layer = HIGH_OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam/falsewall
|
||||
layer = OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/beam/catwalk
|
||||
layer = LATTICE_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/wall
|
||||
icon_state = "ratvarwallglow"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/wall/false
|
||||
layer = OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/floor
|
||||
icon_state = "ratvarfloorglow"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/floor/catwalk
|
||||
layer = LATTICE_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/window
|
||||
icon_state = "ratvarwindowglow"
|
||||
layer = ABOVE_OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/window/single
|
||||
icon_state = "ratvarwindowglow_s"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/gear
|
||||
icon_state = "ratvargearglow"
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/grille
|
||||
icon_state = "ratvargrilleglow"
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/grille/broken
|
||||
icon_state = "ratvarbrokengrilleglow"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/mending_mantra
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 20
|
||||
alpha = 200
|
||||
icon_state = "mending_mantra"
|
||||
light_range = 1.5
|
||||
light_color = "#1E8CE1"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/mending_mantra/Initialize(mapload)
|
||||
. = ..()
|
||||
transform = matrix()*2
|
||||
var/matrix/M = transform
|
||||
M.Turn(90)
|
||||
animate(src, alpha = 20, time = duration, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
|
||||
animate(src, transform = M, time = duration, flags = ANIMATION_PARALLEL)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit
|
||||
name = "volt blast"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 5
|
||||
icon_state = "volt_hit"
|
||||
light_range = 1.5
|
||||
light_power = 2
|
||||
light_color = LIGHT_COLOR_ORANGE
|
||||
var/mob/user
|
||||
var/damage = 20
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit/Initialize(mapload, caster, multiplier)
|
||||
if(multiplier)
|
||||
damage *= multiplier
|
||||
duration = max(round(damage * 0.2), 1)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit/true/Initialize(mapload, caster, multiplier)
|
||||
. = ..()
|
||||
user = caster
|
||||
if(user)
|
||||
var/matrix/M = new
|
||||
M.Turn(Get_Angle(src, user))
|
||||
transform = M
|
||||
INVOKE_ASYNC(src, .proc/volthit)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit/proc/volthit()
|
||||
if(user)
|
||||
Beam(get_turf(user), "volt_ray", time=duration, maxdistance=8, beam_type=/obj/effect/ebeam/volt_ray)
|
||||
var/hit_amount = 0
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/living/L in T)
|
||||
if(is_servant_of_ratvar(L))
|
||||
continue
|
||||
var/obj/item/I = L.null_rod_check()
|
||||
if(I)
|
||||
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
|
||||
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
|
||||
continue
|
||||
L.visible_message("<span class='warning'>[L] is struck by a [name]!</span>", "<span class='userdanger'>You're struck by a [name]!</span>")
|
||||
L.apply_damage(damage, BURN, "chest", L.run_armor_check("chest", "laser", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 0, "Your armor was penetrated by [src]!"))
|
||||
add_logs(user, L, "struck with a volt blast")
|
||||
hit_amount++
|
||||
for(var/obj/mecha/M in T)
|
||||
if(M.occupant)
|
||||
if(is_servant_of_ratvar(M.occupant))
|
||||
continue
|
||||
to_chat(M.occupant, "<span class='userdanger'>Your [M.name] is struck by a [name]!</span>")
|
||||
M.visible_message("<span class='warning'>[M] is struck by a [name]!</span>")
|
||||
M.take_damage(damage, BURN, 0, 0)
|
||||
hit_amount++
|
||||
if(hit_amount)
|
||||
playsound(src, 'sound/machines/defib_zap.ogg', damage*hit_amount, 1, -1)
|
||||
else
|
||||
playsound(src, "sparks", 50, 1)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/ocular_warden
|
||||
name = "warden's gaze"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
icon_state = "warden_gaze"
|
||||
duration = 3
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/ocular_warden/Initialize()
|
||||
. = ..()
|
||||
pixel_x = rand(-8, 8)
|
||||
pixel_y = rand(-10, 10)
|
||||
animate(src, alpha = 0, time = 3, easing = EASE_OUT)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/spearbreak
|
||||
icon = 'icons/effects/64x64.dmi'
|
||||
icon_state = "ratvarspearbreak"
|
||||
layer = BELOW_MOB_LAYER
|
||||
pixel_y = -16
|
||||
pixel_x = -16
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/geis_binding
|
||||
icon_state = "geisbinding"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/geis_binding/top
|
||||
icon_state = "geisbinding_top"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component
|
||||
icon = 'icons/obj/clockwork_objects.dmi'
|
||||
icon_state = "belligerent_eye"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 10
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component/Initialize()
|
||||
. = ..()
|
||||
transform = matrix()*0.75
|
||||
pixel_x = rand(-10, 10)
|
||||
pixel_y = rand(-10, -2)
|
||||
animate(src, pixel_y = pixel_y + 10, alpha = 50, time = 10, easing = EASE_OUT)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component/cogwheel
|
||||
icon_state = "vanguard_cogwheel"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component/capacitor
|
||||
icon_state = "geis_capacitor"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component/alloy
|
||||
icon_state = "replicant_alloy"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/component/ansible
|
||||
icon_state = "hierophant_ansible"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/sigil
|
||||
name = "glowing circle"
|
||||
icon_state = "sigildull"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/sigil/transgression
|
||||
color = "#FAE48C"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 70
|
||||
light_range = 5
|
||||
light_power = 2
|
||||
light_color = "#FAE48C"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/sigil/transgression/Initialize()
|
||||
. = ..()
|
||||
var/oldtransform = transform
|
||||
animate(src, transform = matrix()*2, time = 5)
|
||||
animate(transform = oldtransform, alpha = 0, time = 65)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/sigil/vitality
|
||||
color = "#1E8CE1"
|
||||
icon_state = "sigilactivepulse"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
light_range = 1.4
|
||||
light_power = 0.5
|
||||
light_color = "#1E8CE1"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/sigil/accession
|
||||
color = "#AF0AAF"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 70
|
||||
icon_state = "sigilactiveoverlay"
|
||||
alpha = 0
|
||||
@@ -0,0 +1,144 @@
|
||||
//temporary visual effects(/obj/effect/overlay/temp) used by cult stuff
|
||||
/obj/effect/overlay/temp/cult
|
||||
icon = 'icons/effects/cult_effects.dmi'
|
||||
randomdir = 0
|
||||
duration = 10
|
||||
|
||||
/obj/effect/overlay/temp/cult/sparks
|
||||
randomdir = 1
|
||||
name = "blood sparks"
|
||||
icon_state = "bloodsparkles"
|
||||
|
||||
/obj/effect/overlay/temp/cult/blood // The traditional teleport
|
||||
name = "blood jaunt"
|
||||
duration = 12
|
||||
icon_state = "bloodin"
|
||||
|
||||
/obj/effect/overlay/temp/cult/blood/out
|
||||
icon_state = "bloodout"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/cult/phase // The veil shifter teleport
|
||||
name = "phase glow"
|
||||
duration = 7
|
||||
icon_state = "cultin"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/cult/phase/out
|
||||
icon_state = "cultout"
|
||||
|
||||
/obj/effect/overlay/temp/cult/sac
|
||||
name = "maw of Nar-Sie"
|
||||
icon_state = "sacconsume"
|
||||
|
||||
/obj/effect/overlay/temp/cult/door
|
||||
name = "unholy glow"
|
||||
icon_state = "doorglow"
|
||||
layer = CLOSED_FIREDOOR_LAYER //above closed doors
|
||||
|
||||
/obj/effect/overlay/temp/cult/door/unruned
|
||||
icon_state = "unruneddoorglow"
|
||||
|
||||
/obj/effect/overlay/temp/cult/turf
|
||||
name = "unholy glow"
|
||||
icon_state = "wallglow"
|
||||
layer = ABOVE_NORMAL_TURF_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/cult/turf/floor
|
||||
icon_state = "floorglow"
|
||||
duration = 5
|
||||
|
||||
//visuals for runes being magically created
|
||||
/obj/effect/overlay/temp/cult/rune_spawn
|
||||
icon_state = "runeouter"
|
||||
alpha = 0
|
||||
var/turnedness = 179 //179 turns counterclockwise, 181 turns clockwise
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/Initialize(mapload, set_duration, set_color)
|
||||
if(isnum(set_duration))
|
||||
duration = set_duration
|
||||
if(set_color)
|
||||
add_atom_colour(set_color, FIXED_COLOUR_PRIORITY)
|
||||
. = ..()
|
||||
var/oldtransform = transform
|
||||
transform = matrix()*2
|
||||
var/matrix/M = transform
|
||||
M.Turn(turnedness)
|
||||
transform = M
|
||||
animate(src, alpha = 255, time = duration, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
|
||||
animate(src, transform = oldtransform, time = duration, flags = ANIMATION_PARALLEL)
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune1
|
||||
icon_state = "rune1words"
|
||||
turnedness = 181
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune1/inner
|
||||
icon_state = "rune1inner"
|
||||
turnedness = 179
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune1/center
|
||||
icon_state = "rune1center"
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune2
|
||||
icon_state = "rune2words"
|
||||
turnedness = 181
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune2/inner
|
||||
icon_state = "rune2inner"
|
||||
turnedness = 179
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune2/center
|
||||
icon_state = "rune2center"
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune3
|
||||
icon_state = "rune3words"
|
||||
turnedness = 181
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune3/inner
|
||||
icon_state = "rune3inner"
|
||||
turnedness = 179
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune3/center
|
||||
icon_state = "rune3center"
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune4
|
||||
icon_state = "rune4words"
|
||||
turnedness = 181
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune4/inner
|
||||
icon_state = "rune4inner"
|
||||
turnedness = 179
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune4/center
|
||||
icon_state = "rune4center"
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune5
|
||||
icon_state = "rune5words"
|
||||
turnedness = 181
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune5/inner
|
||||
icon_state = "rune5inner"
|
||||
turnedness = 179
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune5/center
|
||||
icon_state = "rune5center"
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune6
|
||||
icon_state = "rune6words"
|
||||
turnedness = 181
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune6/inner
|
||||
icon_state = "rune6inner"
|
||||
turnedness = 179
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune6/center
|
||||
icon_state = "rune6center"
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune7
|
||||
icon_state = "rune7words"
|
||||
turnedness = 181
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune7/inner
|
||||
icon_state = "rune7inner"
|
||||
turnedness = 179
|
||||
|
||||
/obj/effect/overlay/temp/cult/rune_spawn/rune7/center
|
||||
icon_state = "rune7center"
|
||||
@@ -0,0 +1,312 @@
|
||||
//unsorted miscellaneous temporary visuals
|
||||
/obj/effect/overlay/temp/dir_setting/bloodsplatter
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
duration = 5
|
||||
randomdir = FALSE
|
||||
layer = BELOW_MOB_LAYER
|
||||
var/splatter_type = "splatter"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/bloodsplatter/Initialize(mapload, set_dir)
|
||||
if(set_dir in GLOB.diagonals)
|
||||
icon_state = "[splatter_type][pick(1, 2, 6)]"
|
||||
else
|
||||
icon_state = "[splatter_type][pick(3, 4, 5)]"
|
||||
. = ..()
|
||||
var/target_pixel_x = 0
|
||||
var/target_pixel_y = 0
|
||||
switch(set_dir)
|
||||
if(NORTH)
|
||||
target_pixel_y = 16
|
||||
if(SOUTH)
|
||||
target_pixel_y = -16
|
||||
layer = ABOVE_MOB_LAYER
|
||||
if(EAST)
|
||||
target_pixel_x = 16
|
||||
if(WEST)
|
||||
target_pixel_x = -16
|
||||
if(NORTHEAST)
|
||||
target_pixel_x = 16
|
||||
target_pixel_y = 16
|
||||
if(NORTHWEST)
|
||||
target_pixel_x = -16
|
||||
target_pixel_y = 16
|
||||
if(SOUTHEAST)
|
||||
target_pixel_x = 16
|
||||
target_pixel_y = -16
|
||||
layer = ABOVE_MOB_LAYER
|
||||
if(SOUTHWEST)
|
||||
target_pixel_x = -16
|
||||
target_pixel_y = -16
|
||||
layer = ABOVE_MOB_LAYER
|
||||
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/bloodsplatter/xenosplatter
|
||||
splatter_type = "xsplatter"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/speedbike_trail
|
||||
name = "speedbike trails"
|
||||
icon_state = "ion_fade"
|
||||
layer = BELOW_MOB_LAYER
|
||||
duration = 10
|
||||
randomdir = 0
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/firing_effect
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "firing_effect"
|
||||
duration = 2
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/firing_effect/setDir(newdir)
|
||||
switch(newdir)
|
||||
if(NORTH)
|
||||
layer = BELOW_MOB_LAYER
|
||||
pixel_x = rand(-3,3)
|
||||
pixel_y = rand(4,6)
|
||||
if(SOUTH)
|
||||
pixel_x = rand(-3,3)
|
||||
pixel_y = rand(-1,1)
|
||||
else
|
||||
pixel_x = rand(-1,1)
|
||||
pixel_y = rand(-1,1)
|
||||
..()
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/firing_effect/energy
|
||||
icon_state = "firing_effect_energy"
|
||||
duration = 3
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/firing_effect/magic
|
||||
icon_state = "shieldsparkles"
|
||||
duration = 3
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/ninja
|
||||
name = "ninja shadow"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "uncloak"
|
||||
duration = 9
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/ninja/cloak
|
||||
icon_state = "cloak"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/ninja/shadow
|
||||
icon_state = "shadow"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/ninja/phase
|
||||
name = "ninja energy"
|
||||
icon_state = "phasein"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/ninja/phase/out
|
||||
icon_state = "phaseout"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/wraith
|
||||
name = "blood"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "phase_shift2"
|
||||
duration = 12
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/wraith/out
|
||||
icon_state = "phase_shift"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/tailsweep
|
||||
icon_state = "tailsweep"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/wizard
|
||||
name = "water"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "reappear"
|
||||
duration = 5
|
||||
|
||||
/obj/effect/overlay/temp/wizard/out
|
||||
icon_state = "liquify"
|
||||
duration = 12
|
||||
|
||||
/obj/effect/overlay/temp/monkeyify
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "h2monkey"
|
||||
duration = 22
|
||||
|
||||
/obj/effect/overlay/temp/monkeyify/humanify
|
||||
icon_state = "monkey2h"
|
||||
|
||||
/obj/effect/overlay/temp/borgflash
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "blspell"
|
||||
duration = 5
|
||||
|
||||
/obj/effect/overlay/temp/guardian
|
||||
randomdir = 0
|
||||
|
||||
/obj/effect/overlay/temp/guardian/phase
|
||||
duration = 5
|
||||
icon_state = "phasein"
|
||||
|
||||
/obj/effect/overlay/temp/guardian/phase/out
|
||||
icon_state = "phaseout"
|
||||
|
||||
/obj/effect/overlay/temp/decoy
|
||||
desc = "It's a decoy!"
|
||||
duration = 15
|
||||
|
||||
/obj/effect/overlay/temp/decoy/Initialize(mapload, atom/mimiced_atom)
|
||||
. = ..()
|
||||
alpha = initial(alpha)
|
||||
if(mimiced_atom)
|
||||
name = mimiced_atom.name
|
||||
appearance = mimiced_atom.appearance
|
||||
setDir(mimiced_atom.dir)
|
||||
mouse_opacity = 0
|
||||
|
||||
/obj/effect/overlay/temp/decoy/fading/Initialize(mapload, atom/mimiced_atom)
|
||||
. = ..()
|
||||
animate(src, alpha = 0, time = duration)
|
||||
|
||||
/obj/effect/overlay/temp/decoy/fading/fivesecond
|
||||
duration = 50
|
||||
|
||||
/obj/effect/overlay/temp/small_smoke
|
||||
icon_state = "smoke"
|
||||
duration = 50
|
||||
|
||||
/obj/effect/overlay/temp/fire
|
||||
icon = 'icons/effects/fire.dmi'
|
||||
icon_state = "3"
|
||||
duration = 20
|
||||
|
||||
/obj/effect/overlay/temp/revenant
|
||||
name = "spooky lights"
|
||||
icon_state = "purplesparkles"
|
||||
|
||||
/obj/effect/overlay/temp/revenant/cracks
|
||||
name = "glowing cracks"
|
||||
icon_state = "purplecrack"
|
||||
duration = 6
|
||||
|
||||
/obj/effect/overlay/temp/gravpush
|
||||
name = "gravity wave"
|
||||
icon_state = "shieldsparkles"
|
||||
duration = 5
|
||||
|
||||
/obj/effect/overlay/temp/telekinesis
|
||||
name = "telekinetic force"
|
||||
icon_state = "empdisable"
|
||||
duration = 5
|
||||
|
||||
/obj/effect/overlay/temp/emp
|
||||
name = "emp sparks"
|
||||
icon_state = "empdisable"
|
||||
|
||||
/obj/effect/overlay/temp/emp/pulse
|
||||
name = "emp pulse"
|
||||
icon_state = "emppulse"
|
||||
duration = 8
|
||||
randomdir = 0
|
||||
|
||||
/obj/effect/overlay/temp/gib_animation
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
duration = 15
|
||||
|
||||
/obj/effect/overlay/temp/gib_animation/Initialize(mapload, gib_icon)
|
||||
icon_state = gib_icon // Needs to be before ..() so icon is correct
|
||||
. = ..()
|
||||
|
||||
/obj/effect/overlay/temp/gib_animation/animal
|
||||
icon = 'icons/mob/animal.dmi'
|
||||
|
||||
/obj/effect/overlay/temp/dust_animation
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
duration = 15
|
||||
|
||||
/obj/effect/overlay/temp/dust_animation/Initialize(mapload, dust_icon)
|
||||
icon_state = dust_icon // Before ..() so the correct icon is flick()'d
|
||||
. = ..()
|
||||
|
||||
/obj/effect/overlay/temp/mummy_animation
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "mummy_revive"
|
||||
duration = 20
|
||||
|
||||
/obj/effect/overlay/temp/heal //color is white by default, set to whatever is needed
|
||||
name = "healing glow"
|
||||
icon_state = "heal"
|
||||
duration = 15
|
||||
|
||||
/obj/effect/overlay/temp/heal/Initialize(mapload, set_color)
|
||||
if(set_color)
|
||||
add_atom_colour(set_color, FIXED_COLOUR_PRIORITY)
|
||||
. = ..()
|
||||
pixel_x = rand(-12, 12)
|
||||
pixel_y = rand(-9, 0)
|
||||
|
||||
/obj/effect/overlay/temp/kinetic_blast
|
||||
name = "kinetic explosion"
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "kinetic_blast"
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/explosion
|
||||
name = "explosion"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "explosion"
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
duration = 8
|
||||
|
||||
/obj/effect/overlay/temp/explosion/fast
|
||||
icon_state = "explosionfast"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/blob
|
||||
name = "blob"
|
||||
icon_state = "blob_attack"
|
||||
alpha = 140
|
||||
randomdir = 0
|
||||
duration = 6
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect
|
||||
icon_state = "impact_bullet"
|
||||
duration = 5
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/Initialize(mapload, atom/target, obj/item/projectile/P)
|
||||
if(target == P.original) //the projectile hit the target originally clicked
|
||||
pixel_x = P.p_x + target.pixel_x - 16 + rand(-4,4)
|
||||
pixel_y = P.p_y + target.pixel_y - 16 + rand(-4,4)
|
||||
else
|
||||
pixel_x = target.pixel_x + rand(-4,4)
|
||||
pixel_y = target.pixel_y + rand(-4,4)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/red_laser
|
||||
icon_state = "impact_laser"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/red_laser/wall
|
||||
icon_state = "impact_laser_wall"
|
||||
duration = 10
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/blue_laser
|
||||
icon_state = "impact_laser_blue"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/green_laser
|
||||
icon_state = "impact_laser_green"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/purple_laser
|
||||
icon_state = "impact_laser_purple"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/overlay/temp/impact_effect/ion
|
||||
icon_state = "shieldsparkles"
|
||||
duration = 6
|
||||
|
||||
/obj/effect/overlay/temp/heart
|
||||
name = "heart"
|
||||
icon = 'icons/mob/animal.dmi'
|
||||
icon_state = "heart"
|
||||
duration = 25
|
||||
|
||||
/obj/effect/overlay/temp/heart/Initialize(mapload)
|
||||
. = ..()
|
||||
pixel_x = rand(-4,4)
|
||||
pixel_y = rand(-4,4)
|
||||
animate(src, pixel_y = pixel_y + 32, alpha = 0, time = 25)
|
||||
@@ -0,0 +1,37 @@
|
||||
//temporary visual effects
|
||||
/obj/effect/overlay/temp
|
||||
icon_state = "nothing"
|
||||
anchored = 1
|
||||
layer = ABOVE_MOB_LAYER
|
||||
mouse_opacity = 0
|
||||
var/duration = 10 //in deciseconds
|
||||
var/randomdir = TRUE
|
||||
var/timerid
|
||||
|
||||
/obj/effect/overlay/temp/Initialize()
|
||||
. = ..()
|
||||
if(randomdir)
|
||||
setDir(pick(GLOB.cardinal))
|
||||
|
||||
timerid = QDEL_IN(src, duration)
|
||||
|
||||
/obj/effect/overlay/temp/Destroy()
|
||||
. = ..()
|
||||
deltimer(timerid)
|
||||
|
||||
/obj/effect/overlay/temp/singularity_act()
|
||||
return
|
||||
|
||||
/obj/effect/overlay/temp/singularity_pull()
|
||||
return
|
||||
|
||||
/obj/effect/overlay/temp/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting
|
||||
randomdir = FALSE
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/Initialize(mapload, set_dir)
|
||||
if(set_dir)
|
||||
setDir(set_dir)
|
||||
. = ..()
|
||||
@@ -528,6 +528,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
|
||||
/obj/item/throw_impact(atom/A)
|
||||
if(A && !QDELETED(A))
|
||||
if(is_hot() && isliving(A))
|
||||
var/mob/living/L = A
|
||||
L.IgniteMob()
|
||||
var/itempush = 1
|
||||
if(w_class < 4)
|
||||
itempush = 0 //too light to push anything
|
||||
|
||||
@@ -504,6 +504,113 @@
|
||||
S.change_head_color(color2)
|
||||
dropped = TRUE
|
||||
|
||||
//Peacekeeper Cyborg Projectile Dampenening Field
|
||||
/obj/item/borg/projectile_dampen
|
||||
name = "Hyperkinetic Dampening projector"
|
||||
desc = "A device that projects a dampening field that weakens kinetic energy above a certain threshold. <span class='boldnotice'>Projects a field that drains power per second \
|
||||
while active, that will weaken and slow damaging projectiles inside its field.</span> Still being a prototype, it tends to induce a charge on ungrounded metallic surfaces."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "shield"
|
||||
var/maxenergy = 1500
|
||||
var/energy = 1500
|
||||
var/energy_recharge = 7.5
|
||||
var/energy_recharge_cyborg_drain_coefficient = 0.4
|
||||
var/cyborg_cell_critical_percentage = 0.05
|
||||
var/mob/living/silicon/robot/host = null
|
||||
var/datum/proximity_monitor/advanced/dampening_field
|
||||
var/projectile_damage_coefficient = 0.5
|
||||
var/projectile_damage_tick_ecost_coefficient = 2 //Lasers get half their damage chopped off, drains 50 power/tick. Note that fields are processed 5 times per second.
|
||||
var/projectile_speed_coefficient = 1.5 //Higher the coefficient slower the projectile.
|
||||
var/projectile_tick_speed_ecost = 15
|
||||
var/current_damage_dampening = 0
|
||||
var/list/obj/item/projectile/tracked
|
||||
var/image/projectile_effect
|
||||
var/field_radius = 3
|
||||
|
||||
/obj/item/borg/projectile_dampen/debug
|
||||
maxenergy = 50000
|
||||
energy = 50000
|
||||
energy_recharge = 5000
|
||||
|
||||
/obj/item/borg/projectile_dampen/Initialize()
|
||||
. = ..()
|
||||
projectile_effect = image('icons/effects/fields.dmi', "projectile_dampen_effect")
|
||||
tracked = list()
|
||||
icon_state = "shield0"
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/obj/item/borg/projectile_dampen/Destroy()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/borg/projectile_dampen/attack_self(mob/user)
|
||||
var/active = FALSE
|
||||
if(!istype(dampening_field))
|
||||
activate_field()
|
||||
active = TRUE
|
||||
else
|
||||
deactivate_field()
|
||||
active = FALSE
|
||||
to_chat(user, "<span class='boldnotice'>You [active? "activate":"deactivate"] the [src].</span>")
|
||||
icon_state = "[initial(icon_state)][active]"
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/activate_field()
|
||||
if(!istype(dampening_field))
|
||||
dampening_field = make_field(/datum/proximity_monitor/advanced/peaceborg_dampener, list("current_range" = field_radius, "host" = src, "projector" = src))
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/deactivate_field()
|
||||
QDEL_NULL(dampening_field)
|
||||
visible_message("<span class='warning'>The [src] shuts off!</span>")
|
||||
for(var/obj/item/projectile/P in tracked)
|
||||
restore_projectile(P)
|
||||
|
||||
/obj/item/borg/projectile_dampen/process()
|
||||
process_recharge()
|
||||
process_usage()
|
||||
update_location()
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/update_location()
|
||||
if(dampening_field)
|
||||
dampening_field.HandleMove()
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/process_usage()
|
||||
var/usage = 0
|
||||
for(var/I in tracked)
|
||||
if(!tracked[I]) //No damage
|
||||
continue
|
||||
usage += projectile_tick_speed_ecost
|
||||
usage += (current_damage_dampening * projectile_damage_tick_ecost_coefficient)
|
||||
energy = Clamp(energy - usage, 0, maxenergy)
|
||||
if(energy <= 0)
|
||||
deactivate_field()
|
||||
visible_message("<span class='warning'>The [src] blinks \"ENERGY DEPLETED\"</span>")
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/process_recharge()
|
||||
if(!istype(host))
|
||||
energy = Clamp(energy + energy_recharge, 0, maxenergy)
|
||||
return
|
||||
if((host.cell.charge >= (host.cell.maxcharge * cyborg_cell_critical_percentage)) && (energy < maxenergy))
|
||||
host.cell.use(energy_recharge*energy_recharge_cyborg_drain_coefficient)
|
||||
energy += energy_recharge
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/dampen_projectile(obj/item/projectile/P, track_projectile = TRUE)
|
||||
if(tracked[P])
|
||||
return
|
||||
if(track_projectile)
|
||||
tracked[P] = P.damage
|
||||
current_damage_dampening += P.damage
|
||||
P.damage *= projectile_damage_coefficient
|
||||
P.speed *= projectile_speed_coefficient
|
||||
P.add_overlay(projectile_effect)
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/restore_projectile(obj/item/projectile/P)
|
||||
tracked -= P
|
||||
P.damage *= (1/projectile_damage_coefficient)
|
||||
P.speed *= (1/projectile_speed_coefficient)
|
||||
P.cut_overlay(projectile_effect)
|
||||
current_damage_dampening -= P.damage
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
HUD/SIGHT things
|
||||
***********************************************************************/
|
||||
|
||||
@@ -279,6 +279,28 @@
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
|
||||
/obj/item/toy/windupToolbox
|
||||
name = "windup toolbox"
|
||||
desc = "A replica toolbox that rumbles when you turn the key"
|
||||
icon_state = "his_grace"
|
||||
item_state = "artistic_toolbox"
|
||||
var/active = FALSE
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
attack_verb = list("robusted")
|
||||
|
||||
/obj/item/toy/windupToolbox/attack_self(mob/user)
|
||||
if(!active)
|
||||
icon_state = "his_grace_awakened"
|
||||
to_chat(user, "<span class='warning'>You wind up [src], it begins to rumble.</span>")
|
||||
active = TRUE
|
||||
addtimer(CALLBACK(src, .proc/stopRumble), 600)
|
||||
else
|
||||
to_chat(user, "[src] is already active.")
|
||||
|
||||
/obj/item/toy/windupToolbox/proc/stopRumble()
|
||||
icon_state = initial(icon_state)
|
||||
active = FALSE
|
||||
|
||||
/*
|
||||
* Subtype of Double-Bladed Energy Swords
|
||||
*/
|
||||
|
||||
@@ -472,8 +472,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BELT
|
||||
var/lit = 0
|
||||
var/fancy = TRUE
|
||||
heat = 1500
|
||||
resistance_flags = FIRE_PROOF
|
||||
light_color = LIGHT_COLOR_FIRE
|
||||
|
||||
/obj/item/weapon/lighter/update_icon()
|
||||
if(lit)
|
||||
@@ -484,37 +486,28 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
/obj/item/weapon/lighter/ignition_effect(atom/A, mob/user)
|
||||
. = "<span class='rose'>With a single flick of their wrist, [user] smoothly lights [A] with [src]. Damn [user.p_theyre()] cool.</span>"
|
||||
|
||||
/obj/item/weapon/lighter/greyscale
|
||||
name = "cheap lighter"
|
||||
desc = "A cheap-as-free lighter."
|
||||
icon_state = "lighter"
|
||||
|
||||
/obj/item/weapon/lighter/greyscale/Initialize()
|
||||
. = ..()
|
||||
add_atom_colour(color2hex(randomColor(1)), FIXED_COLOUR_PRIORITY)
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/lighter/greyscale/update_icon()
|
||||
cut_overlays()
|
||||
var/mutable_appearance/base_overlay = mutable_appearance(icon,"[initial(icon_state)]_base")
|
||||
base_overlay.appearance_flags = RESET_COLOR //the edging doesn't change color
|
||||
/obj/item/weapon/lighter/proc/set_lit(new_lit)
|
||||
lit = new_lit
|
||||
if(lit)
|
||||
base_overlay.icon_state = "[initial(icon_state)]_on"
|
||||
add_overlay(base_overlay)
|
||||
|
||||
/obj/item/weapon/lighter/greyscale/ignition_effect(atom/A, mob/user)
|
||||
. = "<span class='notice'>After some fiddling, [user] manages to light [A] with [src].</span>"
|
||||
force = 5
|
||||
damtype = "fire"
|
||||
hitsound = 'sound/items/welder.ogg'
|
||||
attack_verb = list("burnt", "singed")
|
||||
set_light(1)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
hitsound = "swing_hit"
|
||||
force = 0
|
||||
attack_verb = null //human_defense.dm takes care of it
|
||||
set_light(0)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/lighter/attack_self(mob/living/user)
|
||||
if(user.is_holding(src))
|
||||
if(!lit)
|
||||
lit = 1
|
||||
update_icon()
|
||||
force = 5
|
||||
damtype = "fire"
|
||||
hitsound = 'sound/items/welder.ogg'
|
||||
attack_verb = list("burnt", "singed")
|
||||
if(!istype(src, /obj/item/weapon/lighter/greyscale))
|
||||
set_lit(TRUE)
|
||||
if(fancy)
|
||||
user.visible_message("Without even breaking stride, [user] flips open and lights [src] in one smooth movement.", "<span class='notice'>Without even breaking stride, you flip open and lights [src] in one smooth movement.</span>")
|
||||
else
|
||||
var/prot = FALSE
|
||||
@@ -534,20 +527,12 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
user.apply_damage(5, BURN, hitzone)
|
||||
user.visible_message("<span class='warning'>After a few attempts, [user] manages to light [src] - however, [user.p_they()] burn their finger in the process.</span>", "<span class='warning'>You burn yourself while lighting the lighter!</span>")
|
||||
|
||||
set_light(1)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
lit = 0
|
||||
update_icon()
|
||||
hitsound = "swing_hit"
|
||||
force = 0
|
||||
attack_verb = null //human_defense.dm takes care of it
|
||||
if(!istype(src, /obj/item/weapon/lighter/greyscale))
|
||||
set_lit(FALSE)
|
||||
if(fancy)
|
||||
user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what [user.p_theyre()] doing. Wow.", "<span class='notice'>You quietly shut off [src] without even looking at what you're doing. Wow.</span>")
|
||||
else
|
||||
user.visible_message("[user] quietly shuts off [src].", "<span class='notice'>You quietly shut off [src].")
|
||||
set_light(0)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
else
|
||||
. = ..()
|
||||
|
||||
@@ -562,7 +547,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
if(M == user)
|
||||
cig.attackby(src, user)
|
||||
else
|
||||
if(!istype(src, /obj/item/weapon/lighter/greyscale))
|
||||
if(fancy)
|
||||
cig.light("<span class='rose'>[user] whips the [name] out and holds it for [M]. [user.p_their(TRUE)] arm is as steady as the unflickering flame they light \the [cig] with.</span>")
|
||||
else
|
||||
cig.light("<span class='notice'>[user] holds the [name] out for [M], and lights the [cig.name].</span>")
|
||||
@@ -575,6 +560,30 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
/obj/item/weapon/lighter/is_hot()
|
||||
return lit * heat
|
||||
|
||||
|
||||
/obj/item/weapon/lighter/greyscale
|
||||
name = "cheap lighter"
|
||||
desc = "A cheap-as-free lighter."
|
||||
icon_state = "lighter"
|
||||
fancy = FALSE
|
||||
|
||||
/obj/item/weapon/lighter/greyscale/Initialize()
|
||||
. = ..()
|
||||
add_atom_colour(color2hex(randomColor(1)), FIXED_COLOUR_PRIORITY)
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/lighter/greyscale/update_icon()
|
||||
cut_overlays()
|
||||
var/mutable_appearance/base_overlay = mutable_appearance(icon,"[initial(icon_state)]_base")
|
||||
base_overlay.appearance_flags = RESET_COLOR //the edging doesn't change color
|
||||
if(lit)
|
||||
base_overlay.icon_state = "[initial(icon_state)]_on"
|
||||
add_overlay(base_overlay)
|
||||
|
||||
/obj/item/weapon/lighter/greyscale/ignition_effect(atom/A, mob/user)
|
||||
. = "<span class='notice'>After some fiddling, [user] manages to light [A] with [src].</span>"
|
||||
|
||||
|
||||
///////////
|
||||
//ROLLING//
|
||||
///////////
|
||||
|
||||
@@ -50,9 +50,7 @@
|
||||
M.dna.uni_identity = merge_text(M.dna.uni_identity, fields["UI"])
|
||||
M.updateappearance(mutations_overlay_update=1)
|
||||
log_attack(log_msg)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>It appears that [M] does not have compatible DNA.</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/dnainjector/attack(mob/target, mob/user)
|
||||
if(!user.IsAdvancedToolUser())
|
||||
@@ -79,7 +77,9 @@
|
||||
|
||||
add_logs(user, target, "injected", src)
|
||||
|
||||
inject(target, user) //Now we actually do the heavy lifting.
|
||||
if(!inject(target, user)) //Now we actually do the heavy lifting.
|
||||
to_chat(user, "<span class='notice'>It appears that [target] does not have compatible DNA.</span>")
|
||||
|
||||
used = 1
|
||||
icon_state = "dnainjector0"
|
||||
desc += " This one is used up."
|
||||
|
||||
@@ -48,23 +48,27 @@
|
||||
/obj/item/weapon/grenade/attack_self(mob/user)
|
||||
if(!active)
|
||||
if(clown_check(user))
|
||||
to_chat(user, "<span class='warning'>You prime the [name]! [det_time/10] seconds!</span>")
|
||||
playsound(user.loc, 'sound/weapons/armbomb.ogg', 60, 1)
|
||||
active = 1
|
||||
icon_state = initial(icon_state) + "_active"
|
||||
add_fingerprint(user)
|
||||
var/turf/bombturf = get_turf(src)
|
||||
var/area/A = get_area(bombturf)
|
||||
var/message = "[ADMIN_LOOKUPFLW(user)]) has primed a [name] for detonation at [ADMIN_COORDJMP(bombturf)]"
|
||||
GLOB.bombers += message
|
||||
message_admins(message)
|
||||
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(bombturf)].")
|
||||
preprime(user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
C.throw_mode_on()
|
||||
spawn(det_time)
|
||||
prime()
|
||||
|
||||
/obj/item/weapon/grenade/proc/preprime(mob/user)
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>You prime the [name]! [det_time/10] seconds!</span>")
|
||||
playsound(loc, 'sound/weapons/armbomb.ogg', 60, 1)
|
||||
active = TRUE
|
||||
icon_state = initial(icon_state) + "_active"
|
||||
add_fingerprint(user)
|
||||
var/turf/bombturf = get_turf(src)
|
||||
var/area/A = get_area(bombturf)
|
||||
if(user)
|
||||
var/message = "[ADMIN_LOOKUPFLW(user)]) has primed a [name] for detonation at [ADMIN_COORDJMP(bombturf)]"
|
||||
GLOB.bombers += message
|
||||
message_admins(message)
|
||||
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(bombturf)].")
|
||||
|
||||
addtimer(CALLBACK(src, .proc/prime), det_time)
|
||||
|
||||
/obj/item/weapon/grenade/proc/prime()
|
||||
|
||||
@@ -104,4 +108,4 @@
|
||||
if(damage && attack_type == PROJECTILE_ATTACK && prob(15))
|
||||
owner.visible_message("<span class='danger'>[attack_text] hits [owner]'s [src], setting it off! What a shot!</span>")
|
||||
prime()
|
||||
return 1 //It hit the grenade, not them
|
||||
return 1 //It hit the grenade, not them
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
plastic_overlay = mutable_appearance(icon, "[item_state]2")
|
||||
..()
|
||||
|
||||
/obj/item/weapon/grenade/plastic/Initialize(mapload)
|
||||
. = ..()
|
||||
SET_SECONDARY_FLAG(src, NO_EMP_WIRES)
|
||||
|
||||
/obj/item/weapon/grenade/plastic/Destroy()
|
||||
qdel(nadeassembly)
|
||||
nadeassembly = null
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
range_multiplier = 3
|
||||
fire_mode = PCANNON_FIFO
|
||||
throw_amount = 1
|
||||
maxWeightClass = 100 //50 pies. :^)
|
||||
maxWeightClass = 150 //50 pies. :^)
|
||||
clumsyCheck = FALSE
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/pie/can_load_item(obj/item/I, mob/user)
|
||||
@@ -252,3 +252,22 @@
|
||||
return ..()
|
||||
to_chat(user, "<span class='warning'>[src] only accepts pies!</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/pie/selfcharge
|
||||
automatic = TRUE
|
||||
var/charge_amount = 1
|
||||
var/charge_ticks = 1
|
||||
var/charge_tick = 0
|
||||
maxWeightClass = 60 //20 pies.
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/pie/selfcharge/Initialize()
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/pie/selfcharge/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/pie/selfcharge/process()
|
||||
if(++charge_tick >= charge_ticks)
|
||||
fill_with_type(/obj/item/weapon/reagent_containers/food/snacks/pie, charge_amount)
|
||||
|
||||
@@ -140,6 +140,8 @@
|
||||
item_state = "plasmaman_tank_belt"
|
||||
slot_flags = SLOT_BELT
|
||||
force = 5
|
||||
volume = 3
|
||||
w_class = WEIGHT_CLASS_SMALL //thanks i forgot this
|
||||
|
||||
/obj/item/weapon/tank/internals/plasmaman/belt/full/New()
|
||||
..()
|
||||
|
||||
@@ -149,8 +149,8 @@
|
||||
|
||||
/obj/effect/mob_spawn/human/golem/attack_hand(mob/user)
|
||||
if(isgolem(user) && can_transfer)
|
||||
var/transfer = alert("Transfer your soul to [src]? (Warning, your old body will die!)",,"Yes","No")
|
||||
if(!transfer)
|
||||
var/transfer_choice = alert("Transfer your soul to [src]? (Warning, your old body will die!)",,"Yes","No")
|
||||
if(transfer_choice != "Yes")
|
||||
return
|
||||
log_game("[user.ckey] golem-swapped into [src]")
|
||||
user.visible_message("<span class='notice'>A faint light leaves [user], moving to [src] and animating it!</span>","<span class='notice'>You leave your old body behind, and transfer into [src]!</span>")
|
||||
|
||||
@@ -440,7 +440,7 @@
|
||||
dir = FULLTILE_WINDOW_DIR
|
||||
max_integrity = 50
|
||||
fulltile = 1
|
||||
flags = NONE
|
||||
flags = PREVENT_CLICK_UNDER
|
||||
smooth = SMOOTH_TRUE
|
||||
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile,/obj/structure/window/reinforced/highpressure/fulltile, /obj/structure/window/reinforced/tinted/fulltile)
|
||||
glass_amount = 2
|
||||
@@ -454,7 +454,7 @@
|
||||
dir = FULLTILE_WINDOW_DIR
|
||||
max_integrity = 100
|
||||
fulltile = 1
|
||||
flags = NONE
|
||||
flags = PREVENT_CLICK_UNDER
|
||||
smooth = SMOOTH_TRUE
|
||||
|
||||
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile,/obj/structure/window/reinforced/highpressure/fulltile, /obj/structure/window/reinforced/tinted/fulltile)
|
||||
@@ -467,7 +467,7 @@
|
||||
dir = FULLTILE_WINDOW_DIR
|
||||
max_integrity = 1000
|
||||
fulltile = 1
|
||||
flags = NONE
|
||||
flags = PREVENT_CLICK_UNDER
|
||||
smooth = SMOOTH_TRUE
|
||||
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile,/obj/structure/window/reinforced/highpressure/fulltile, /obj/structure/window/reinforced/tinted/fulltile)
|
||||
level = 3
|
||||
@@ -481,7 +481,7 @@
|
||||
icon_state = "tinted_window"
|
||||
dir = FULLTILE_WINDOW_DIR
|
||||
fulltile = 1
|
||||
flags = NONE
|
||||
flags = PREVENT_CLICK_UNDER
|
||||
smooth = SMOOTH_TRUE
|
||||
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile,/obj/structure/window/reinforced/highpressure/fulltile, /obj/structure/window/reinforced/tinted/fulltile/)
|
||||
level = 3
|
||||
@@ -504,7 +504,7 @@
|
||||
max_integrity = 100
|
||||
wtype = "shuttle"
|
||||
fulltile = 1
|
||||
flags = NONE
|
||||
flags = PREVENT_CLICK_UNDER
|
||||
reinf = 1
|
||||
heat_resistance = 1600
|
||||
armor = list(melee = 50, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 100, fire = 80, acid = 100)
|
||||
@@ -583,7 +583,7 @@
|
||||
smooth = SMOOTH_TRUE
|
||||
canSmoothWith = null
|
||||
fulltile = 1
|
||||
flags = NONE
|
||||
flags = PREVENT_CLICK_UNDER
|
||||
dir = FULLTILE_WINDOW_DIR
|
||||
max_integrity = 120
|
||||
level = 3
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
if (opacity)
|
||||
has_opaque_atom = TRUE
|
||||
|
||||
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
|
||||
/turf/open/space/attack_ghost(mob/dead/observer/user)
|
||||
@@ -177,7 +177,7 @@
|
||||
ChangeTurf(/turf/open/floor/plating)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/turf/open/space/ReplaceWithLattice()
|
||||
var/dest_x = destination_x
|
||||
var/dest_y = destination_y
|
||||
@@ -186,4 +186,4 @@
|
||||
destination_x = dest_x
|
||||
destination_y = dest_y
|
||||
destination_z = dest_z
|
||||
|
||||
|
||||
|
||||
@@ -92,39 +92,39 @@
|
||||
LC.attackby(C,user)
|
||||
return
|
||||
coil.place_turf(src, user)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/turf/CanPass(atom/movable/mover, turf/target, height=1.5)
|
||||
if(!target) return 0
|
||||
if(!target) return FALSE
|
||||
|
||||
if(istype(mover)) // turf/Enter(...) will perform more advanced checks
|
||||
return !density
|
||||
|
||||
else // Now, doing more detailed checks for air movement and air group formation
|
||||
if(target.blocks_air||blocks_air)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
for(var/obj/obstacle in src)
|
||||
if(!obstacle.CanPass(mover, target, height))
|
||||
return 0
|
||||
return FALSE
|
||||
for(var/obj/obstacle in target)
|
||||
if(!obstacle.CanPass(mover, src, height))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area)
|
||||
if (!mover)
|
||||
return 1
|
||||
return TRUE
|
||||
// First, make sure it can leave its square
|
||||
if(isturf(mover.loc))
|
||||
// Nothing but border objects stop you from leaving a tile, only one loop is needed
|
||||
for(var/obj/obstacle in mover.loc)
|
||||
if(!obstacle.CheckExit(mover, src) && obstacle != mover && obstacle != forget)
|
||||
mover.Bump(obstacle, 1)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/list/large_dense = list()
|
||||
//Next, check objects to block entry that are on the border
|
||||
@@ -132,14 +132,14 @@
|
||||
if(border_obstacle.flags & ON_BORDER)
|
||||
if(!border_obstacle.CanPass(mover, mover.loc, 1) && (forget != border_obstacle))
|
||||
mover.Bump(border_obstacle, 1)
|
||||
return 0
|
||||
return FALSE
|
||||
else
|
||||
large_dense += border_obstacle
|
||||
|
||||
//Then, check the turf itself
|
||||
if (!src.CanPass(mover, src))
|
||||
mover.Bump(src, 1)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
//Finally, check objects/mobs to block entry that are not on the border
|
||||
var/atom/movable/tompost_bump
|
||||
@@ -151,8 +151,9 @@
|
||||
top_layer = obstacle.layer
|
||||
if(tompost_bump)
|
||||
mover.Bump(tompost_bump,1)
|
||||
return 0
|
||||
return 1 //Nothing found to block so return success!
|
||||
return FALSE
|
||||
|
||||
return TRUE //Nothing found to block so return success!
|
||||
|
||||
/turf/Entered(atom/movable/AM)
|
||||
if(explosion_level && AM.ex_check(explosion_id))
|
||||
@@ -185,7 +186,7 @@
|
||||
O.make_unfrozen()
|
||||
|
||||
/turf/proc/is_plasteel_floor()
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/turf/proc/levelupdate()
|
||||
for(var/obj/O in src)
|
||||
@@ -303,7 +304,7 @@
|
||||
if(src_object.contents.len)
|
||||
to_chat(usr, "<span class='notice'>You start dumping out the contents...</span>")
|
||||
if(!do_after(usr,20,target=src_object))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/list/things = src_object.contents.Copy()
|
||||
var/datum/progressbar/progress = new(user, things.len, src)
|
||||
@@ -311,7 +312,7 @@
|
||||
sleep(1)
|
||||
qdel(progress)
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
//////////////////////////////
|
||||
//Distance procs
|
||||
@@ -325,7 +326,7 @@
|
||||
// possible. It results in more efficient (CPU-wise) pathing
|
||||
// for bots and anything else that only moves in cardinal dirs.
|
||||
/turf/proc/Distance_cardinal(turf/T)
|
||||
if(!src || !T) return 0
|
||||
if(!src || !T) return FALSE
|
||||
return abs(x - T.x) + abs(y - T.y)
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
@@ -341,7 +342,7 @@
|
||||
return(2)
|
||||
|
||||
/turf/proc/can_have_cabling()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/turf/proc/can_lay_cable()
|
||||
return can_have_cabling() & !intact
|
||||
|
||||
@@ -108,7 +108,11 @@ GLOBAL_PROTECT(AdminProcCallCount)
|
||||
return call(target, procname)(arglist(arguments))
|
||||
|
||||
/proc/IsAdminAdvancedProcCall()
|
||||
#ifdef TESTING
|
||||
return FALSE
|
||||
#else
|
||||
return usr && usr.client && GLOB.AdminProcCaller == usr.client.ckey
|
||||
#endif
|
||||
|
||||
/client/proc/callproc_datum(datum/A as null|area|mob|obj|turf)
|
||||
set category = "Debug"
|
||||
|
||||
@@ -153,8 +153,8 @@
|
||||
return
|
||||
var/datum/gas_mixture/air1 = AIR1
|
||||
var/turf/T = get_turf(src)
|
||||
if(isliving(occupant))
|
||||
var/mob/living/mob_occupant
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant.health >= 100) // Don't bother with fully healed people.
|
||||
on = FALSE
|
||||
update_icon()
|
||||
@@ -176,8 +176,8 @@
|
||||
|
||||
if(beaker)
|
||||
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
|
||||
beaker.reagents.trans_to(mob_occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
|
||||
beaker.reagents.reaction(mob_occupant, VAPOR)
|
||||
beaker.reagents.trans_to(occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
|
||||
beaker.reagents.reaction(occupant, VAPOR)
|
||||
air1.gases["o2"][MOLES] -= 2 / efficiency // Lets use gas for this.
|
||||
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
|
||||
reagent_transfer = 0
|
||||
@@ -192,7 +192,7 @@
|
||||
on = FALSE
|
||||
update_icon()
|
||||
return
|
||||
if(isliving(occupant))
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/cold_protection = 0
|
||||
var/mob/living/carbon/human/H = occupant
|
||||
@@ -244,7 +244,7 @@
|
||||
..()
|
||||
if(occupant)
|
||||
if(on)
|
||||
to_chat(user, "[occupant] is inside [src]!")
|
||||
to_chat(user, "Someone's inside [src]!")
|
||||
else
|
||||
to_chat(user, "You can barely make out a form floating in [src].")
|
||||
else
|
||||
@@ -299,7 +299,7 @@
|
||||
data["autoEject"] = autoeject
|
||||
|
||||
var/list/occupantData = list()
|
||||
if(isliving(occupant))
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
occupantData["name"] = mob_occupant.name
|
||||
occupantData["stat"] = mob_occupant.stat
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
|
||||
//Movable and easily code-modified fields! Allows for custom AOE effects that affect movement and anything inside of them, and can do custom turf effects!
|
||||
//Supports automatic recalculation/reset on movement.
|
||||
//If there's any way to make this less CPU intensive than I've managed, gimme a call or do it yourself! - kevinz000
|
||||
|
||||
//Field shapes
|
||||
#define FIELD_NO_SHAPE 0 //Does not update turfs automatically
|
||||
#define FIELD_SHAPE_RADIUS_SQUARE 1 //Uses current_range and square_depth_up/down
|
||||
#define FIELD_SHAPE_CUSTOM_SQUARE 2 //Uses square_height and square_width and square_depth_up/down
|
||||
|
||||
//Proc to make fields. make_field(field_type, field_params_in_associative_list)
|
||||
/proc/make_field(field_type, list/field_params, override_checks = FALSE, start_field = TRUE)
|
||||
var/datum/proximity_monitor/advanced/F = new field_type()
|
||||
if(!F.assume_params(field_params) && !override_checks)
|
||||
QDEL_NULL(F)
|
||||
if(!F.check_variables() && !override_checks)
|
||||
QDEL_NULL(F)
|
||||
if(start_field && (F || override_checks))
|
||||
F.Initialize()
|
||||
return F
|
||||
|
||||
/datum/proximity_monitor/advanced
|
||||
var/name = "\improper Energy Field"
|
||||
//Field setup specifications
|
||||
var/field_shape = FIELD_NO_SHAPE
|
||||
var/square_height = 0
|
||||
var/square_width = 0
|
||||
var/square_depth_up = 0
|
||||
var/square_depth_down = 0
|
||||
//Processing
|
||||
var/requires_processing = FALSE
|
||||
var/process_inner_turfs = FALSE //Don't do this unless it's absolutely necessary
|
||||
var/process_edge_turfs = FALSE //Don't do this either unless it's absolutely necessary, you can just track what things are inside manually or on the initial setup.
|
||||
var/setup_edge_turfs = FALSE //Setup edge turfs/all field turfs. Set either or both to ON when you need it, it's defaulting to off unless you do to save CPU.
|
||||
var/setup_field_turfs = FALSE
|
||||
|
||||
var/list/turf/field_turfs = list()
|
||||
var/list/turf/edge_turfs = list()
|
||||
var/list/turf/field_turfs_new = list()
|
||||
var/list/turf/edge_turfs_new = list()
|
||||
|
||||
/datum/proximity_monitor/advanced/New()
|
||||
SSfields.register_new_field(src)
|
||||
|
||||
/datum/proximity_monitor/advanced/Destroy()
|
||||
SSfields.unregister_field(src)
|
||||
full_cleanup()
|
||||
return ..()
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/assume_params(list/field_params)
|
||||
var/pass_check = TRUE
|
||||
for(var/param in field_params)
|
||||
if(vars[param] || isnull(vars[param]) || (param in vars))
|
||||
vars[param] = field_params[param]
|
||||
else
|
||||
pass_check = FALSE
|
||||
return pass_check
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/check_variables()
|
||||
var/pass = TRUE
|
||||
if(field_shape == FIELD_NO_SHAPE) //If you're going to make a manually updated field you shouldn't be using automatic checks so don't.
|
||||
pass = FALSE
|
||||
if(current_range < 0 || square_height < 0 || square_width < 0 || square_depth_up < 0 || square_depth_down < 0)
|
||||
pass = FALSE
|
||||
if(!istype(host))
|
||||
pass = FALSE
|
||||
return pass
|
||||
|
||||
/datum/proximity_monitor/advanced/process()
|
||||
if(process_inner_turfs)
|
||||
for(var/turf/T in field_turfs)
|
||||
process_inner_turf(T)
|
||||
CHECK_TICK //Really crappy lagchecks, needs improvement once someone starts using processed fields.
|
||||
if(process_edge_turfs)
|
||||
for(var/turf/T in edge_turfs)
|
||||
process_edge_turf(T)
|
||||
CHECK_TICK //Same here.
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/process_inner_turf(turf/T)
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/process_edge_turf(turf/T)
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/Initialize()
|
||||
setup_field()
|
||||
post_setup_field()
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/full_cleanup() //Full cleanup for when you change something that would require complete resetting.
|
||||
for(var/turf/T in edge_turfs)
|
||||
cleanup_edge_turf(T)
|
||||
for(var/turf/T in field_turfs)
|
||||
cleanup_field_turf(T)
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/recalculate_field(ignore_movement_check = FALSE) //Call every time the field moves (done automatically if you use update_center) or a setup specification is changed.
|
||||
if(!(ignore_movement_check || ((host.loc != last_host_loc) && (field_shape != FIELD_NO_SHAPE))))
|
||||
return
|
||||
update_new_turfs()
|
||||
var/list/turf/needs_setup = field_turfs_new.Copy()
|
||||
if(setup_field_turfs)
|
||||
for(var/turf/T in field_turfs)
|
||||
if(!(T in needs_setup))
|
||||
cleanup_field_turf(T)
|
||||
else
|
||||
needs_setup -= T
|
||||
CHECK_TICK
|
||||
for(var/turf/T in needs_setup)
|
||||
setup_field_turf(T)
|
||||
CHECK_TICK
|
||||
if(setup_edge_turfs)
|
||||
for(var/turf/T in edge_turfs)
|
||||
cleanup_edge_turf(T)
|
||||
CHECK_TICK
|
||||
for(var/turf/T in edge_turfs_new)
|
||||
setup_edge_turf(T)
|
||||
CHECK_TICK
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/field_turf_canpass(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F, turf/entering)
|
||||
return TRUE
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/field_turf_uncross(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F)
|
||||
return TRUE
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/field_turf_crossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F)
|
||||
return TRUE
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/field_turf_uncrossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F)
|
||||
return TRUE
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/field_edge_canpass(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F, turf/entering)
|
||||
return TRUE
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/field_edge_uncross(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
|
||||
return TRUE
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/field_edge_crossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
|
||||
return TRUE
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/field_edge_uncrossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
|
||||
return TRUE
|
||||
|
||||
/datum/proximity_monitor/advanced/HandleMove()
|
||||
var/atom/_host = host
|
||||
var/atom/new_host_loc = _host.loc
|
||||
if(last_host_loc != new_host_loc)
|
||||
recalculate_field()
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/post_setup_field()
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/setup_field()
|
||||
update_new_turfs()
|
||||
if(setup_field_turfs)
|
||||
for(var/turf/T in field_turfs_new)
|
||||
setup_field_turf(T)
|
||||
CHECK_TICK
|
||||
if(setup_edge_turfs)
|
||||
for(var/turf/T in edge_turfs_new)
|
||||
setup_edge_turf(T)
|
||||
CHECK_TICK
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/cleanup_field_turf(turf/T)
|
||||
qdel(field_turfs[T])
|
||||
field_turfs -= T
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/cleanup_edge_turf(turf/T)
|
||||
qdel(edge_turfs[T])
|
||||
edge_turfs -= T
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/setup_field_turf(turf/T)
|
||||
field_turfs[T] = new /obj/effect/abstract/proximity_checker/advanced/field_turf(T, src)
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/setup_edge_turf(turf/T)
|
||||
edge_turfs[T] = new /obj/effect/abstract/proximity_checker/advanced/field_edge(T, src)
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/update_new_turfs()
|
||||
if(!istype(host))
|
||||
return FALSE
|
||||
last_host_loc = host.loc
|
||||
var/turf/center = get_turf(host)
|
||||
field_turfs_new = list()
|
||||
edge_turfs_new = list()
|
||||
switch(field_shape)
|
||||
if(FIELD_NO_SHAPE)
|
||||
return FALSE
|
||||
if(FIELD_SHAPE_RADIUS_SQUARE)
|
||||
for(var/turf/T in block(locate(center.x-current_range,center.y-current_range,center.z-square_depth_down),locate(center.x+current_range, center.y+current_range,center.z+square_depth_up)))
|
||||
field_turfs_new += T
|
||||
edge_turfs_new = field_turfs_new.Copy()
|
||||
if(current_range >= 1)
|
||||
var/list/turf/center_turfs = list()
|
||||
for(var/turf/T in block(locate(center.x-current_range+1,center.y-current_range+1,center.z-square_depth_down),locate(center.x+current_range-1, center.y+current_range-1,center.z+square_depth_up)))
|
||||
center_turfs += T
|
||||
for(var/turf/T in center_turfs)
|
||||
edge_turfs_new -= T
|
||||
if(FIELD_SHAPE_CUSTOM_SQUARE)
|
||||
for(var/turf/T in block(locate(center.x-square_width,center.y-square_height,center.z-square_depth_down),locate(center.x+square_width, center.y+square_height,center.z+square_depth_up)))
|
||||
field_turfs_new += T
|
||||
edge_turfs_new = field_turfs_new.Copy()
|
||||
if(square_height >= 1 && square_width >= 1)
|
||||
var/list/turf/center_turfs = list()
|
||||
for(var/turf/T in block(locate(center.x-square_width+1,center.y-square_height+1,center.z-square_depth_down),locate(center.x+square_width-1, center.y+square_height-1,center.z+square_depth_up)))
|
||||
center_turfs += T
|
||||
for(var/turf/T in center_turfs)
|
||||
edge_turfs_new -= T
|
||||
|
||||
//Gets edge direction/corner, only works with square radius/WDH fields!
|
||||
/datum/proximity_monitor/advanced/proc/get_edgeturf_direction(turf/T, turf/center_override = null)
|
||||
var/turf/checking_from = get_turf(host)
|
||||
if(istype(center_override))
|
||||
checking_from = center_override
|
||||
if(field_shape != FIELD_SHAPE_RADIUS_SQUARE && field_shape != FIELD_SHAPE_CUSTOM_SQUARE)
|
||||
return
|
||||
if(!(T in edge_turfs))
|
||||
return
|
||||
switch(field_shape)
|
||||
if(FIELD_SHAPE_RADIUS_SQUARE)
|
||||
if(((T.x == (checking_from.x + current_range)) || (T.x == (checking_from.x - current_range))) && ((T.y == (checking_from.y + current_range)) || (T.y == (checking_from.y - current_range))))
|
||||
return get_dir(checking_from, T)
|
||||
if(T.x == (checking_from.x + current_range))
|
||||
return EAST
|
||||
if(T.x == (checking_from.x - current_range))
|
||||
return WEST
|
||||
if(T.y == (checking_from.y - current_range))
|
||||
return SOUTH
|
||||
if(T.y == (checking_from.y + current_range))
|
||||
return NORTH
|
||||
if(FIELD_SHAPE_CUSTOM_SQUARE)
|
||||
if(((T.x == (checking_from.x + square_width)) || (T.x == (checking_from.x - square_width))) && ((T.y == (checking_from.y + square_height)) || (T.y == (checking_from.y - square_height))))
|
||||
return get_dir(checking_from, T)
|
||||
if(T.x == (checking_from.x + square_width))
|
||||
return EAST
|
||||
if(T.x == (checking_from.x - square_width))
|
||||
return WEST
|
||||
if(T.y == (checking_from.y - square_height))
|
||||
return SOUTH
|
||||
if(T.y == (checking_from.y + square_height))
|
||||
return NORTH
|
||||
|
||||
//DEBUG FIELDS
|
||||
/datum/proximity_monitor/advanced/debug
|
||||
name = "\improper Color Matrix Field"
|
||||
field_shape = FIELD_SHAPE_RADIUS_SQUARE
|
||||
current_range = 5
|
||||
var/set_fieldturf_color = "#aaffff"
|
||||
var/set_edgeturf_color = "#ffaaff"
|
||||
setup_field_turfs = TRUE
|
||||
setup_edge_turfs = TRUE
|
||||
|
||||
/datum/proximity_monitor/advanced/debug/recalculate_field()
|
||||
..()
|
||||
|
||||
/datum/proximity_monitor/advanced/debug/post_setup_field()
|
||||
..()
|
||||
|
||||
/datum/proximity_monitor/advanced/debug/setup_edge_turf(turf/T)
|
||||
T.color = set_edgeturf_color
|
||||
..()
|
||||
|
||||
/datum/proximity_monitor/advanced/debug/cleanup_edge_turf(turf/T)
|
||||
T.color = initial(T.color)
|
||||
..()
|
||||
if(T in field_turfs)
|
||||
T.color = set_fieldturf_color
|
||||
|
||||
/datum/proximity_monitor/advanced/debug/setup_field_turf(turf/T)
|
||||
T.color = set_fieldturf_color
|
||||
..()
|
||||
|
||||
/datum/proximity_monitor/advanced/debug/cleanup_field_turf(turf/T)
|
||||
T.color = initial(T.color)
|
||||
..()
|
||||
|
||||
//DEBUG FIELD ITEM
|
||||
/obj/item/device/multitool/field_debug
|
||||
name = "strange multitool"
|
||||
desc = "Seems to project a colored field!"
|
||||
var/list/field_params = list("field_shape" = FIELD_SHAPE_RADIUS_SQUARE, "current_range" = 5, "set_fieldturf_color" = "#aaffff", "set_edgeturf_color" = "#ffaaff")
|
||||
var/field_type = /datum/proximity_monitor/advanced/debug
|
||||
var/operating = FALSE
|
||||
var/datum/proximity_monitor/advanced/current = null
|
||||
|
||||
/obj/item/device/multitool/field_debug/New()
|
||||
START_PROCESSING(SSobj, src)
|
||||
..()
|
||||
|
||||
/obj/item/device/multitool/field_debug/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
QDEL_NULL(current)
|
||||
..()
|
||||
|
||||
/obj/item/device/multitool/field_debug/proc/setup_debug_field()
|
||||
var/list/new_params = field_params.Copy()
|
||||
new_params["host"] = src
|
||||
current = make_field(field_type, new_params)
|
||||
|
||||
/obj/item/device/multitool/field_debug/attack_self(mob/user)
|
||||
operating = !operating
|
||||
to_chat(user, "You turn the [src] [operating? "on":"off"].")
|
||||
if(!istype(current) && operating)
|
||||
setup_debug_field()
|
||||
else if(!operating)
|
||||
QDEL_NULL(current)
|
||||
|
||||
/obj/item/device/multitool/field_debug/on_mob_move()
|
||||
check_turf(get_turf(src))
|
||||
|
||||
/obj/item/device/multitool/field_debug/process()
|
||||
check_turf(get_turf(src))
|
||||
|
||||
/obj/item/device/multitool/field_debug/proc/check_turf(turf/T)
|
||||
current.HandleMove()
|
||||
@@ -0,0 +1,106 @@
|
||||
|
||||
//Projectile dampening field that slows projectiles and lowers their damage for an energy cost deducted every 1/5 second.
|
||||
//Only use square radius for this!
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener
|
||||
name = "\improper Hyperkinetic Dampener Field"
|
||||
requires_processing = TRUE
|
||||
setup_edge_turfs = TRUE
|
||||
setup_field_turfs = TRUE
|
||||
field_shape = FIELD_SHAPE_RADIUS_SQUARE
|
||||
var/static/image/edgeturf_south = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_south")
|
||||
var/static/image/edgeturf_north = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_north")
|
||||
var/static/image/edgeturf_west = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_west")
|
||||
var/static/image/edgeturf_east = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_east")
|
||||
var/static/image/northwest_corner = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_northwest")
|
||||
var/static/image/southwest_corner = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_southwest")
|
||||
var/static/image/northeast_corner = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_northeast")
|
||||
var/static/image/southeast_corner = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_southeast")
|
||||
var/obj/item/borg/projectile_dampen/projector = null
|
||||
var/list/obj/item/projectile/tracked
|
||||
var/list/obj/item/projectile/staging
|
||||
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener/New()
|
||||
tracked = list()
|
||||
staging = list()
|
||||
..()
|
||||
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener/process()
|
||||
if(!istype(projector))
|
||||
qdel(src)
|
||||
var/list/ranged = list()
|
||||
for(var/obj/item/projectile/P in range(current_range, get_turf(host)))
|
||||
ranged += P
|
||||
for(var/obj/item/projectile/P in tracked)
|
||||
if(!(P in ranged) || !P.loc)
|
||||
release_projectile(P)
|
||||
for(var/mob/living/silicon/robot/R in range(current_range, get_turf(host)))
|
||||
if(R.has_buckled_mobs())
|
||||
for(var/mob/living/L in R.buckled_mobs)
|
||||
L.visible_message("<span class='warning'>[L] is knocked off of [R] by the charge in [R]'s chassis induced by [name]!</span>") //I know it's bad.
|
||||
L.Weaken(3)
|
||||
R.unbuckle_mob(L)
|
||||
do_sparks(5, 0, L)
|
||||
..()
|
||||
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener/setup_edge_turf(turf/T)
|
||||
..()
|
||||
var/image/I = get_edgeturf_overlay(get_edgeturf_direction(T))
|
||||
var/obj/effect/abstract/proximity_checker/advanced/F = edge_turfs[T]
|
||||
F.appearance = I.appearance
|
||||
F.invisibility = 0
|
||||
F.layer = 5
|
||||
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener/cleanup_edge_turf(turf/T)
|
||||
..()
|
||||
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener/proc/get_edgeturf_overlay(direction)
|
||||
switch(direction)
|
||||
if(NORTH)
|
||||
return edgeturf_north
|
||||
if(SOUTH)
|
||||
return edgeturf_south
|
||||
if(EAST)
|
||||
return edgeturf_east
|
||||
if(WEST)
|
||||
return edgeturf_west
|
||||
if(NORTHEAST)
|
||||
return northeast_corner
|
||||
if(NORTHWEST)
|
||||
return northwest_corner
|
||||
if(SOUTHEAST)
|
||||
return southeast_corner
|
||||
if(SOUTHWEST)
|
||||
return southwest_corner
|
||||
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener/proc/capture_projectile(obj/item/projectile/P, track_projectile = TRUE)
|
||||
if(P in tracked)
|
||||
return
|
||||
projector.dampen_projectile(P, track_projectile)
|
||||
if(track_projectile)
|
||||
tracked += P
|
||||
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener/proc/release_projectile(obj/item/projectile/P)
|
||||
projector.restore_projectile(P)
|
||||
tracked -= P
|
||||
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener/field_edge_uncrossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
|
||||
if(!is_turf_in_field(get_turf(AM), src))
|
||||
if(istype(AM, /obj/item/projectile))
|
||||
if(AM in tracked)
|
||||
release_projectile(AM)
|
||||
else
|
||||
capture_projectile(AM, FALSE)
|
||||
return ..()
|
||||
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener/field_edge_crossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
|
||||
if(istype(AM, /obj/item/projectile) && !(AM in tracked) && staging[AM] && !is_turf_in_field(staging[AM], src))
|
||||
capture_projectile(AM)
|
||||
staging -= AM
|
||||
return ..()
|
||||
|
||||
/datum/proximity_monitor/advanced/peaceborg_dampener/field_edge_canpass(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F, turf/entering)
|
||||
if(istype(AM, /obj/item/projectile))
|
||||
staging[AM] = get_turf(AM)
|
||||
. = ..()
|
||||
if(!.)
|
||||
staging -= AM //This one ain't goin' through.
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced
|
||||
name = "field"
|
||||
desc = "Why can you see energy fields?!"
|
||||
icon = null
|
||||
icon_state = null
|
||||
alpha = 0
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
flags = ABSTRACT|ON_BORDER
|
||||
var/datum/proximity_monitor/advanced/parent = null
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/Initialize(mapload, _monitor)
|
||||
if(_monitor)
|
||||
parent = _monitor
|
||||
return ..()
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/center
|
||||
name = "field anchor"
|
||||
desc = "No."
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/field_turf
|
||||
name = "energy field"
|
||||
desc = "Get off my turf!"
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/field_turf/CanPass(atom/movable/AM, turf/target, height)
|
||||
if(parent)
|
||||
return parent.field_turf_canpass(AM, src, target)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/field_turf/Crossed(atom/movable/AM)
|
||||
if(parent)
|
||||
return parent.field_turf_crossed(AM, src)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/field_turf/Uncross(atom/movable/AM)
|
||||
if(parent)
|
||||
return parent.field_turf_uncross(AM, src)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/field_turf/Uncrossed(atom/movable/AM)
|
||||
if(parent)
|
||||
return parent.field_turf_uncrossed(AM, src)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/field_edge
|
||||
name = "energy field edge"
|
||||
desc = "Edgy description here."
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/field_edge/CanPass(atom/movable/AM, turf/target, height)
|
||||
if(parent)
|
||||
return parent.field_edge_canpass(AM, src, target)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/field_edge/Crossed(atom/movable/AM)
|
||||
if(parent)
|
||||
return parent.field_edge_crossed(AM, src)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/field_edge/Uncross(atom/movable/AM)
|
||||
if(parent)
|
||||
return parent.field_edge_uncross(AM, src)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/abstract/proximity_checker/advanced/field_edge/Uncrossed(atom/movable/AM)
|
||||
if(parent)
|
||||
return parent.field_edge_uncrossed(AM, src)
|
||||
return TRUE
|
||||
|
||||
/proc/is_turf_in_field(turf/T, datum/proximity_monitor/advanced/F) //Looking for ways to optimize this!
|
||||
for(var/obj/effect/abstract/proximity_checker/advanced/O in T)
|
||||
if(istype(O, /obj/effect/abstract/proximity_checker/advanced/field_edge))
|
||||
if(O.parent == F)
|
||||
return FIELD_EDGE
|
||||
if(O.parent == F)
|
||||
return FIELD_TURF
|
||||
return NO_FIELD
|
||||
@@ -135,7 +135,6 @@
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/customizable/initialize_slice(obj/item/weapon/reagent_containers/food/snacks/slice, reagents_per_slice)
|
||||
..()
|
||||
slice.name = "[customname] [initial(slice.name)]"
|
||||
slice.filling_color = filling_color
|
||||
slice.update_overlays(src)
|
||||
|
||||
|
||||
@@ -215,8 +215,9 @@
|
||||
/obj/item/weapon/reagent_containers/food/snacks/proc/initialize_slice(obj/item/weapon/reagent_containers/food/snacks/slice, reagents_per_slice)
|
||||
slice.create_reagents(slice.volume)
|
||||
reagents.trans_to(slice,reagents_per_slice)
|
||||
if( name != initial(name) || desc != initial(desc) )
|
||||
slice.name = "slice of [src]"
|
||||
if(name != initial(name))
|
||||
slice.name = "slice of [name]"
|
||||
if(desc != initial(desc))
|
||||
slice.desc = "[desc]"
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/proc/generate_trash(atom/location)
|
||||
|
||||
@@ -174,7 +174,6 @@
|
||||
var/mob/living/carbon/human/gibee = occupant
|
||||
sourcejob = gibee.job
|
||||
var/sourcenutriment = mob_occupant.nutrition / 15
|
||||
var/sourcetotalreagents = mob_occupant.reagents.total_volume
|
||||
var/gibtype = /obj/effect/decal/cleanable/blood/gibs
|
||||
var/typeofmeat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human
|
||||
var/typeofskin = /obj/item/stack/sheet/animalhide/human
|
||||
@@ -207,7 +206,6 @@
|
||||
newmeat.reagents.add_reagent ("nutriment", sourcenutriment / meat_produced) // Thehehe. Fat guys go first
|
||||
if(sourcejob)
|
||||
newmeat.subjectjob = sourcejob
|
||||
src.occupant.reagents.trans_to (newmeat, round (sourcetotalreagents / meat_produced, 1)) // Transfer all the reagents from the
|
||||
allmeat[i] = newmeat
|
||||
allskin = newskin
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
#define BAD_ZLEVEL 1
|
||||
#define BAD_AREA 2
|
||||
#define ZONE_SET 3
|
||||
#define BAD_COORDS 3
|
||||
#define ZONE_SET 4
|
||||
|
||||
/area/shuttle/auxillary_base
|
||||
name = "Auxillary Base"
|
||||
@@ -149,6 +150,9 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
|
||||
if(T.z != ZLEVEL_MINING)
|
||||
return BAD_ZLEVEL
|
||||
var/colony_radius = max(base_dock.width, base_dock.height)*0.5
|
||||
if(T.x - colony_radius < 1 || T.x + colony_radius >= world.maxx || T.y - colony_radius < 1 || T.y + colony_radius >= world.maxx)
|
||||
return BAD_COORDS //Avoid dropping the base too close to map boundaries, as it results in parts of it being left in space
|
||||
|
||||
var/list/area_counter = get_areas_in_range(colony_radius, T)
|
||||
if(area_counter.len > 1) //Avoid smashing ruins unless you are inside a really big one
|
||||
return BAD_AREA
|
||||
@@ -195,6 +199,7 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
|
||||
if(!do_after(user, 50, target = user)) //You get a few seconds to cancel if you do not want to drop there.
|
||||
setting = FALSE
|
||||
return
|
||||
setting = FALSE
|
||||
|
||||
var/turf/T = get_turf(user)
|
||||
var/obj/machinery/computer/auxillary_base/AB
|
||||
@@ -212,6 +217,8 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
|
||||
to_chat(user, "<span class='warning'>This uplink can only be used in a designed mining zone.</span>")
|
||||
if(BAD_AREA)
|
||||
to_chat(user, "<span class='warning'>Unable to acquire a targeting lock. Find an area clear of stuctures or entirely within one.</span>")
|
||||
if(BAD_COORDS)
|
||||
to_chat(user, "<span class='warning'>Location is too close to the edge of the station's scanning range. Move several paces away and try again.</span>")
|
||||
if(ZONE_SET)
|
||||
qdel(src)
|
||||
|
||||
@@ -347,4 +354,5 @@ obj/docking_port/stationary/public_mining_dock/onShuttleMove()
|
||||
|
||||
#undef BAD_ZLEVEL
|
||||
#undef BAD_AREA
|
||||
#undef BAD_COORDS
|
||||
#undef ZONE_SET
|
||||
@@ -1,5 +1,6 @@
|
||||
//The chests dropped by mob spawner tendrils. Also contains associated loot.
|
||||
|
||||
|
||||
/obj/structure/closet/crate/necropolis
|
||||
name = "necropolis chest"
|
||||
desc = "It's watching you closely."
|
||||
@@ -821,6 +822,8 @@
|
||||
if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one!
|
||||
chaser_timer = world.time + chaser_cooldown
|
||||
new /obj/effect/temp_visual/hierophant/chaser(get_turf(user), user, target, chaser_speed, friendly_fire_check)
|
||||
C.damage = 30
|
||||
C.monster_damage_boost = FALSE
|
||||
add_logs(user, target, "fired a chaser at", src)
|
||||
else
|
||||
INVOKE_ASYNC(src, .proc/cardinal_blasts, T, user) //otherwise, just do cardinal blast
|
||||
@@ -1005,6 +1008,8 @@
|
||||
if(!J)
|
||||
return
|
||||
new /obj/effect/temp_visual/hierophant/blast(J, user, friendly_fire_check)
|
||||
B.damage = 30
|
||||
B.monster_damage_boost = FALSE
|
||||
previousturf = J
|
||||
J = get_step(previousturf, dir)
|
||||
|
||||
@@ -1016,3 +1021,4 @@
|
||||
sleep(2)
|
||||
for(var/t in RANGE_TURFS(1, T))
|
||||
new /obj/effect/temp_visual/hierophant/blast(t, user, friendly_fire_check)
|
||||
B.damage = 15 //keeps monster damage boost due to lower damage
|
||||
|
||||
@@ -17,4 +17,4 @@
|
||||
/mob/living/carbon/alien/AdjustStunned(amount, updating = 1, ignore_canstun = 0)
|
||||
. = ..()
|
||||
if(!.)
|
||||
move_delay_add = min(move_delay_add + round(amount / 2), 10)
|
||||
move_delay_add = Clamp(move_delay_add + round(amount/2), 0, 10)
|
||||
|
||||
@@ -823,7 +823,7 @@
|
||||
|
||||
/mob/living/proc/has_bane(banetype)
|
||||
var/datum/antagonist/devil/devilInfo = is_devil(src)
|
||||
return (banetype == devilInfo.bane)
|
||||
return devilInfo && banetype == devilInfo.bane
|
||||
|
||||
/mob/living/proc/check_weakness(obj/item/weapon, mob/living/attacker)
|
||||
if(mind && mind.has_antag_datum(ANTAG_DATUM_DEVIL))
|
||||
|
||||
@@ -1,361 +1,370 @@
|
||||
|
||||
/mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = null, soften_text = null, armour_penetration, penetrated_text)
|
||||
var/armor = getarmor(def_zone, attack_flag)
|
||||
|
||||
//the if "armor" check is because this is used for everything on /living, including humans
|
||||
if(armor && armour_penetration)
|
||||
armor = max(0, armor - armour_penetration)
|
||||
if(penetrated_text)
|
||||
to_chat(src, "<span class='userdanger'>[penetrated_text]</span>")
|
||||
else
|
||||
to_chat(src, "<span class='userdanger'>Your armor was penetrated!</span>")
|
||||
else if(armor >= 100)
|
||||
if(absorb_text)
|
||||
to_chat(src, "<span class='userdanger'>[absorb_text]</span>")
|
||||
else
|
||||
to_chat(src, "<span class='userdanger'>Your armor absorbs the blow!</span>")
|
||||
else if(armor > 0)
|
||||
if(soften_text)
|
||||
to_chat(src, "<span class='userdanger'>[soften_text]</span>")
|
||||
else
|
||||
to_chat(src, "<span class='userdanger'>Your armor softens the blow!</span>")
|
||||
return armor
|
||||
|
||||
|
||||
/mob/living/proc/getarmor(def_zone, type)
|
||||
return 0
|
||||
|
||||
//this returns the mob's protection against eye damage (number between -1 and 2)
|
||||
/mob/living/proc/get_eye_protection()
|
||||
return 0
|
||||
|
||||
//this returns the mob's protection against ear damage (0:no protection; 1: some ear protection; 2: has no ears)
|
||||
/mob/living/proc/get_ear_protection()
|
||||
return 0
|
||||
|
||||
/mob/living/proc/on_hit(obj/item/projectile/P)
|
||||
return
|
||||
|
||||
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
|
||||
var/armor = run_armor_check(def_zone, P.flag, "","",P.armour_penetration)
|
||||
if(!P.nodamage)
|
||||
apply_damage(P.damage, P.damage_type, def_zone, armor)
|
||||
if(P.dismemberment)
|
||||
check_projectile_dismemberment(P, def_zone)
|
||||
return P.on_hit(src, armor)
|
||||
|
||||
/mob/living/proc/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
|
||||
return 0
|
||||
|
||||
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
|
||||
if(throwforce && w_class)
|
||||
return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
|
||||
else if(w_class)
|
||||
return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
|
||||
else
|
||||
return 0
|
||||
|
||||
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
|
||||
var/dtype = BRUTE
|
||||
var/volume = I.get_volume_by_throwforce_and_or_w_class()
|
||||
if(istype(I,/obj/item/weapon)) //If the item is a weapon...
|
||||
var/obj/item/weapon/W = I
|
||||
dtype = W.damtype
|
||||
|
||||
if (W.throwforce > 0) //If the weapon's throwforce is greater than zero...
|
||||
if (W.throwhitsound) //...and throwhitsound is defined...
|
||||
playsound(loc, W.throwhitsound, volume, 1, -1) //...play the weapon's throwhitsound.
|
||||
else if(W.hitsound) //Otherwise, if the weapon's hitsound is defined...
|
||||
playsound(loc, W.hitsound, volume, 1, -1) //...play the weapon's hitsound.
|
||||
else if(!W.throwhitsound) //Otherwise, if throwhitsound isn't defined...
|
||||
playsound(loc, 'sound/weapons/genhit.ogg',volume, 1, -1) //...play genhit.ogg.
|
||||
|
||||
else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero...
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', volume, 1, -1)//...play genhit.ogg
|
||||
if(!I.throwforce)// Otherwise, if the item's throwforce is 0...
|
||||
playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg.
|
||||
if(!blocked)
|
||||
visible_message("<span class='danger'>[src] has been hit by [I].</span>", \
|
||||
"<span class='userdanger'>[src] has been hit by [I].</span>")
|
||||
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
|
||||
apply_damage(I.throwforce, dtype, zone, armor)
|
||||
if(I.thrownby)
|
||||
add_logs(I.thrownby, src, "hit", I)
|
||||
else
|
||||
return 1
|
||||
else
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/mech_melee_attack(obj/mecha/M)
|
||||
if(M.occupant.a_intent == INTENT_HARM)
|
||||
M.do_attack_animation(src)
|
||||
if(M.damtype == "brute")
|
||||
step_away(src,M,15)
|
||||
switch(M.damtype)
|
||||
if(BRUTE)
|
||||
Paralyse(1)
|
||||
take_overall_damage(rand(M.force/2, M.force))
|
||||
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
|
||||
if(BURN)
|
||||
take_overall_damage(0, rand(M.force/2, M.force))
|
||||
playsound(src, 'sound/items/Welder.ogg', 50, 1)
|
||||
if(TOX)
|
||||
M.mech_toxin_damage(src)
|
||||
else
|
||||
return
|
||||
updatehealth()
|
||||
visible_message("<span class='danger'>[M.name] has hit [src]!</span>", \
|
||||
"<span class='userdanger'>[M.name] has hit [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
|
||||
else
|
||||
step_away(src,M)
|
||||
add_logs(M.occupant, src, "pushed", M)
|
||||
visible_message("<span class='warning'>[M] pushes [src] out of the way.</span>", null, null, 5)
|
||||
|
||||
/mob/living/fire_act()
|
||||
adjust_fire_stacks(3)
|
||||
IgniteMob()
|
||||
|
||||
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0)
|
||||
if(user == src || anchored || !isturf(user.loc))
|
||||
return 0
|
||||
if(!user.pulling || user.pulling != src)
|
||||
user.start_pulling(src, supress_message)
|
||||
return
|
||||
|
||||
if(!(status_flags & CANPUSH))
|
||||
to_chat(user, "<span class='warning'>[src] can't be grabbed more aggressively!</span>")
|
||||
return 0
|
||||
grippedby(user)
|
||||
|
||||
//proc to upgrade a simple pull into a more aggressive grab.
|
||||
/mob/living/proc/grippedby(mob/living/carbon/user)
|
||||
if(user.grab_state < GRAB_KILL)
|
||||
user.changeNext_move(CLICK_CD_GRABBING)
|
||||
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
if(user.grab_state) //only the first upgrade is instantaneous
|
||||
var/old_grab_state = user.grab_state
|
||||
var/grab_upgrade_time = 30
|
||||
visible_message("<span class='danger'>[user] starts to tighten [user.p_their()] grip on [src]!</span>", \
|
||||
"<span class='userdanger'>[user] starts to tighten [user.p_their()] grip on you!</span>")
|
||||
if(!do_mob(user, src, grab_upgrade_time))
|
||||
return 0
|
||||
if(!user.pulling || user.pulling != src || user.grab_state != old_grab_state || user.a_intent != INTENT_GRAB)
|
||||
return 0
|
||||
user.grab_state++
|
||||
switch(user.grab_state)
|
||||
if(GRAB_AGGRESSIVE)
|
||||
add_logs(user, src, "grabbed", addition="aggressively")
|
||||
visible_message("<span class='danger'>[user] has grabbed [src] aggressively!</span>", \
|
||||
"<span class='userdanger'>[user] has grabbed [src] aggressively!</span>")
|
||||
drop_all_held_items()
|
||||
stop_pulling()
|
||||
if(GRAB_NECK)
|
||||
visible_message("<span class='danger'>[user] has grabbed [src] by the neck!</span>",\
|
||||
"<span class='userdanger'>[user] has grabbed you by the neck!</span>")
|
||||
update_canmove() //we fall down
|
||||
if(!buckled && !density)
|
||||
Move(user.loc)
|
||||
if(GRAB_KILL)
|
||||
visible_message("<span class='danger'>[user] is strangling [src]!</span>", \
|
||||
"<span class='userdanger'>[user] is strangling you!</span>")
|
||||
update_canmove() //we fall down
|
||||
if(!buckled && !density)
|
||||
Move(user.loc)
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
|
||||
|
||||
/mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = null, soften_text = null, armour_penetration, penetrated_text)
|
||||
var/armor = getarmor(def_zone, attack_flag)
|
||||
|
||||
//the if "armor" check is because this is used for everything on /living, including humans
|
||||
if(armor && armour_penetration)
|
||||
armor = max(0, armor - armour_penetration)
|
||||
if(penetrated_text)
|
||||
to_chat(src, "<span class='userdanger'>[penetrated_text]</span>")
|
||||
else
|
||||
to_chat(src, "<span class='userdanger'>Your armor was penetrated!</span>")
|
||||
else if(armor >= 100)
|
||||
if(absorb_text)
|
||||
to_chat(src, "<span class='userdanger'>[absorb_text]</span>")
|
||||
else
|
||||
to_chat(src, "<span class='userdanger'>Your armor absorbs the blow!</span>")
|
||||
else if(armor > 0)
|
||||
if(soften_text)
|
||||
to_chat(src, "<span class='userdanger'>[soften_text]</span>")
|
||||
else
|
||||
to_chat(src, "<span class='userdanger'>Your armor softens the blow!</span>")
|
||||
return armor
|
||||
|
||||
|
||||
/mob/living/proc/getarmor(def_zone, type)
|
||||
return 0
|
||||
|
||||
//this returns the mob's protection against eye damage (number between -1 and 2)
|
||||
/mob/living/proc/get_eye_protection()
|
||||
return 0
|
||||
|
||||
//this returns the mob's protection against ear damage (0:no protection; 1: some ear protection; 2: has no ears)
|
||||
/mob/living/proc/get_ear_protection()
|
||||
return 0
|
||||
|
||||
/mob/living/proc/on_hit(obj/item/projectile/P)
|
||||
return
|
||||
|
||||
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
|
||||
var/armor = run_armor_check(def_zone, P.flag, "","",P.armour_penetration)
|
||||
if(!P.nodamage)
|
||||
apply_damage(P.damage, P.damage_type, def_zone, armor)
|
||||
if(P.dismemberment)
|
||||
check_projectile_dismemberment(P, def_zone)
|
||||
return P.on_hit(src, armor)
|
||||
|
||||
/mob/living/proc/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
|
||||
return 0
|
||||
|
||||
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
|
||||
if(throwforce && w_class)
|
||||
return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
|
||||
else if(w_class)
|
||||
return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
|
||||
else
|
||||
return 0
|
||||
|
||||
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
|
||||
var/dtype = BRUTE
|
||||
var/volume = I.get_volume_by_throwforce_and_or_w_class()
|
||||
if(istype(I,/obj/item/weapon)) //If the item is a weapon...
|
||||
var/obj/item/weapon/W = I
|
||||
dtype = W.damtype
|
||||
|
||||
if (W.throwforce > 0) //If the weapon's throwforce is greater than zero...
|
||||
if (W.throwhitsound) //...and throwhitsound is defined...
|
||||
playsound(loc, W.throwhitsound, volume, 1, -1) //...play the weapon's throwhitsound.
|
||||
else if(W.hitsound) //Otherwise, if the weapon's hitsound is defined...
|
||||
playsound(loc, W.hitsound, volume, 1, -1) //...play the weapon's hitsound.
|
||||
else if(!W.throwhitsound) //Otherwise, if throwhitsound isn't defined...
|
||||
playsound(loc, 'sound/weapons/genhit.ogg',volume, 1, -1) //...play genhit.ogg.
|
||||
|
||||
else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero...
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', volume, 1, -1)//...play genhit.ogg
|
||||
if(!I.throwforce)// Otherwise, if the item's throwforce is 0...
|
||||
playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg.
|
||||
if(!blocked)
|
||||
visible_message("<span class='danger'>[src] has been hit by [I].</span>", \
|
||||
"<span class='userdanger'>[src] has been hit by [I].</span>")
|
||||
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
|
||||
apply_damage(I.throwforce, dtype, zone, armor)
|
||||
if(I.thrownby)
|
||||
add_logs(I.thrownby, src, "hit", I)
|
||||
else
|
||||
return 1
|
||||
else
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/mech_melee_attack(obj/mecha/M)
|
||||
if(M.occupant.a_intent == INTENT_HARM)
|
||||
M.do_attack_animation(src)
|
||||
if(M.damtype == "brute")
|
||||
step_away(src,M,15)
|
||||
switch(M.damtype)
|
||||
if(BRUTE)
|
||||
Paralyse(1)
|
||||
take_overall_damage(rand(M.force/2, M.force))
|
||||
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
|
||||
if(BURN)
|
||||
take_overall_damage(0, rand(M.force/2, M.force))
|
||||
playsound(src, 'sound/items/Welder.ogg', 50, 1)
|
||||
if(TOX)
|
||||
M.mech_toxin_damage(src)
|
||||
else
|
||||
return
|
||||
updatehealth()
|
||||
visible_message("<span class='danger'>[M.name] has hit [src]!</span>", \
|
||||
"<span class='userdanger'>[M.name] has hit [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
|
||||
else
|
||||
step_away(src,M)
|
||||
add_logs(M.occupant, src, "pushed", M)
|
||||
visible_message("<span class='warning'>[M] pushes [src] out of the way.</span>", null, null, 5)
|
||||
|
||||
/mob/living/fire_act()
|
||||
adjust_fire_stacks(3)
|
||||
IgniteMob()
|
||||
|
||||
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0)
|
||||
if(user == src || anchored || !isturf(user.loc))
|
||||
return 0
|
||||
if(!user.pulling || user.pulling != src)
|
||||
user.start_pulling(src, supress_message)
|
||||
return
|
||||
|
||||
if(!(status_flags & CANPUSH))
|
||||
to_chat(user, "<span class='warning'>[src] can't be grabbed more aggressively!</span>")
|
||||
return 0
|
||||
grippedby(user)
|
||||
|
||||
//proc to upgrade a simple pull into a more aggressive grab.
|
||||
/mob/living/proc/grippedby(mob/living/carbon/user)
|
||||
if(user.grab_state < GRAB_KILL)
|
||||
user.changeNext_move(CLICK_CD_GRABBING)
|
||||
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
if(user.grab_state) //only the first upgrade is instantaneous
|
||||
var/old_grab_state = user.grab_state
|
||||
var/grab_upgrade_time = 30
|
||||
visible_message("<span class='danger'>[user] starts to tighten [user.p_their()] grip on [src]!</span>", \
|
||||
"<span class='userdanger'>[user] starts to tighten [user.p_their()] grip on you!</span>")
|
||||
if(!do_mob(user, src, grab_upgrade_time))
|
||||
return 0
|
||||
if(!user.pulling || user.pulling != src || user.grab_state != old_grab_state || user.a_intent != INTENT_GRAB)
|
||||
return 0
|
||||
user.grab_state++
|
||||
switch(user.grab_state)
|
||||
if(GRAB_AGGRESSIVE)
|
||||
add_logs(user, src, "grabbed", addition="aggressively")
|
||||
visible_message("<span class='danger'>[user] has grabbed [src] aggressively!</span>", \
|
||||
"<span class='userdanger'>[user] has grabbed [src] aggressively!</span>")
|
||||
drop_all_held_items()
|
||||
stop_pulling()
|
||||
if(GRAB_NECK)
|
||||
visible_message("<span class='danger'>[user] has grabbed [src] by the neck!</span>",\
|
||||
"<span class='userdanger'>[user] has grabbed you by the neck!</span>")
|
||||
update_canmove() //we fall down
|
||||
if(!buckled && !density)
|
||||
Move(user.loc)
|
||||
if(GRAB_KILL)
|
||||
visible_message("<span class='danger'>[user] is strangling [src]!</span>", \
|
||||
"<span class='userdanger'>[user] is strangling you!</span>")
|
||||
update_canmove() //we fall down
|
||||
if(!buckled && !density)
|
||||
Move(user.loc)
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(!SSticker.HasRoundStarted())
|
||||
to_chat(M, "You cannot attack people before the game has started.")
|
||||
return
|
||||
|
||||
if(M.buckled)
|
||||
if(M in buckled_mobs)
|
||||
M.Feedstop()
|
||||
return // can't attack while eating!
|
||||
|
||||
if (stat != DEAD)
|
||||
add_logs(M, src, "attacked")
|
||||
M.do_attack_animation(src)
|
||||
visible_message("<span class='danger'>The [M.name] glomps [src]!</span>", \
|
||||
"<span class='userdanger'>The [M.name] glomps [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 1
|
||||
|
||||
/mob/living/attack_animal(mob/living/simple_animal/M)
|
||||
M.face_atom(src)
|
||||
if(M.melee_damage_upper == 0)
|
||||
M.visible_message("<span class='notice'>\The [M] [M.friendly] [src]!</span>")
|
||||
return 0
|
||||
else
|
||||
if(M.attack_sound)
|
||||
playsound(loc, M.attack_sound, 50, 1, 1)
|
||||
M.do_attack_animation(src)
|
||||
visible_message("<span class='danger'>\The [M] [M.attacktext] [src]!</span>", \
|
||||
"<span class='userdanger'>\The [M] [M.attacktext] [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
add_logs(M, src, "attacked")
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/attack_paw(mob/living/carbon/monkey/M)
|
||||
if(isturf(loc) && istype(loc.loc, /area/start))
|
||||
to_chat(M, "No attacking people at spawn, you jackass.")
|
||||
return 0
|
||||
|
||||
if (M.a_intent == INTENT_HARM)
|
||||
if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
|
||||
to_chat(M, "<span class='warning'>You can't bite with your mouth covered!</span>")
|
||||
return 0
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
|
||||
if (prob(75))
|
||||
add_logs(M, src, "attacked")
|
||||
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
|
||||
visible_message("<span class='danger'>[M.name] bites [src]!</span>", \
|
||||
"<span class='userdanger'>[M.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 1
|
||||
else
|
||||
visible_message("<span class='danger'>[M.name] has attempted to bite [src]!</span>", \
|
||||
"<span class='userdanger'>[M.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 0
|
||||
|
||||
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
switch(L.a_intent)
|
||||
if("help")
|
||||
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
|
||||
return 0
|
||||
|
||||
else
|
||||
L.do_attack_animation(src)
|
||||
if(prob(90))
|
||||
add_logs(L, src, "attacked")
|
||||
visible_message("<span class='danger'>[L.name] bites [src]!</span>", \
|
||||
"<span class='userdanger'>[L.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
|
||||
return 1
|
||||
else
|
||||
visible_message("<span class='danger'>[L.name] has attempted to bite [src]!</span>", \
|
||||
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 0
|
||||
|
||||
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
switch(M.a_intent)
|
||||
if ("help")
|
||||
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
|
||||
return 0
|
||||
|
||||
if ("grab")
|
||||
grabbedby(M)
|
||||
return 0
|
||||
if("harm")
|
||||
M.do_attack_animation(src)
|
||||
return 1
|
||||
if("disarm")
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
return 1
|
||||
|
||||
/mob/living/ex_act(severity, target, origin)
|
||||
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
|
||||
return
|
||||
..()
|
||||
|
||||
//Looking for irradiate()? It's been moved to radiation.dm under the rad_act() for mobs.
|
||||
|
||||
/mob/living/acid_act(acidpwr, acid_volume)
|
||||
take_bodypart_damage(acidpwr * min(1, acid_volume * 0.1))
|
||||
return 1
|
||||
|
||||
/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
|
||||
to_chat(M, "You cannot attack people before the game has started.")
|
||||
return
|
||||
|
||||
if(M.buckled)
|
||||
if(M in buckled_mobs)
|
||||
M.Feedstop()
|
||||
return // can't attack while eating!
|
||||
|
||||
if (stat != DEAD)
|
||||
add_logs(M, src, "attacked")
|
||||
M.do_attack_animation(src)
|
||||
visible_message("<span class='danger'>The [M.name] glomps [src]!</span>", \
|
||||
"<span class='userdanger'>The [M.name] glomps [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 1
|
||||
|
||||
/mob/living/attack_animal(mob/living/simple_animal/M)
|
||||
M.face_atom(src)
|
||||
if(M.melee_damage_upper == 0)
|
||||
M.visible_message("<span class='notice'>\The [M] [M.friendly] [src]!</span>")
|
||||
return 0
|
||||
else
|
||||
if(M.attack_sound)
|
||||
playsound(loc, M.attack_sound, 50, 1, 1)
|
||||
M.do_attack_animation(src)
|
||||
visible_message("<span class='danger'>\The [M] [M.attacktext] [src]!</span>", \
|
||||
"<span class='userdanger'>\The [M] [M.attacktext] [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
add_logs(M, src, "attacked")
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/attack_paw(mob/living/carbon/monkey/M)
|
||||
if(isturf(loc) && istype(loc.loc, /area/start))
|
||||
to_chat(M, "No attacking people at spawn, you jackass.")
|
||||
return 0
|
||||
|
||||
if (M.a_intent == INTENT_HARM)
|
||||
if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
|
||||
to_chat(M, "<span class='warning'>You can't bite with your mouth covered!</span>")
|
||||
return 0
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
|
||||
if (prob(75))
|
||||
add_logs(M, src, "attacked")
|
||||
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
|
||||
visible_message("<span class='danger'>[M.name] bites [src]!</span>", \
|
||||
"<span class='userdanger'>[M.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 1
|
||||
else
|
||||
visible_message("<span class='danger'>[M.name] has attempted to bite [src]!</span>", \
|
||||
"<span class='userdanger'>[M.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 0
|
||||
|
||||
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
switch(L.a_intent)
|
||||
if("help")
|
||||
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
|
||||
return 0
|
||||
|
||||
else
|
||||
L.do_attack_animation(src)
|
||||
if(prob(90))
|
||||
add_logs(L, src, "attacked")
|
||||
visible_message("<span class='danger'>[L.name] bites [src]!</span>", \
|
||||
"<span class='userdanger'>[L.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
|
||||
return 1
|
||||
else
|
||||
visible_message("<span class='danger'>[L.name] has attempted to bite [src]!</span>", \
|
||||
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 0
|
||||
|
||||
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
switch(M.a_intent)
|
||||
if ("help")
|
||||
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
|
||||
return 0
|
||||
|
||||
if ("grab")
|
||||
grabbedby(M)
|
||||
return 0
|
||||
if("harm")
|
||||
M.do_attack_animation(src)
|
||||
return 1
|
||||
if("disarm")
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
return 1
|
||||
|
||||
/mob/living/ex_act(severity, target, origin)
|
||||
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
|
||||
return
|
||||
..()
|
||||
|
||||
//Looking for irradiate()? It's been moved to radiation.dm under the rad_act() for mobs.
|
||||
|
||||
/mob/living/acid_act(acidpwr, acid_volume)
|
||||
take_bodypart_damage(acidpwr * min(1, acid_volume * 0.1))
|
||||
return 1
|
||||
|
||||
/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
|
||||
if(tesla_shock && HAS_SECONDARY_FLAG(src, TESLA_IGNORE))
|
||||
return FALSE
|
||||
if(shock_damage > 0)
|
||||
if(!illusion)
|
||||
adjustFireLoss(shock_damage)
|
||||
visible_message(
|
||||
"<span class='danger'>[src] was shocked by \the [source]!</span>", \
|
||||
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
|
||||
"<span class='italics'>You hear a heavy electrical crack.</span>" \
|
||||
)
|
||||
return shock_damage
|
||||
|
||||
/mob/living/emp_act(severity)
|
||||
var/list/L = src.get_contents()
|
||||
for(var/obj/O in L)
|
||||
O.emp_act(severity)
|
||||
..()
|
||||
|
||||
/mob/living/singularity_act()
|
||||
var/gain = 20
|
||||
investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up!
|
||||
gib()
|
||||
return(gain)
|
||||
|
||||
/mob/living/narsie_act()
|
||||
if(status_flags & GODMODE)
|
||||
return
|
||||
|
||||
if(is_servant_of_ratvar(src) && !stat)
|
||||
to_chat(src, "<span class='userdanger'>You resist Nar-Sie's influence... but not all of it. <i>Run!</i></span>")
|
||||
adjustBruteLoss(35)
|
||||
if(src && reagents)
|
||||
reagents.add_reagent("heparin", 5)
|
||||
return FALSE
|
||||
if(client)
|
||||
return FALSE
|
||||
if(shock_damage > 0)
|
||||
if(!illusion)
|
||||
adjustFireLoss(shock_damage)
|
||||
visible_message(
|
||||
"<span class='danger'>[src] was shocked by \the [source]!</span>", \
|
||||
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
|
||||
"<span class='italics'>You hear a heavy electrical crack.</span>" \
|
||||
)
|
||||
return shock_damage
|
||||
|
||||
/mob/living/emp_act(severity)
|
||||
var/list/L = src.get_contents()
|
||||
for(var/obj/O in L)
|
||||
O.emp_act(severity)
|
||||
..()
|
||||
|
||||
/mob/living/singularity_act()
|
||||
var/gain = 20
|
||||
investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up!
|
||||
gib()
|
||||
return(gain)
|
||||
|
||||
/mob/living/narsie_act()
|
||||
if(status_flags & GODMODE)
|
||||
return
|
||||
|
||||
if(is_servant_of_ratvar(src) && !stat)
|
||||
to_chat(src, "<span class='userdanger'>You resist Nar-Sie's influence... but not all of it. <i>Run!</i></span>")
|
||||
adjustBruteLoss(35)
|
||||
if(src && reagents)
|
||||
reagents.add_reagent("heparin", 5)
|
||||
return FALSE
|
||||
if(GLOB.cult_narsie && GLOB.cult_narsie.souls_needed[src])
|
||||
GLOB.cult_narsie.resize(1.1)
|
||||
GLOB.cult_narsie.souls_needed -= src
|
||||
GLOB.cult_narsie.souls += 1
|
||||
if((GLOB.cult_narsie.souls == GLOB.cult_narsie.soul_goal) && (GLOB.cult_narsie.resolved == FALSE))
|
||||
GLOB.cult_narsie.resolved = TRUE
|
||||
world << sound('sound/machines/Alarm.ogg')
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/cult_ending_helper, 1), 120)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/ending_helper), 270)
|
||||
if(client)
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/harvester, src, cultoverride = TRUE)
|
||||
else
|
||||
else
|
||||
switch(rand(1, 6))
|
||||
if(1)
|
||||
new /mob/living/simple_animal/hostile/construct/armored/hostile(get_turf(src))
|
||||
if(2)
|
||||
new /mob/living/simple_animal/hostile/construct/wraith/hostile(get_turf(src))
|
||||
if(3 to 6)
|
||||
new /mob/living/simple_animal/hostile/construct/builder/hostile(get_turf(src))
|
||||
spawn_dust()
|
||||
gib()
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/ratvar_act()
|
||||
if(status_flags & GODMODE)
|
||||
return
|
||||
|
||||
if(stat != DEAD && !is_servant_of_ratvar(src))
|
||||
for(var/obj/item/weapon/implant/mindshield/M in implants)
|
||||
qdel(M)
|
||||
if(!add_servant_of_ratvar(src))
|
||||
to_chat(src, "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>")
|
||||
adjustFireLoss(35)
|
||||
if(src)
|
||||
adjust_fire_stacks(1)
|
||||
IgniteMob()
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
//called when the mob receives a bright flash
|
||||
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash)
|
||||
if(get_eye_protection() < intensity && (override_blindness_check || !(disabilities & BLIND)))
|
||||
overlay_fullscreen("flash", type)
|
||||
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)
|
||||
return 1
|
||||
|
||||
//called when the mob receives a loud bang
|
||||
/mob/living/proc/soundbang_act()
|
||||
return 0
|
||||
|
||||
//to damage the clothes worn by a mob
|
||||
/mob/living/proc/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone)
|
||||
return
|
||||
|
||||
|
||||
/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
|
||||
if(A != src)
|
||||
end_pixel_y = get_standard_pixel_y_offset(lying)
|
||||
used_item = get_active_held_item()
|
||||
..()
|
||||
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
|
||||
if(1)
|
||||
new /mob/living/simple_animal/hostile/construct/armored/hostile(get_turf(src))
|
||||
if(2)
|
||||
new /mob/living/simple_animal/hostile/construct/wraith/hostile(get_turf(src))
|
||||
if(3 to 6)
|
||||
new /mob/living/simple_animal/hostile/construct/builder/hostile(get_turf(src))
|
||||
spawn_dust()
|
||||
gib()
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/ratvar_act()
|
||||
if(status_flags & GODMODE)
|
||||
return
|
||||
|
||||
if(stat != DEAD && !is_servant_of_ratvar(src))
|
||||
for(var/obj/item/weapon/implant/mindshield/M in implants)
|
||||
qdel(M)
|
||||
if(!add_servant_of_ratvar(src))
|
||||
to_chat(src, "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>")
|
||||
adjustFireLoss(35)
|
||||
if(src)
|
||||
adjust_fire_stacks(1)
|
||||
IgniteMob()
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
//called when the mob receives a bright flash
|
||||
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash)
|
||||
if(get_eye_protection() < intensity && (override_blindness_check || !(disabilities & BLIND)))
|
||||
overlay_fullscreen("flash", type)
|
||||
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)
|
||||
return 1
|
||||
|
||||
//called when the mob receives a loud bang
|
||||
/mob/living/proc/soundbang_act()
|
||||
return 0
|
||||
|
||||
//to damage the clothes worn by a mob
|
||||
/mob/living/proc/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone)
|
||||
return
|
||||
|
||||
|
||||
/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
|
||||
if(A != src)
|
||||
end_pixel_y = get_standard_pixel_y_offset(lying)
|
||||
used_item = get_active_held_item()
|
||||
..()
|
||||
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
|
||||
@@ -407,7 +407,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/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,
|
||||
|
||||
@@ -171,7 +171,30 @@
|
||||
attacktext = "slashes"
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
construct_spells = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift)
|
||||
playstyle_string = "<b>You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.</b>"
|
||||
playstyle_string = "<b>You are a Wraith. Though relatively fragile, you are fast, deadly, can phase through walls, and your attacks will lower the cooldown on phasing.</b>"
|
||||
var/attack_refund = 10 //1 second per attack
|
||||
var/crit_refund = 50 //5 seconds when putting a target into critical
|
||||
var/kill_refund = 250 //full refund on kills
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/wraith/AttackingTarget() //refund jaunt cooldown when attacking living targets
|
||||
var/prev_stat
|
||||
if(isliving(target) && !iscultist(target))
|
||||
var/mob/living/L = target
|
||||
prev_stat = L.stat
|
||||
|
||||
. = ..()
|
||||
|
||||
if(. && isnum(prev_stat))
|
||||
var/mob/living/L = target
|
||||
var/refund = 0
|
||||
if(QDELETED(L) || (L.stat == DEAD && prev_stat != DEAD)) //they're dead, you killed them
|
||||
refund += kill_refund
|
||||
else if(L.InCritical() && prev_stat == CONSCIOUS) //you knocked them into critical
|
||||
refund += crit_refund
|
||||
if(L.stat != DEAD && prev_stat != DEAD)
|
||||
refund += attack_refund
|
||||
for(var/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/S in mob_spell_list)
|
||||
S.charge_counter = min(S.charge_counter + refund, S.charge_max)
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/wraith/hostile //actually hostile, will move around, hit things
|
||||
AIStatus = AI_ON
|
||||
@@ -265,8 +288,8 @@
|
||||
name = "Harvester"
|
||||
real_name = "Harvester"
|
||||
desc = "A long, thin construct built to herald Nar-Sie's rise. It'll be all over soon."
|
||||
icon_state = "harvester"
|
||||
icon_living = "harvester"
|
||||
icon_state = "chosen"
|
||||
icon_living = "chosen"
|
||||
maxHealth = 60
|
||||
health = 60
|
||||
sight = SEE_MOBS
|
||||
@@ -277,9 +300,10 @@
|
||||
construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/area_conversion,
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall)
|
||||
playstyle_string = "<B>You are a Harvester. You are incapable of directly killing humans, but your attacks will remove their limbs: \
|
||||
Bring those who still cling to this world of illusion back to the Geometer so they may know Truth.</B>"
|
||||
Bring those who still cling to this world of illusion back to the Geometer so they may know Truth. Your form and any you are pulling can pass through runed walls effortlessly.</B>"
|
||||
can_repair_constructs = TRUE
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/harvester/Bump(atom/AM)
|
||||
. = ..()
|
||||
if(istype(AM, /turf/closed/wall/mineral/cult) && AM != loc) //we can go through cult walls
|
||||
@@ -306,6 +330,8 @@
|
||||
if(!LAZYLEN(parts))
|
||||
if(undismembermerable_limbs) //they have limbs we can't remove, and no parts we can, attack!
|
||||
return ..()
|
||||
C.Weaken(30)
|
||||
visible_message("<span class='danger'>[src] paralyzes [C]!</span>")
|
||||
to_chat(src, "<span class='cultlarge'>\"Bring [C.p_them()] to me.\"</span>")
|
||||
return FALSE
|
||||
do_attack_animation(C)
|
||||
@@ -314,6 +340,11 @@
|
||||
return FALSE
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/harvester/Initialize()
|
||||
. = ..()
|
||||
var/datum/action/innate/seek_prey/seek = new()
|
||||
seek.Grant(src)
|
||||
seek.Activate()
|
||||
|
||||
///////////////////////Master-Tracker///////////////////////
|
||||
|
||||
@@ -326,11 +357,14 @@
|
||||
var/tracking = FALSE
|
||||
var/mob/living/simple_animal/hostile/construct/the_construct
|
||||
|
||||
|
||||
/datum/action/innate/seek_master/Grant(var/mob/living/C)
|
||||
the_construct = C
|
||||
..()
|
||||
|
||||
/datum/action/innate/seek_master/Activate()
|
||||
if(!SSticker.mode.eldergod)
|
||||
the_construct.master = GLOB.blood_target
|
||||
if(!the_construct.master)
|
||||
to_chat(the_construct, "<span class='cultitalic'>You have no master to seek!</span>")
|
||||
the_construct.seeking = FALSE
|
||||
@@ -346,6 +380,43 @@
|
||||
to_chat(the_construct, "<span class='cultitalic'>You are now tracking your master.</span>")
|
||||
|
||||
|
||||
/datum/action/innate/seek_prey
|
||||
name = "Seek the Harvest"
|
||||
desc = "None can hide from Nar'Sie, activate to track a survivor attempting to flee the red harvest!"
|
||||
background_icon_state = "bg_demon"
|
||||
buttontooltipstyle = "cult"
|
||||
button_icon_state = "cult_mark"
|
||||
var/tracking = FALSE
|
||||
var/mob/living/simple_animal/hostile/construct/harvester/the_construct
|
||||
|
||||
/datum/action/innate/seek_prey/Grant(var/mob/living/C)
|
||||
the_construct = C
|
||||
..()
|
||||
|
||||
/datum/action/innate/seek_prey/Activate()
|
||||
if(GLOB.cult_narsie == null)
|
||||
return
|
||||
if(tracking)
|
||||
desc = "None can hide from Nar'Sie, activate to track a survivor attempting to flee the red harvest!"
|
||||
button_icon_state = "cult_mark"
|
||||
tracking = FALSE
|
||||
the_construct.seeking = FALSE
|
||||
the_construct.master = GLOB.cult_narsie
|
||||
to_chat(the_construct, "<span class='cultitalic'>You are now tracking Nar'Sie, return to reap the harvest!</span>")
|
||||
return
|
||||
else
|
||||
if(LAZYLEN(GLOB.cult_narsie.souls_needed))
|
||||
the_construct.master = pick(GLOB.cult_narsie.souls_needed)
|
||||
to_chat(the_construct, "<span class='cultitalic'>You are now tracking your prey, [the_construct.master] - harvest them!</span>")
|
||||
else
|
||||
to_chat(the_construct, "<span class='cultitalic'>Nar'Sie has completed her harvest!</span>")
|
||||
return
|
||||
desc = "Activate to track Nar'Sie!"
|
||||
button_icon_state = "sintouch"
|
||||
tracking = TRUE
|
||||
the_construct.seeking = TRUE
|
||||
|
||||
|
||||
/////////////////////////////ui stuff/////////////////////////////
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/update_health_hud()
|
||||
|
||||
@@ -467,6 +467,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
var/used_message = "<span class='holoparasite'>All the cards seem to be blank now.</span>"
|
||||
var/failure_message = "<span class='holoparasitebold'>..And draw a card! It's...blank? Maybe you should try again later.</span>"
|
||||
var/ling_failure = "<span class='holoparasitebold'>The deck refuses to respond to a souless creature such as you.</span>"
|
||||
var/activation_message = "<span class='holoparasite'>The rest of the deck rapidly flashes to ash!</span>"
|
||||
var/list/possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
|
||||
var/random = TRUE
|
||||
var/allowmultiple = FALSE
|
||||
@@ -495,6 +496,8 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
if(candidates.len)
|
||||
theghost = pick(candidates)
|
||||
spawn_guardian(user, theghost.key)
|
||||
to_chat(user, "[activation_message]")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "[failure_message]")
|
||||
used = FALSE
|
||||
@@ -587,6 +590,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
used_message = "<span class='holoparasite'>The injector has already been used.</span>"
|
||||
failure_message = "<span class='holoparasitebold'>...ERROR. BOOT SEQUENCE ABORTED. AI FAILED TO INTIALIZE. PLEASE CONTACT SUPPORT OR TRY AGAIN LATER.</span>"
|
||||
ling_failure = "<span class='holoparasitebold'>The holoparasites recoil in horror. They want nothing to do with a creature like you.</span>"
|
||||
activation_message = "<span class='holoparasite'>The injector self destructs after you inject yourself with it.</span>"
|
||||
|
||||
/obj/item/weapon/guardiancreator/tech/choose/traitor
|
||||
possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
|
||||
@@ -599,7 +603,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
|
||||
/obj/item/weapon/paper/guardian
|
||||
name = "Holoparasite Guide"
|
||||
icon_state = "paper_words"
|
||||
icon_state = "alienpaper_words"
|
||||
info = {"<b>A list of Holoparasite Types</b><br>
|
||||
|
||||
<br>
|
||||
@@ -670,6 +674,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
used_message = "<span class='holoparasite'>Someone's already taken a bite out of these fishsticks! Ew.</span>"
|
||||
failure_message = "<span class='holoparasitebold'>You couldn't catch any carp spirits from the seas of Lake Carp. Maybe there are none, maybe you fucked up.</span>"
|
||||
ling_failure = "<span class='holoparasitebold'>Carp'sie is fine with changelings, so you shouldn't be seeing this message.</span>"
|
||||
activation_message = "<span class='holoparasite'>You finish eating the fishsticks! Delicious!>"
|
||||
allowmultiple = TRUE
|
||||
allowling = TRUE
|
||||
random = TRUE
|
||||
|
||||
@@ -478,6 +478,8 @@ Difficulty: Hard
|
||||
var/speed = 3 //how many deciseconds between each step
|
||||
var/currently_seeking = FALSE
|
||||
var/friendly_fire_check = FALSE //if blasts produced apply friendly fire
|
||||
var/monster_damage_boost = TRUE
|
||||
var/damage = 10
|
||||
|
||||
/obj/effect/temp_visual/hierophant/chaser/Initialize(mapload, new_caster, new_target, new_speed, is_friendly_fire)
|
||||
. = ..()
|
||||
@@ -524,6 +526,8 @@ Difficulty: Hard
|
||||
|
||||
/obj/effect/temp_visual/hierophant/chaser/proc/make_blast()
|
||||
new /obj/effect/temp_visual/hierophant/blast(loc, caster, friendly_fire_check)
|
||||
B.damage = damage
|
||||
B.monster_damage_boost = monster_damage_boost
|
||||
|
||||
/obj/effect/temp_visual/hierophant/telegraph
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
@@ -553,6 +557,7 @@ Difficulty: Hard
|
||||
desc = "Get out of the way!"
|
||||
duration = 9
|
||||
var/damage = 10 //how much damage do we do?
|
||||
var/monster_damage_boost = TRUE //do we deal extra damage to monsters? Used by the boss
|
||||
var/list/hit_things = list() //we hit these already, ignore them
|
||||
var/friendly_fire_check = FALSE
|
||||
var/bursting = FALSE //if we're bursting and need to hit anyone crossing us
|
||||
@@ -595,7 +600,7 @@ Difficulty: Hard
|
||||
var/limb_to_hit = L.get_bodypart(pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg"))
|
||||
var/armor = L.run_armor_check(limb_to_hit, "melee", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 50, "Your armor was penetrated by [src]!")
|
||||
L.apply_damage(damage, BURN, limb_to_hit, armor)
|
||||
if(ismegafauna(L) || istype(L, /mob/living/simple_animal/hostile/asteroid))
|
||||
if(monster_damage_boost && (ismegafauna(L) || istype(L, /mob/living/simple_animal/hostile/asteroid)))
|
||||
L.adjustBruteLoss(damage)
|
||||
add_logs(caster, L, "struck with a [name]")
|
||||
for(var/obj/mecha/M in T.contents - hit_things) //and mechs.
|
||||
|
||||
@@ -170,8 +170,7 @@
|
||||
|
||||
/obj/item/weapon/paper/proc/updateinfolinks()
|
||||
info_links = info
|
||||
var/i = 0
|
||||
for(i=1,i<=fields,i++)
|
||||
for(var/i in 1 to min(fields, 15))
|
||||
addtofield(i, "<font face=\"[PEN_FONT]\"><A href='?src=\ref[src];write=[i]'>write</A></font>", 1)
|
||||
info_links = info_links + "<font face=\"[PEN_FONT]\"><A href='?src=\ref[src];write=end'>write</A></font>"
|
||||
|
||||
|
||||
@@ -304,16 +304,17 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
|
||||
// Sound the alert if gravity was just enabled or disabled.
|
||||
var/alert = 0
|
||||
var/area/A = get_area(src)
|
||||
if(on && SSticker.IsRoundInProgress()) // If we turned on and the game is live.
|
||||
if(gravity_in_level() == 0)
|
||||
alert = 1
|
||||
investigate_log("was brought online and is now producing gravity for this level.", "gravity")
|
||||
message_admins("The gravity generator was brought online [A][ADMIN_COORDJMP(src)]")
|
||||
else
|
||||
if(gravity_in_level() == 1)
|
||||
alert = 1
|
||||
investigate_log("was brought offline and there is now no gravity for this level.", "gravity")
|
||||
message_admins("The gravity generator was brought offline with no backup generator. [A][ADMIN_COORDJMP(src)]")
|
||||
if(SSticker.IsRoundInProgress())
|
||||
if(on) // If we turned on and the game is live.
|
||||
if(gravity_in_level() == 0)
|
||||
alert = 1
|
||||
investigate_log("was brought online and is now producing gravity for this level.", "gravity")
|
||||
message_admins("The gravity generator was brought online [A][ADMIN_COORDJMP(src)]")
|
||||
else
|
||||
if(gravity_in_level() == 1)
|
||||
alert = 1
|
||||
investigate_log("was brought offline and there is now no gravity for this level.", "gravity")
|
||||
message_admins("The gravity generator was brought offline with no backup generator. [A][ADMIN_COORDJMP(src)]")
|
||||
|
||||
update_icon()
|
||||
update_list()
|
||||
|
||||
@@ -34,13 +34,61 @@
|
||||
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/effects.dmi', "ghostalertsie")
|
||||
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/cult_effects.dmi', "ghostalertsie")
|
||||
notify_ghosts("Nar-Sie has risen in \the [A.name]. Reach out to the Geometer to be given a new shell for your soul.", source = src, alert_overlay = alert_overlay, action=NOTIFY_ATTACK)
|
||||
INVOKE_ASYNC(src, .proc/narsie_spawn_animation)
|
||||
|
||||
narsie_spawn_animation()
|
||||
/obj/singularity/narsie/large/cult // For the new cult ending, guaranteed to end the round within 3 minutes
|
||||
var/list/souls_needed = list()
|
||||
var/soul_goal = 0
|
||||
var/souls = 0
|
||||
var/resolved = FALSE
|
||||
|
||||
sleep(19)
|
||||
SSshuttle.emergency.request(null, set_coefficient = 0) //instantly arrives
|
||||
/obj/singularity/narsie/large/cult/proc/resize(var/ratio)
|
||||
var/matrix/ntransform = matrix(transform) //aka transform.Copy()
|
||||
ntransform.Scale(ratio)
|
||||
animate(src, transform = ntransform, time = 40, easing = EASE_IN|EASE_OUT)
|
||||
|
||||
/obj/singularity/narsie/large/cult/Initialize()
|
||||
. = ..()
|
||||
GLOB.cult_narsie = src
|
||||
GLOB.blood_target = src
|
||||
resize(0.6)
|
||||
for(var/datum/mind/cult_mind in SSticker.mode.cult)
|
||||
if(isliving(cult_mind.current))
|
||||
var/mob/living/L = cult_mind.current
|
||||
L.narsie_act()
|
||||
for(var/mob/living/player in GLOB.player_list)
|
||||
if(player.stat != DEAD && player.loc.z == ZLEVEL_STATION && !iscultist(player) && isliving(player))
|
||||
souls_needed[player] = TRUE
|
||||
soul_goal = round(1 + LAZYLEN(souls_needed) * 0.6)
|
||||
INVOKE_ASYNC(src, .proc/begin_the_end)
|
||||
|
||||
/obj/singularity/narsie/large/cult/proc/begin_the_end()
|
||||
sleep(50)
|
||||
priority_announce("An acausal dimensional event has been detected in your sector. Event has been flagged EXTINCTION-CLASS. Directing all available assets toward simulating solutions. SOLUTION ETA: 60 SECONDS.","Central Command Higher Dimensional Affairs", 'sound/misc/airraid.ogg')
|
||||
sleep(550)
|
||||
priority_announce("Simulations on acausal dimensional event complete. Deploying solution package now. Deployment ETA: TWO MINUTES. ","Central Command Higher Dimensional Affairs")
|
||||
sleep(50)
|
||||
set_security_level("delta")
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
SSshuttle.lockdown = TRUE
|
||||
sleep(1150)
|
||||
if(resolved == FALSE)
|
||||
resolved = TRUE
|
||||
world << sound('sound/machines/Alarm.ogg')
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/cult_ending_helper), 120)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/ending_helper), 220)
|
||||
|
||||
/obj/singularity/narsie/large/cult/Destroy()
|
||||
GLOB.cult_narsie = null
|
||||
return ..()
|
||||
|
||||
/proc/ending_helper()
|
||||
SSticker.force_ending = 1
|
||||
|
||||
/proc/cult_ending_helper(var/no_explosion = 0)
|
||||
SSticker.station_explosion_cinematic(no_explosion, "cult", null)
|
||||
|
||||
|
||||
/obj/singularity/narsie/large/attack_ghost(mob/dead/observer/user as mob)
|
||||
@@ -134,7 +182,7 @@
|
||||
return
|
||||
to_chat(target, "<span class='cultsmall'>NAR-SIE HAS LOST INTEREST IN YOU.</span>")
|
||||
target = food
|
||||
if(isliving(target))
|
||||
if(ishuman(target))
|
||||
to_chat(target, "<span class ='cult'>NAR-SIE HUNGERS FOR YOUR SOUL.</span>")
|
||||
else
|
||||
to_chat(target, "<span class ='cult'>NAR-SIE HAS CHOSEN YOU TO LEAD HER TO HER NEXT MEAL.</span>")
|
||||
|
||||
@@ -64,6 +64,25 @@
|
||||
qdel(S)
|
||||
..()
|
||||
|
||||
/obj/item/ammo_casing/dnainjector
|
||||
name = "rigged syringe gun spring"
|
||||
desc = "A high-power spring that throws DNA injectors."
|
||||
projectile_type = /obj/item/projectile/bullet/dnainjector
|
||||
firing_effect_type = null
|
||||
|
||||
/obj/item/ammo_casing/dnainjector/ready_proj(atom/target, mob/living/user, quiet, zone_override = "")
|
||||
if(!BB)
|
||||
return
|
||||
if(istype(loc, /obj/item/weapon/gun/syringe/dna))
|
||||
var/obj/item/weapon/gun/syringe/dna/SG = loc
|
||||
if(!SG.syringes.len)
|
||||
return
|
||||
|
||||
var/obj/item/weapon/dnainjector/S = popleft(SG.syringes)
|
||||
var/obj/item/projectile/bullet/dnainjector/D = BB
|
||||
S.forceMove(D)
|
||||
D.injector = S
|
||||
..()
|
||||
|
||||
/obj/item/ammo_casing/energy/c3dbullet
|
||||
projectile_type = /obj/item/projectile/bullet/midbullet3
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
item_state = null
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 10
|
||||
modifystate = TRUE
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BACK
|
||||
ammo_type = list(/obj/item/ammo_casing/energy/laser/pulse, /obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser)
|
||||
@@ -39,7 +40,7 @@
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
slot_flags = SLOT_BELT
|
||||
icon_state = "pulse_carbine"
|
||||
item_state = "pulse"
|
||||
item_state = null
|
||||
cell_type = "/obj/item/weapon/stock_parts/cell/pulse/carbine"
|
||||
can_flashlight = 1
|
||||
flight_x_offset = 18
|
||||
|
||||
@@ -49,18 +49,18 @@
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/syringe/attackby(obj/item/A, mob/user, params, show_msg = 1)
|
||||
/obj/item/weapon/gun/syringe/attackby(obj/item/A, mob/user, params, show_msg = TRUE)
|
||||
if(istype(A, /obj/item/weapon/reagent_containers/syringe))
|
||||
if(syringes.len < max_syringes)
|
||||
if(!user.transferItemToLoc(A, src))
|
||||
return
|
||||
return FALSE
|
||||
to_chat(user, "<span class='notice'>You load [A] into \the [src].</span>")
|
||||
syringes.Add(A)
|
||||
syringes += A
|
||||
recharge_newshot()
|
||||
return 1
|
||||
return TRUE
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>[src] cannot hold more syringes!</span>")
|
||||
return 0
|
||||
to_chat(user, "<span class='warning'>[src] cannot hold more syringes!</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/item/weapon/gun/syringe/rapidsyringe
|
||||
name = "rapid syringe gun"
|
||||
@@ -78,3 +78,29 @@
|
||||
force = 2 //Also very weak because it's smaller
|
||||
suppressed = 1 //Softer fire sound
|
||||
can_unsuppress = 0 //Permanently silenced
|
||||
|
||||
/obj/item/weapon/gun/syringe/dna
|
||||
name = "modified syringe gun"
|
||||
desc = "A syringe gun that has been modified to fit DNA injectors instead of normal syringes."
|
||||
origin_tech = "combat=2;syndicate=2;biotech=3"
|
||||
|
||||
/obj/item/weapon/gun/syringe/dna/Initialize()
|
||||
. = ..()
|
||||
chambered = new /obj/item/ammo_casing/dnainjector(src)
|
||||
|
||||
/obj/item/weapon/gun/syringe/dna/attackby(obj/item/A, mob/user, params, show_msg = TRUE)
|
||||
if(istype(A, /obj/item/weapon/dnainjector))
|
||||
var/obj/item/weapon/dnainjector/D = A
|
||||
if(D.used)
|
||||
to_chat(user, "<span class='warning'>This injector is used up!</span>")
|
||||
return
|
||||
if(syringes.len < max_syringes)
|
||||
if(!user.transferItemToLoc(D, src))
|
||||
return FALSE
|
||||
to_chat(user, "<span class='notice'>You load \the [D] into \the [src].</span>")
|
||||
syringes += D
|
||||
recharge_newshot()
|
||||
return TRUE
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] cannot hold more syringes!</span>")
|
||||
return FALSE
|
||||
@@ -190,7 +190,7 @@
|
||||
name = "dart"
|
||||
icon_state = "cbbolt"
|
||||
damage = 6
|
||||
var/piercing = 0
|
||||
var/piercing = FALSE
|
||||
|
||||
/obj/item/projectile/bullet/dart/New()
|
||||
..()
|
||||
@@ -201,15 +201,15 @@
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/M = target
|
||||
if(blocked != 100) // not completely blocked
|
||||
if(M.can_inject(null, 0, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
|
||||
if(M.can_inject(null, FALSE, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
|
||||
..()
|
||||
reagents.reaction(M, INJECT)
|
||||
reagents.trans_to(M, reagents.total_volume)
|
||||
return 1
|
||||
return TRUE
|
||||
else
|
||||
blocked = 100
|
||||
target.visible_message("<span class='danger'>The [name] was deflected!</span>", \
|
||||
"<span class='userdanger'>You were protected against the [name]!</span>")
|
||||
target.visible_message("<span class='danger'>\The [src] was deflected!</span>", \
|
||||
"<span class='userdanger'>You were protected against \the [src]!</span>")
|
||||
|
||||
..(target, blocked)
|
||||
reagents.set_reacting(TRUE)
|
||||
@@ -240,7 +240,28 @@
|
||||
nodamage = 1
|
||||
. = ..() // Execute the rest of the code.
|
||||
|
||||
|
||||
/obj/item/projectile/bullet/dnainjector
|
||||
name = "\improper DNA injector"
|
||||
icon_state = "syringeproj"
|
||||
var/obj/item/weapon/dnainjector/injector
|
||||
|
||||
/obj/item/projectile/bullet/dnainjector/on_hit(atom/target, blocked = 0)
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/M = target
|
||||
if(blocked != 100)
|
||||
if(M.can_inject(null, FALSE, def_zone, FALSE))
|
||||
if(injector.inject(M, firer))
|
||||
QDEL_NULL(injector)
|
||||
return TRUE
|
||||
else
|
||||
blocked = 100
|
||||
target.visible_message("<span class='danger'>\The [src] was deflected!</span>", \
|
||||
"<span class='userdanger'>You were protected against \the [src]!</span>")
|
||||
return ..()
|
||||
|
||||
/obj/item/projectile/bullet/dnainjector/Destroy()
|
||||
QDEL_NULL(injector)
|
||||
return ..()
|
||||
|
||||
//// SNIPER BULLETS
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
has_id = 1
|
||||
flavour_text = "<font size=3>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. <b>Continue your research as best you can, and try to keep a low profile. Do not abandon the base without good cause.</b> The base is rigged with explosives should the worst happen, do not let the base fall into enemy hands!</b>"
|
||||
id_access_list = list(GLOB.access_syndicate)
|
||||
faction = list("syndicate")
|
||||
|
||||
/obj/effect/mob_spawn/human/lavaland_syndicate/comms
|
||||
name = "Syndicate Comms Agent"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
if(charge_type == "recharge")
|
||||
var/refund_percent = current_amount/projectile_amount
|
||||
charge_counter = charge_max * refund_percent
|
||||
start_recharge()
|
||||
remove_ranged_ability(msg)
|
||||
else
|
||||
msg = "<span class='notice'>[active_msg]<B>Left-click to shoot it at a target!</B></span>"
|
||||
|
||||
@@ -1276,6 +1276,14 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
|
||||
restricted_roles = list("Chaplain")
|
||||
surplus = 5 //Very low chance to get it in a surplus crate even without being the chaplain
|
||||
|
||||
/datum/uplink_item/role_restricted/pie_cannon
|
||||
name = "Banana Cream Pie Cannon"
|
||||
desc = "A special pie cannon for a special clown, this gadget can hold up to 20 pies and automatically fabricates one every two seconds!"
|
||||
cost = 10
|
||||
item = /obj/item/weapon/pneumatic_cannon/pie/selfcharge
|
||||
restricted_roles = list("Clown")
|
||||
surplus = 0 //No fun unless you're the clown!
|
||||
|
||||
/datum/uplink_item/role_restricted/ancient_jumpsuit
|
||||
name = "Ancient Jumpsuit"
|
||||
desc = "A tattered old jumpsuit that will provide absolutely no benefit to you. It fills the wearer with a strange compulsion to blurt out 'glorf'."
|
||||
@@ -1291,6 +1299,13 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
|
||||
cost = 2
|
||||
restricted_roles = list("Curator")
|
||||
limited_stock = 1 // please don't spam deadchat
|
||||
|
||||
/datum/uplink_item/role_restricted/modified_syringe_gun
|
||||
name = "Modified Syringe Gun"
|
||||
desc = "A syringe gun that fires DNA injectors instead of normal syringes."
|
||||
item = /obj/item/weapon/gun/syringe/dna
|
||||
cost = 14
|
||||
restricted_roles = list("Geneticist", "Chief Medical Officer")
|
||||
|
||||
// Pointless
|
||||
/datum/uplink_item/badass
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
It requires an organic host as a home base and source of fuel." //This is the description of the actual injector. Feel free to change this for uplink purposes//
|
||||
item = /obj/item/weapon/storage/box/syndie_kit/holoparasite
|
||||
refundable = TRUE
|
||||
cost = 10 //I'm working off the borer. Price subject to change
|
||||
cost = 15 //I'm working off the borer. Price subject to change
|
||||
surplus = 20 //Nobody needs a ton of parasites
|
||||
exclude_modes = list(/datum/game_mode/nuclear)
|
||||
exclude_modes = list(/datum/game_mode/nuclear)
|
||||
refund_path = /obj/item/weapon/guardiancreator/tech/choose/traitor
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Lordpidey"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Toy toolboxes with realistic rumbling action have been added to arcade prizes."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Tacolizard Forever: Plasmaman Powercreep"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Plasmaman tanks are the same size as emergency oxygen tanks."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "CitadelStationBot"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Peacekeeper cyborgs now have projectile dampening fields."
|
||||
@@ -0,0 +1,8 @@
|
||||
author: "coiax"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Various vending machines, when shooting their inventory at nearby
|
||||
people, will \"demonstrate their products features\". This means that if a
|
||||
cigarette vending machine throws a lighter at you, it will be on.
|
||||
Vending machines also choose random products when throwing, rather than
|
||||
the first available one."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Joan"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Proselytizing alloy shards will now proselytize all the shards in the tile, instead of requiring you to proselytize each one at a time."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "CitadelStationBot"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Golems touching a shell can now choose to stay in their own body."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Swindly"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Added modified syringe guns. They fire DNA injectors. Geneticists and CMOs can buy them from the traitor uplink for 14 TC."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Steelpoint"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "All Pulse weapons now accurately show, by their sprites, what fire mode they are in."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "LetterJay"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Cryo should now properly utilize chems as well as freeze the occupant."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Gun Hog"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "The Auxiliary Base can no longer land outside the lavaland map's boundaries."
|
||||
@@ -0,0 +1,6 @@
|
||||
author: "Robustin"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Summoning Nar'Sie now triggers a different ending. No shuttle is coming! Survivors must escape on a pod or survive the Red Harvest for 3 minutes. If Nar'Sie acquires enough souls, the round ends immediately with a **special ending**."
|
||||
- rscadd: "New Harvester Sprite"
|
||||
- rscadd: "Harvesters can now track a random survivor on the station, then switch back to tracking Nar'Sie, via a new action button."
|
||||
|
After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 526 KiB After Width: | Height: | Size: 494 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 5.2 MiB |
|
Before Width: | Height: | Size: 249 KiB After Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
@@ -33,6 +33,7 @@
|
||||
#include "code\__DEFINES\combat.dm"
|
||||
#include "code\__DEFINES\construction.dm"
|
||||
#include "code\__DEFINES\contracts.dm"
|
||||
#include "code\__DEFINES\cult.dm"
|
||||
#include "code\__DEFINES\DNA.dm"
|
||||
#include "code\__DEFINES\events.dm"
|
||||
#include "code\__DEFINES\flags.dm"
|
||||
@@ -196,6 +197,7 @@
|
||||
#include "code\controllers\subsystem\dbcore.dm"
|
||||
#include "code\controllers\subsystem\disease.dm"
|
||||
#include "code\controllers\subsystem\events.dm"
|
||||
#include "code\controllers\subsystem\fields.dm"
|
||||
#include "code\controllers\subsystem\fire_burning.dm"
|
||||
#include "code\controllers\subsystem\garbage.dm"
|
||||
#include "code\controllers\subsystem\icon_smooth.dm"
|
||||
@@ -468,6 +470,7 @@
|
||||
#include "code\game\gamemodes\cult\cult_items.dm"
|
||||
#include "code\game\gamemodes\cult\cult_structures.dm"
|
||||
#include "code\game\gamemodes\cult\ritual.dm"
|
||||
#include "code\game\gamemodes\cult\rune_spawn_action.dm"
|
||||
#include "code\game\gamemodes\cult\runes.dm"
|
||||
#include "code\game\gamemodes\cult\supply.dm"
|
||||
#include "code\game\gamemodes\cult\talisman.dm"
|
||||
@@ -709,10 +712,10 @@
|
||||
#include "code\game\objects\effects\decals\decal.dm"
|
||||
#include "code\game\objects\effects\decals\misc.dm"
|
||||
#include "code\game\objects\effects\decals\remains.dm"
|
||||
#include "code\game\objects\effects\decals\cleanable\aliens.dm"
|
||||
#include "code\game\objects\effects\decals\cleanable\humans.dm"
|
||||
#include "code\game\objects\effects\decals\cleanable\misc.dm"
|
||||
#include "code\game\objects\effects\decals\cleanable\robots.dm"
|
||||
#include "code\game\objects\effects\decals\Cleanable\aliens.dm"
|
||||
#include "code\game\objects\effects\decals\Cleanable\humans.dm"
|
||||
#include "code\game\objects\effects\decals\Cleanable\misc.dm"
|
||||
#include "code\game\objects\effects\decals\Cleanable\robots.dm"
|
||||
#include "code\game\objects\effects\effect_system\effect_system.dm"
|
||||
#include "code\game\objects\effects\effect_system\effects_explosion.dm"
|
||||
#include "code\game\objects\effects\effect_system\effects_foam.dm"
|
||||
@@ -727,6 +730,10 @@
|
||||
#include "code\game\objects\effects\spawners\structure.dm"
|
||||
#include "code\game\objects\effects\spawners\vaultspawner.dm"
|
||||
#include "code\game\objects\effects\spawners\xeno_egg_delivery.dm"
|
||||
#include "code\game\objects\effects\temporary_visuals\clockcult.dm"
|
||||
#include "code\game\objects\effects\temporary_visuals\cult.dm"
|
||||
#include "code\game\objects\effects\temporary_visuals\miscellaneous.dm"
|
||||
#include "code\game\objects\effects\temporary_visuals\temporary_visual.dm"
|
||||
#include "code\game\objects\items\apc_frame.dm"
|
||||
#include "code\game\objects\items\blueprints.dm"
|
||||
#include "code\game\objects\items\body_egg.dm"
|
||||
@@ -1304,6 +1311,9 @@
|
||||
#include "code\modules\events\wizard\rpgloot.dm"
|
||||
#include "code\modules\events\wizard\shuffle.dm"
|
||||
#include "code\modules\events\wizard\summons.dm"
|
||||
#include "code\modules\fields\fields.dm"
|
||||
#include "code\modules\fields\peaceborg_dampener.dm"
|
||||
#include "code\modules\fields\turf_objects.dm"
|
||||
#include "code\modules\flufftext\Dreaming.dm"
|
||||
#include "code\modules\flufftext\Hallucination.dm"
|
||||
#include "code\modules\flufftext\TextFilters.dm"
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
diff a/tgstation.dme b/tgstation.dme (rejected hunks)
|
||||
@@ -677,10 +677,10 @@
|
||||
#include "code\game\objects\effects\decals\decal.dm"
|
||||
#include "code\game\objects\effects\decals\misc.dm"
|
||||
#include "code\game\objects\effects\decals\remains.dm"
|
||||
-#include "code\game\objects\effects\decals\Cleanable\aliens.dm"
|
||||
-#include "code\game\objects\effects\decals\Cleanable\humans.dm"
|
||||
-#include "code\game\objects\effects\decals\Cleanable\misc.dm"
|
||||
-#include "code\game\objects\effects\decals\Cleanable\robots.dm"
|
||||
+#include "code\game\objects\effects\decals\cleanable\aliens.dm"
|
||||
+#include "code\game\objects\effects\decals\cleanable\humans.dm"
|
||||
+#include "code\game\objects\effects\decals\cleanable\misc.dm"
|
||||
+#include "code\game\objects\effects\decals\cleanable\robots.dm"
|
||||
#include "code\game\objects\effects\effect_system\effect_system.dm"
|
||||
#include "code\game\objects\effects\effect_system\effects_explosion.dm"
|
||||
#include "code\game\objects\effects\effect_system\effects_foam.dm"
|
||||