Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into upstream-merge-26952
This commit is contained in:
+2
-1
@@ -43,7 +43,7 @@
|
||||
if(SSatoms.InitAtom(src, args))
|
||||
//we were deleted
|
||||
return
|
||||
|
||||
|
||||
var/list/created = SSatoms.created_atoms
|
||||
if(created)
|
||||
created += src
|
||||
@@ -274,6 +274,7 @@
|
||||
return
|
||||
|
||||
/atom/proc/ex_act(severity, target)
|
||||
set waitfor = FALSE
|
||||
contents_explosion(severity, target)
|
||||
|
||||
/atom/proc/blob_act(obj/structure/blob/B)
|
||||
|
||||
+51
-26
@@ -13,9 +13,9 @@
|
||||
var/throw_speed = 2 //How many tiles to move per ds when being thrown. Float values are fully supported
|
||||
var/throw_range = 7
|
||||
var/mob/pulledby = null
|
||||
var/list/languages
|
||||
var/list/initial_languages = list(/datum/language/common)
|
||||
var/only_speaks_language = null
|
||||
var/initial_language_holder = /datum/language_holder
|
||||
var/datum/language_holder/language_holder
|
||||
var/datum/language_menu/language_menu = null
|
||||
var/verb_say = "says"
|
||||
var/verb_ask = "asks"
|
||||
var/verb_exclaim = "exclaims"
|
||||
@@ -44,10 +44,6 @@
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/atom/movable/Initialize(mapload)
|
||||
. = ..()
|
||||
for(var/L in initial_languages)
|
||||
grant_language(L)
|
||||
|
||||
/atom/movable/Move(atom/newloc, direct = 0)
|
||||
if(!loc || !newloc) return 0
|
||||
@@ -177,6 +173,7 @@
|
||||
STOP_PROCESSING(SSinbounds, src)
|
||||
|
||||
QDEL_NULL(proximity_monitor)
|
||||
QDEL_NULL(language_holder)
|
||||
|
||||
. = ..()
|
||||
if(loc)
|
||||
@@ -576,44 +573,70 @@
|
||||
|
||||
|
||||
/* Language procs */
|
||||
/atom/movable/proc/get_language_holder(shadow=TRUE)
|
||||
if(language_holder)
|
||||
return language_holder
|
||||
else
|
||||
language_holder = new initial_language_holder(src)
|
||||
return language_holder
|
||||
|
||||
|
||||
/atom/movable/proc/grant_language(datum/language/dt)
|
||||
LAZYINITLIST(languages)
|
||||
languages[dt] = TRUE
|
||||
var/datum/language_holder/H = get_language_holder()
|
||||
H.grant_language(dt)
|
||||
|
||||
/atom/movable/proc/grant_all_languages(omnitongue=FALSE)
|
||||
for(var/la in subtypesof(/datum/language))
|
||||
grant_language(la)
|
||||
|
||||
if(omnitongue)
|
||||
SET_SECONDARY_FLAG(src, OMNITONGUE)
|
||||
var/datum/language_holder/H = get_language_holder()
|
||||
H.grant_all_languages(omnitongue)
|
||||
|
||||
/atom/movable/proc/get_random_understood_language()
|
||||
var/list/possible = list()
|
||||
for(var/dt in languages)
|
||||
possible += dt
|
||||
. = safepick(possible)
|
||||
var/datum/language_holder/H = get_language_holder()
|
||||
. = H.get_random_understood_language()
|
||||
|
||||
/atom/movable/proc/remove_language(datum/language/dt)
|
||||
LAZYREMOVE(languages, dt)
|
||||
var/datum/language_holder/H = get_language_holder()
|
||||
H.remove_language(dt)
|
||||
|
||||
/atom/movable/proc/remove_all_languages()
|
||||
LAZYCLEARLIST(languages)
|
||||
var/datum/language_holder/H = get_language_holder()
|
||||
H.remove_all_languages()
|
||||
|
||||
/atom/movable/proc/has_language(datum/language/dt)
|
||||
. = is_type_in_typecache(dt, languages)
|
||||
var/datum/language_holder/H = get_language_holder()
|
||||
. = H.has_language(dt)
|
||||
|
||||
// Whether an AM can speak in a language or not, independent of whether
|
||||
// it KNOWS the language
|
||||
/atom/movable/proc/could_speak_in_language(datum/language/dt)
|
||||
. = TRUE
|
||||
|
||||
/atom/movable/proc/can_speak_in_language(datum/language/dt)
|
||||
. = has_language(dt)
|
||||
if(only_speaks_language && !HAS_SECONDARY_FLAG(src, OMNITONGUE))
|
||||
. = . && ispath(only_speaks_language, dt)
|
||||
var/datum/language_holder/H = get_language_holder()
|
||||
|
||||
if(!H.has_language(dt))
|
||||
return FALSE
|
||||
else if(H.omnitongue || could_speak_in_language(dt))
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/atom/movable/proc/get_default_language()
|
||||
// if no language is specified, and we want to say() something, which
|
||||
// language do we use?
|
||||
var/datum/language_holder/H = get_language_holder()
|
||||
|
||||
if(H.selected_default_language)
|
||||
if(H.has_language(H.selected_default_language))
|
||||
return H.selected_default_language
|
||||
else
|
||||
H.selected_default_language = null
|
||||
|
||||
|
||||
|
||||
var/datum/language/chosen_langtype
|
||||
var/highest_priority
|
||||
|
||||
for(var/lt in languages)
|
||||
for(var/lt in H.languages)
|
||||
var/datum/language/langtype = lt
|
||||
if(!can_speak_in_language(langtype))
|
||||
continue
|
||||
@@ -622,8 +645,10 @@
|
||||
if(!highest_priority || (pri > highest_priority))
|
||||
chosen_langtype = langtype
|
||||
highest_priority = pri
|
||||
|
||||
H.selected_default_language = .
|
||||
. = chosen_langtype
|
||||
|
||||
/* End language procs */
|
||||
/atom/movable/proc/ConveyorMove(movedir)
|
||||
set waitfor = FALSE
|
||||
if(!anchored && has_gravity())
|
||||
|
||||
@@ -155,7 +155,8 @@
|
||||
if(!(check_usability(user)))
|
||||
return
|
||||
|
||||
var/list/nuke_candidates = pollCandidatesForMob("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150, src)
|
||||
to_chat(user, "<span class='notice'>You activate [src] and wait for confirmation.</span>")
|
||||
var/list/nuke_candidates = pollCandidatesForMob("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150, POLL_IGNORE_SYNDICATE, src)
|
||||
if(nuke_candidates.len)
|
||||
if(!(check_usability(user)))
|
||||
return
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
alpha = 75
|
||||
color = "#FAE48C"
|
||||
light_range = 1.4
|
||||
light_power = 0.4
|
||||
light_power = 1
|
||||
light_color = "#FAE48C"
|
||||
sigil_name = "Sigil of Transgression"
|
||||
|
||||
@@ -96,10 +96,6 @@
|
||||
sigil_name = "Sigil of Submission"
|
||||
var/glow_type
|
||||
|
||||
/obj/effect/clockwork/sigil/submission/New()
|
||||
..()
|
||||
update_light()
|
||||
|
||||
/obj/effect/clockwork/sigil/submission/proc/post_channel(mob/living/L)
|
||||
|
||||
/obj/effect/clockwork/sigil/submission/sigil_effects(mob/living/L)
|
||||
@@ -205,6 +201,21 @@
|
||||
and <b>[structure_number]</b> Clockwork Structure[structure_number == 1 ? "":"s"] [structure_number == 1 ? "is":"are"] in range.</span>")
|
||||
if(iscyborg(user))
|
||||
to_chat(user, "<span class='brass'>You can recharge from the [sigil_name] by crossing it.</span>")
|
||||
else if(!GLOB.ratvar_awakens)
|
||||
to_chat(user, "<span class='brass'>Hitting the [sigil_name] with brass sheets will convert them to power at a rate of <b>1</b> brass sheet to <b>[POWER_FLOOR]W</b> power.</span>")
|
||||
if(!GLOB.ratvar_awakens)
|
||||
to_chat(user, "<span class='brass'>You can recharge Clockwork Proselytizers from the [sigil_name].</span>")
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/attackby(obj/item/I, mob/living/user, params)
|
||||
if(is_servant_of_ratvar(user) && istype(I, /obj/item/stack/tile/brass) && !GLOB.ratvar_awakens)
|
||||
var/obj/item/stack/tile/brass/B = I
|
||||
user.visible_message("<span class='warning'>[user] places [B] on [src], causing it to disintegrate into glowing orange energy!</span>", \
|
||||
"<span class='brass'>You charge the [sigil_name] with [B], providing it with <b>[B.amount * POWER_FLOOR]W</b> of power.</span>")
|
||||
modify_charge(-(B.amount * POWER_FLOOR))
|
||||
playsound(src, 'sound/effects/light_flicker.ogg', (B.amount * POWER_FLOOR) * 0.01, 1)
|
||||
qdel(B)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/sigil_effects(mob/living/L)
|
||||
if(is_servant_of_ratvar(L))
|
||||
@@ -217,9 +228,7 @@
|
||||
if(!cyborg_checks(cyborg))
|
||||
return
|
||||
to_chat(cyborg, "<span class='brass'>You start to charge from the [sigil_name]...</span>")
|
||||
if(!do_after(cyborg, 50, target = src))
|
||||
return
|
||||
if(!cyborg_checks(cyborg))
|
||||
if(!do_after(cyborg, 50, target = src, extra_checks = CALLBACK(src, .proc/cyborg_checks, cyborg, TRUE)))
|
||||
return
|
||||
var/giving_power = min(Floor(cyborg.cell.maxcharge - cyborg.cell.charge, MIN_CLOCKCULT_POWER), power_charge) //give the borg either all our power or their missing power floored to MIN_CLOCKCULT_POWER
|
||||
if(modify_charge(giving_power))
|
||||
@@ -231,23 +240,27 @@
|
||||
animate(cyborg, color = previous_color, time = 100)
|
||||
addtimer(CALLBACK(cyborg, /atom/proc/update_atom_colour), 100)
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/proc/cyborg_checks(mob/living/silicon/robot/cyborg)
|
||||
/obj/effect/clockwork/sigil/transmission/proc/cyborg_checks(mob/living/silicon/robot/cyborg, silent)
|
||||
if(!cyborg.cell)
|
||||
to_chat(cyborg, "<span class='warning'>You have no cell!</span>")
|
||||
if(!silent)
|
||||
to_chat(cyborg, "<span class='warning'>You have no cell!</span>")
|
||||
return FALSE
|
||||
if(!power_charge)
|
||||
to_chat(cyborg, "<span class='warning'>The [sigil_name] has no stored power!</span>")
|
||||
if(!silent)
|
||||
to_chat(cyborg, "<span class='warning'>The [sigil_name] has no stored power!</span>")
|
||||
return FALSE
|
||||
if(cyborg.cell.charge > cyborg.cell.maxcharge - MIN_CLOCKCULT_POWER)
|
||||
to_chat(cyborg, "<span class='warning'>You are already at maximum charge!</span>")
|
||||
if(!silent)
|
||||
to_chat(cyborg, "<span class='warning'>You are already at maximum charge!</span>")
|
||||
return FALSE
|
||||
if(cyborg.has_status_effect(STATUS_EFFECT_POWERREGEN))
|
||||
to_chat(cyborg, "<span class='warning'>You are already regenerating power!</span>")
|
||||
if(!silent)
|
||||
to_chat(cyborg, "<span class='warning'>You are already regenerating power!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/New()
|
||||
..()
|
||||
/obj/effect/clockwork/sigil/transmission/Initialize()
|
||||
. = ..()
|
||||
update_glow()
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/proc/modify_charge(amount)
|
||||
@@ -268,7 +281,7 @@
|
||||
if(!power_charge)
|
||||
set_light(0)
|
||||
else
|
||||
set_light(round(alpha*0.02, 1), round(alpha*0.005, 1))
|
||||
set_light(max(alpha*0.02, 1.4), max(alpha*0.01, 0.1))
|
||||
|
||||
//Vitality Matrix: Drains health from non-servants to heal or even revive servants.
|
||||
/obj/effect/clockwork/sigil/vitality
|
||||
@@ -302,8 +315,7 @@
|
||||
if((is_servant_of_ratvar(L) && L.suiciding) || sigil_active)
|
||||
return
|
||||
visible_message("<span class='warning'>[src] begins to glow bright blue!</span>")
|
||||
animate(src, alpha = 255, time = 10)
|
||||
addtimer(CALLBACK(src, .proc/update_alpha), 10)
|
||||
animate(src, alpha = 255, time = 10, flags = ANIMATION_END_NOW) //we may have a previous animation going. finish it first, then do this one without delay.
|
||||
sleep(10)
|
||||
//as long as they're still on the sigil and are either not a servant or they're a servant AND it has remaining vitality
|
||||
while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && (GLOB.ratvar_awakens || vitality))) && get_turf(L) == get_turf(src))
|
||||
@@ -372,12 +384,4 @@
|
||||
animation_number = initial(animation_number)
|
||||
sigil_active = FALSE
|
||||
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
|
||||
if(sigil_active || alpha == 255)
|
||||
animate(src, alpha = initial(alpha), time = 10)
|
||||
addtimer(CALLBACK(src, .proc/update_alpha), 10)
|
||||
|
||||
/obj/effect/clockwork/sigil/vitality/proc/update_alpha()
|
||||
if(sigil_active)
|
||||
alpha = 255
|
||||
else
|
||||
alpha = initial(alpha)
|
||||
animate(src, alpha = initial(alpha), time = 10, flags = ANIMATION_END_NOW)
|
||||
|
||||
@@ -180,17 +180,26 @@
|
||||
return procure_gateway(invoker, time_duration, gateway_uses, two_way)
|
||||
var/istargetobelisk = istype(target, /obj/structure/destructible/clockwork/powered/clockwork_obelisk)
|
||||
var/issrcobelisk = istype(src, /obj/structure/destructible/clockwork/powered/clockwork_obelisk)
|
||||
if(issrcobelisk && !anchored)
|
||||
to_chat(invoker, "<span class='warning'>[src] is no longer secured!</span>")
|
||||
return FALSE
|
||||
if(issrcobelisk)
|
||||
if(!anchored)
|
||||
to_chat(invoker, "<span class='warning'>[src] is no longer secured!</span>")
|
||||
return FALSE
|
||||
var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/CO = src //foolish as I am, how I set this proc up makes substypes unfeasible
|
||||
if(CO.active)
|
||||
to_chat(invoker, "<span class='warning'>[src] is now sustaining a gateway!</span>")
|
||||
return FALSE
|
||||
if(istargetobelisk)
|
||||
if(!target.anchored)
|
||||
to_chat(invoker, "<span class='warning'>That [target.name] is no longer secured!</span>")
|
||||
return procure_gateway(invoker, time_duration, gateway_uses, two_way)
|
||||
var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/CO = target
|
||||
if(CO.active)
|
||||
to_chat(invoker, "<span class='warning'>That [target.name] is sustaining a gateway, and cannot recieve another!</span>")
|
||||
return procure_gateway(invoker, time_duration, gateway_uses, two_way)
|
||||
var/efficiency = CO.get_efficiency_mod()
|
||||
gateway_uses = round(gateway_uses * (2 * efficiency), 1)
|
||||
time_duration = round(time_duration * (2 * efficiency), 1)
|
||||
CO.active = TRUE //you'd be active in a second but you should update immediately
|
||||
invoker.visible_message("<span class='warning'>The air in front of [invoker] ripples before suddenly tearing open!</span>", \
|
||||
"<span class='brass'>With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [time_duration / 10] seconds and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].</span>")
|
||||
var/obj/effect/clockwork/spatial_gateway/S1 = new(issrcobelisk ? get_turf(src) : get_step(get_turf(invoker), invoker.dir))
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
else
|
||||
for(var/i in GLOB.clockwork_component_cache)
|
||||
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*GLOB.clockwork_component_cache[i], 1)
|
||||
for(var/obj/structure/destructible/clockwork/massive/celestial_gateway/G in GLOB.all_clockwork_objects)
|
||||
if(G.still_needs_components())
|
||||
for(var/i in G.required_components)
|
||||
if(!G.required_components[i])
|
||||
. -= i
|
||||
break
|
||||
. = pickweight(.)
|
||||
|
||||
//returns a component name from a component id
|
||||
@@ -37,6 +43,8 @@
|
||||
return "Replicant Alloy"
|
||||
if(HIEROPHANT_ANSIBLE)
|
||||
return "Hierophant Ansible"
|
||||
else
|
||||
return null
|
||||
|
||||
//returns a component acronym from a component id
|
||||
/proc/get_component_acronym(id)
|
||||
@@ -51,6 +59,8 @@
|
||||
return "RA"
|
||||
if(HIEROPHANT_ANSIBLE)
|
||||
return "HA"
|
||||
else
|
||||
return null
|
||||
|
||||
//returns a component id from a component name
|
||||
/proc/get_component_id(name)
|
||||
@@ -65,6 +75,8 @@
|
||||
return REPLICANT_ALLOY
|
||||
if("Hierophant Ansible")
|
||||
return HIEROPHANT_ANSIBLE
|
||||
else
|
||||
return null
|
||||
|
||||
//returns a component spanclass from a component id
|
||||
/proc/get_component_span(id)
|
||||
@@ -121,6 +133,8 @@
|
||||
return /obj/effect/overlay/temp/ratvar/component/alloy
|
||||
if(HIEROPHANT_ANSIBLE)
|
||||
return /obj/effect/overlay/temp/ratvar/component/ansible
|
||||
else
|
||||
return null
|
||||
|
||||
//returns a type for a component from a component id
|
||||
/proc/get_component_type(id)
|
||||
@@ -134,4 +148,6 @@
|
||||
if(REPLICANT_ALLOY)
|
||||
return /obj/item/clockwork/component/replicant_alloy
|
||||
if(HIEROPHANT_ANSIBLE)
|
||||
return /obj/item/clockwork/component/hierophant_ansible
|
||||
return /obj/item/clockwork/component/hierophant_ansible
|
||||
else
|
||||
return null
|
||||
@@ -286,6 +286,28 @@
|
||||
user.visible_message("<span class='notice'>[user]'s [proselytizer.name] stops covering [src] with glowing orange energy.</span>", \
|
||||
"<span class='alloy'>You finish repairing [src]. It is now at <b>[obj_integrity]/[max_integrity]</b> integrity.</span>")
|
||||
|
||||
//Hitting a sigil of transmission will try to charge from it.
|
||||
/obj/effect/clockwork/sigil/transmission/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
|
||||
. = TRUE
|
||||
var/list/charge_values = list()
|
||||
if(!proselytizer.sigil_charge_checks(charge_values, src, user))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user]'s [proselytizer.name] starts draining glowing orange energy from [src]...</span>", \
|
||||
"<span class='alloy'>You start recharging your [proselytizer.name]...</span>")
|
||||
proselytizer.recharging = src
|
||||
while(proselytizer && user && src)
|
||||
if(!do_after(user, 10, target = src, extra_checks = CALLBACK(proselytizer, /obj/item/clockwork/clockwork_proselytizer.proc/sigil_charge_checks, charge_values, src, user, TRUE)))
|
||||
break
|
||||
modify_charge(charge_values["power_gain"])
|
||||
proselytizer.modify_stored_power(charge_values["power_gain"])
|
||||
playsound(src, 'sound/effects/light_flicker.ogg', charge_values["power_gain"] * 0.1, 1)
|
||||
|
||||
if(proselytizer)
|
||||
proselytizer.recharging = null
|
||||
if(user)
|
||||
user.visible_message("<span class='notice'>[user]'s [proselytizer.name] stops draining glowing orange energy from [src].</span>", \
|
||||
"<span class='alloy'>You finish recharging your [proselytizer.name]. It now contains <b>[proselytizer.get_power()]W/[proselytizer.get_max_power()]W</b> power.</span>")
|
||||
|
||||
//Proselytizer mob heal proc, to avoid as much copypaste as possible.
|
||||
/mob/living/proc/proselytizer_heal(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
|
||||
var/list/repair_values = list()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
var/uses_power = TRUE
|
||||
var/metal_to_power = FALSE
|
||||
var/repairing = null //what we're currently repairing, if anything
|
||||
var/obj/effect/clockwork/sigil/transmission/recharging = null //the sigil we're charging from, if any
|
||||
var/speed_multiplier = 1 //how fast this proselytizer works
|
||||
var/charge_rate = MIN_CLOCKCULT_POWER //how much power we gain every two seconds
|
||||
var/charge_delay = 2 //how many proccess ticks remain before we can start to charge
|
||||
@@ -140,10 +141,11 @@
|
||||
|
||||
/obj/item/clockwork/clockwork_proselytizer/attack_self(mob/living/user)
|
||||
if(is_servant_of_ratvar(user))
|
||||
if(!can_use_power(POWER_WALL_TOTAL))
|
||||
to_chat(user, "<span class='warning'>[src] requires <b>[POWER_WALL_TOTAL]W</b> of power to produce brass sheets!</span>")
|
||||
return
|
||||
modify_stored_power(-POWER_WALL_TOTAL)
|
||||
if(uses_power)
|
||||
if(!can_use_power(POWER_WALL_TOTAL))
|
||||
to_chat(user, "<span class='warning'>[src] requires <b>[POWER_WALL_TOTAL]W</b> of power to produce brass sheets!</span>")
|
||||
return
|
||||
modify_stored_power(-POWER_WALL_TOTAL)
|
||||
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
new/obj/item/stack/tile/brass(user.loc, 5)
|
||||
to_chat(user, "<span class='brass'>You user [stored_power ? "some":"all"] of [src]'s power to produce some brass sheets. It now stores <b>[get_power()]W/[get_max_power()]W</b> of power.</span>")
|
||||
@@ -182,6 +184,9 @@
|
||||
if(repairing)
|
||||
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>")
|
||||
return FALSE
|
||||
var/list/proselytize_values = target.proselytize_vals(user, src) //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
|
||||
@@ -237,7 +242,7 @@
|
||||
/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)
|
||||
return FALSE
|
||||
if(repairing)
|
||||
if(repairing || recharging)
|
||||
return FALSE
|
||||
if(target.type != expected_type)
|
||||
return FALSE
|
||||
@@ -296,3 +301,20 @@
|
||||
<b>[round(repair_values["amount_to_heal"]*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)]W</b> to fully repair [target == user ? "yourself" : "[target.p_them()]"]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//checked constantly while charging from a sigil
|
||||
/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)
|
||||
return FALSE
|
||||
if(can_use_power(RATVAR_POWER_CHECK))
|
||||
return FALSE
|
||||
charge_values["power_gain"] = Clamp(sigil.power_charge, 0, POWER_WALL_MINUS_FLOOR)
|
||||
if(!charge_values["power_gain"])
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>The [sigil.sigil_name] contains no power!</span>")
|
||||
return FALSE
|
||||
if(stored_power + charge_values["power_gain"] > max_power)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>Your [name] contains too much power to charge from the [sigil.sigil_name]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
apply_eye_damage(H)
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/wraith_spectacles/tick()
|
||||
if(!ishuman(owner))
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
speak_emote = list("clanks", "clinks", "clunks", "clangs")
|
||||
verb_ask = "requests"
|
||||
verb_exclaim = "proclaims"
|
||||
verb_whisper = "imparts"
|
||||
verb_yell = "harangues"
|
||||
initial_languages = list(/datum/language/common, /datum/language/ratvar)
|
||||
only_speaks_language = /datum/language/ratvar
|
||||
initial_language_holder = /datum/language_holder/clockmob
|
||||
bubble_icon = "clock"
|
||||
light_color = "#E42742"
|
||||
death_sound = 'sound/magic/clockwork/anima_fragment_death.ogg'
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
if(!check_special_requirements())
|
||||
return FALSE
|
||||
to_chat(invoker, "<span class='warning'>The tendril shivers slightly as it selects a marauder...</span>")
|
||||
var/list/marauder_candidates = pollCandidates("Do you want to play as the clockwork marauder of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 50, POLL_IGNORE_CLOCKWORK_MARAUDER)
|
||||
var/list/marauder_candidates = pollGhostCandidates("Do you want to play as the clockwork marauder of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 50, POLL_IGNORE_CLOCKWORK_MARAUDER)
|
||||
if(!check_special_requirements())
|
||||
return FALSE
|
||||
if(!marauder_candidates.len)
|
||||
@@ -218,22 +218,22 @@
|
||||
/datum/clockwork_scripture/create_object/mania_motor
|
||||
descname = "Powered Structure, Area Denial"
|
||||
name = "Mania Motor"
|
||||
desc = "Creates a mania motor which will cause brain damage and hallucinations in nearby non-Servant humans. It will also try to convert humans directly adjecent to the motor."
|
||||
desc = "Creates a mania motor which causes minor damage and a variety of negative mental effects in nearby non-Servant humans, potentially up to and including conversion."
|
||||
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
|
||||
channel_time = 80
|
||||
consumed_components = list(GEIS_CAPACITOR = 5, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
|
||||
object_path = /obj/structure/destructible/clockwork/powered/mania_motor
|
||||
creator_message = "<span class='brass'>You form a mania motor which will cause brain damage and hallucinations in nearby humans while active.</span>"
|
||||
creator_message = "<span class='brass'>You form a mania motor, which causes minor damage and negative mental effects in non-Servants.</span>"
|
||||
observer_message = "<span class='warning'>A two-pronged machine rises from the ground!</span>"
|
||||
invokers_required = 2
|
||||
multiple_invokers_used = TRUE
|
||||
usage_tip = "Eligible non-Servant humans next to the motor will be converted at an additional power cost. It will also cure hallucinations and brain damage in nearby Servants."
|
||||
usage_tip = "It will also cure hallucinations and brain damage in nearby Servants."
|
||||
tier = SCRIPTURE_APPLICATION
|
||||
one_per_tile = TRUE
|
||||
primary_component = GEIS_CAPACITOR
|
||||
sort_priority = 8
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Creates a Mania Motor, which can convert adjacent non-Servants with power."
|
||||
quickbind_desc = "Creates a Mania Motor, which causes minor damage and negative mental effects in non-Servants."
|
||||
|
||||
|
||||
//Tinkerer's Daemon: Creates an efficient machine that rapidly produces components at a power cost.
|
||||
|
||||
@@ -17,23 +17,10 @@
|
||||
sort_priority = 1
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Forces nearby non-Servants to walk, doing minor damage with each chant.<br><b>Maximum 15 chants.</b>"
|
||||
var/noncultist_damage = 2 //damage per chant to noncultists
|
||||
var/cultist_damage = 8 //damage per chant to non-walking cultists
|
||||
|
||||
/datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number)
|
||||
for(var/mob/living/carbon/C in hearers(7, invoker))
|
||||
var/number_legs = C.get_num_legs()
|
||||
if(!is_servant_of_ratvar(C) && !C.null_rod_check() && number_legs) //you have legs right
|
||||
C.apply_damage(noncultist_damage * 0.5, BURN, "l_leg")
|
||||
C.apply_damage(noncultist_damage * 0.5, BURN, "r_leg")
|
||||
if(C.m_intent != MOVE_INTENT_WALK)
|
||||
if(!iscultist(C))
|
||||
to_chat(C, "<span class='warning'>Your leg[number_legs > 1 ? "s shiver":" shivers"] with pain!</span>")
|
||||
else //Cultists take extra burn damage
|
||||
to_chat(C, "<span class='warning'>Your leg[number_legs > 1 ? "s burn":" burns"] with pain!</span>")
|
||||
C.apply_damage(cultist_damage * 0.5, BURN, "l_leg")
|
||||
C.apply_damage(cultist_damage * 0.5, BURN, "r_leg")
|
||||
C.toggle_move_intent()
|
||||
C.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
new /obj/effect/overlay/temp/heal(T, "#1E8CE1")
|
||||
else
|
||||
break
|
||||
new /obj/effect/overlay/temp/ratvar/mending_mantra(get_turf(invoker))
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
var/input = stripped_input(usr, "Please choose a message to send over the Hierophant Network.", "Hierophant Broadcast", "")
|
||||
if(!is_servant_of_ratvar(user) || !input || !user.canUseTopic(src, !issilicon(user)))
|
||||
return
|
||||
if(anchored)
|
||||
if(!anchored)
|
||||
to_chat(user, "<span class='warning'>[src] is no longer secured!</span>")
|
||||
return FALSE
|
||||
if(active)
|
||||
@@ -84,7 +84,8 @@
|
||||
return
|
||||
if(procure_gateway(user, round(100 * get_efficiency_mod(), 1), round(5 * get_efficiency_mod(), 1), 1))
|
||||
process()
|
||||
if(!active)
|
||||
if(!active) //we won't be active if nobody has sent a gateway to us
|
||||
active = TRUE
|
||||
clockwork_say(user, text2ratvar("Spatial Gateway, activate!"))
|
||||
return
|
||||
return_power(gateway_cost) //if we didn't return above, ie, successfully create a gateway, we give the power back
|
||||
@@ -92,7 +93,8 @@
|
||||
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/process()
|
||||
if(!anchored)
|
||||
return
|
||||
if(locate(/obj/effect/clockwork/spatial_gateway) in loc)
|
||||
var/obj/effect/clockwork/spatial_gateway/SG = locate(/obj/effect/clockwork/spatial_gateway)
|
||||
if(SG && SG.timerid) //it's a valid gateway, we're active
|
||||
icon_state = active_icon
|
||||
density = 0
|
||||
active = TRUE
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//Mania Motor: A pair of antenna that, while active, cause braindamage and hallucinations in nearby human mobs.
|
||||
//Mania Motor: A pair of antenna that, while active, cause a variety of negative mental effects in nearby human mobs.
|
||||
/obj/structure/destructible/clockwork/powered/mania_motor
|
||||
name = "mania motor"
|
||||
desc = "A pair of antenna with what appear to be sockets around the base. It reminds you of an antlion."
|
||||
clockwork_desc = "A transmitter that allows Sevtug to whisper into the minds of nearby non-servants, causing hallucinations and brain damage as long as it remains powered."
|
||||
clockwork_desc = "A transmitter that allows Sevtug to whisper into the minds of nearby non-servants, causing a variety of negative mental effects, up to and including conversion."
|
||||
icon_state = "mania_motor_inactive"
|
||||
active_icon = "mania_motor"
|
||||
inactive_icon = "mania_motor_inactive"
|
||||
@@ -16,22 +16,11 @@
|
||||
/obj/item/clockwork/alloy_shards/small = 2, \
|
||||
/obj/item/clockwork/component/geis_capacitor/antennae = 1)
|
||||
var/mania_cost = 150
|
||||
var/convert_cost = 150
|
||||
var/static/list/mania_messages = list("Go nuts.", "Take a crack at crazy.", "Make a bid for insanity.", "Get kooky.", "Move towards mania.", "Become bewildered.", "Wax wild.", \
|
||||
"Go round the bend.", "Land in lunacy.", "Try dementia.", "Strive to get a screw loose.")
|
||||
var/static/list/compel_messages = list("Come closer.", "Approach the transmitter.", "Touch the antennae.", "I always have to deal with idiots. Move towards the mania motor.", \
|
||||
"Advance forward and place your head between the antennae - that's all it's good for.", "If you were smarter, you'd be over here already.", "Move FORWARD, you fool.")
|
||||
var/static/list/convert_messages = list("You won't do. Go to sleep while I tell these nitwits how to convert you.", "You are insufficient. I must instruct these idiots in the art of conversion.", \
|
||||
"Oh of course, someone we can't convert. These servants are fools.", "How hard is it to use a Sigil, anyway? All it takes is dragging someone onto it.", \
|
||||
"How do they fail to use a Sigil of Accession, anyway?", "Why is it that all servants are this inept?", "It's quite likely you'll be stuck here for a while.")
|
||||
var/static/list/close_messages = list("Well, you can't reach the motor from THERE, you moron.", "Interesting location. I'd prefer if you went somewhere you could ACTUALLY TOUCH THE ANTENNAE!", \
|
||||
"Amazing. You somehow managed to wedge yourself somewhere you can't actually reach the motor from.", "Such a show of idiocy is unparalleled. Perhaps I should put you on display?", \
|
||||
"Did you do this on purpose? I can't imagine you doing so accidentally. Oh, wait, I can.", "How is it that such smart creatures can still do something AS STUPID AS THIS!")
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/mania_motor/examine(mob/user)
|
||||
..()
|
||||
if(is_servant_of_ratvar(user) || isobserver(user))
|
||||
to_chat(user, "<span class='sevtug_small'>It requires <b>[mania_cost]W</b> to run, and at least <b>[convert_cost]W</b> to attempt to convert humans adjacent to it.</span>")
|
||||
to_chat(user, "<span class='sevtug_small'>It requires <b>[mania_cost]W</b> to run.</span>")
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/mania_motor/forced_disable(bad_effects)
|
||||
if(active)
|
||||
@@ -60,82 +49,17 @@
|
||||
if(!try_use_power(mania_cost))
|
||||
forced_disable(FALSE)
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
var/hum = get_sfx('sound/effects/screech.ogg') //like playsound, same sound for everyone affected
|
||||
var/efficiency = get_efficiency_mod()
|
||||
for(var/mob/living/carbon/human/H in viewers(7, src))
|
||||
if(is_servant_of_ratvar(H)) //heals servants of braindamage, hallucination, druggy, dizziness, and confusion
|
||||
var/brainloss = H.getBrainLoss()
|
||||
if(brainloss)
|
||||
H.adjustBrainLoss(-brainloss)
|
||||
if(H.hallucination)
|
||||
H.hallucination = 0
|
||||
if(H.druggy)
|
||||
H.adjust_drugginess(-H.druggy)
|
||||
if(H.dizziness)
|
||||
H.dizziness = 0
|
||||
if(H.confused)
|
||||
H.confused = 0
|
||||
else if(!H.null_rod_check() && H.stat != DEAD)
|
||||
var/distance = 0 + get_dist(T, get_turf(H))
|
||||
var/falloff_distance = min((110) - distance * 10, 80)
|
||||
var/sound_distance = falloff_distance * 0.5
|
||||
var/targetbrainloss = H.getBrainLoss()
|
||||
if(distance > 3 && prob(falloff_distance * 0.5))
|
||||
to_chat(H, "<span class='sevtug_small'>\"[text2ratvar(pick(mania_messages))]\"</span>")
|
||||
if(distance <= 1)
|
||||
if(!H.Adjacent(src))
|
||||
to_chat(H, "<span class='sevtug'>\"[text2ratvar(pick(close_messages))]\"</span>")
|
||||
H.playsound_local(T, hum, sound_distance, 1)
|
||||
else if(!try_use_power(convert_cost))
|
||||
visible_message("<span class='warning'>[src]'s antennae fizzle quietly.</span>")
|
||||
playsound(src, 'sound/effects/light_flicker.ogg', 50, 1)
|
||||
else
|
||||
H.playsound_local(T, hum, 80, 1)
|
||||
if(!H.stat)
|
||||
if(H.getBrainLoss() < 100)
|
||||
H.adjustBrainLoss(20 * efficiency)
|
||||
H.visible_message("<span class='warning'>[H] reaches out and touches [src].</span>", "<span class='sevtug'>You touch [src] involuntarily.</span>")
|
||||
else
|
||||
H.Paralyse(3)
|
||||
else if(is_eligible_servant(H))
|
||||
to_chat(H, "<span class='sevtug'>\"[text2ratvar("You are mine and his, now.")]\"</span>")
|
||||
add_servant_of_ratvar(H)
|
||||
H.Paralyse(5)
|
||||
else
|
||||
H.playsound_local(T, hum, sound_distance, 1)
|
||||
switch(distance)
|
||||
if(0 to 3)
|
||||
if(prob(falloff_distance * 0.5))
|
||||
if(prob(falloff_distance))
|
||||
to_chat(H, "<span class='sevtug_small'>\"[text2ratvar(pick(mania_messages))]\"</span>")
|
||||
else
|
||||
to_chat(H, "<span class='sevtug'>\"[text2ratvar(pick(compel_messages))]\"</span>")
|
||||
if(targetbrainloss <= 40)
|
||||
H.adjustBrainLoss(3 * efficiency)
|
||||
H.adjust_drugginess(Clamp(7 * efficiency, 0, 50 - H.druggy))
|
||||
H.hallucination = min(H.hallucination + (7 * efficiency), 50)
|
||||
H.dizziness = min(H.dizziness + (3 * efficiency), 20)
|
||||
H.confused = min(H.confused + (3 * efficiency), 20)
|
||||
if(3 to 5)
|
||||
if(targetbrainloss <= 20)
|
||||
H.adjustBrainLoss(2 * efficiency)
|
||||
H.adjust_drugginess(Clamp(5 * efficiency, 0, 25 - H.druggy))
|
||||
H.hallucination = min(H.hallucination + (5 * efficiency), 25)
|
||||
H.dizziness = min(H.dizziness + (2 * efficiency), 10)
|
||||
H.confused = min(H.confused + (2 * efficiency), 10)
|
||||
if(5 to 6)
|
||||
if(targetbrainloss <= 10)
|
||||
H.adjustBrainLoss(1 * efficiency)
|
||||
H.adjust_drugginess(Clamp(2 * efficiency, 0, 20 - H.druggy))
|
||||
H.hallucination = min(H.hallucination + (2 * efficiency), 20)
|
||||
H.dizziness = min(H.dizziness + (2 * efficiency), 5)
|
||||
H.confused = min(H.confused + (2 * efficiency), 5)
|
||||
if(6 to 7)
|
||||
if(targetbrainloss <= 5)
|
||||
H.adjustBrainLoss(1 * efficiency)
|
||||
H.adjust_drugginess(Clamp(2 * efficiency, 0, 10 - H.druggy))
|
||||
H.hallucination = min(H.hallucination + (2 * efficiency), 10)
|
||||
if(7 to INFINITY)
|
||||
H.adjust_drugginess(Clamp(2 * efficiency, 0, 5 - H.druggy))
|
||||
H.hallucination = min(H.hallucination + (2 * efficiency), 5)
|
||||
if(is_servant_of_ratvar(H))
|
||||
continue
|
||||
var/list/effects = H.has_status_effect_list(STATUS_EFFECT_MANIAMOTOR)
|
||||
var/datum/status_effect/maniamotor/M
|
||||
for(var/datum/status_effect/maniamotor/MM in effects)
|
||||
if(MM.motor == src)
|
||||
M = MM
|
||||
break
|
||||
if(!M)
|
||||
M = H.apply_status_effect(STATUS_EFFECT_MANIAMOTOR)
|
||||
M.motor = src
|
||||
M.severity = Clamp(M.severity + ((11 - get_dist(src, H)) * efficiency * efficiency), 0, MAX_MANIA_SEVERITY)
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
if(!prey && LAZYLEN(meals))
|
||||
prey = pick(meals)
|
||||
to_chat(prey, "<span class='heavy_brass'><font size=5>\"You will do, heretic.\"</font></span>\n\
|
||||
<span class='userdanger'You feel something massive turn its crushing focus to you...</span>")
|
||||
<span class='userdanger'>You feel something massive turn its crushing focus to you...</span>")
|
||||
prey << 'sound/effects/ratvar_reveal.ogg'
|
||||
else
|
||||
if((!istype(prey, /obj/singularity/narsie) && prob(10) && LAZYLEN(meals) > 1) || prey.z != z || !(prey in meals))
|
||||
|
||||
@@ -1,34 +1,31 @@
|
||||
|
||||
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/cult = list()
|
||||
var/list/cult_objectives = list()
|
||||
var/eldergod = 1 //for the summon god objective
|
||||
|
||||
/proc/iscultist(mob/living/M)
|
||||
return istype(M) && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_CULT)
|
||||
|
||||
/proc/is_sacrifice_target(datum/mind/mind)
|
||||
if(SSticker.mode.name == "cult")
|
||||
var/datum/game_mode/cult/cult_mode = SSticker.mode
|
||||
if(mind == cult_mode.sacrifice_target)
|
||||
return 1
|
||||
return 0
|
||||
if(mind == GLOB.sac_mind)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/proc/is_convertable_to_cult(mob/living/M)
|
||||
if(!istype(M))
|
||||
return 0
|
||||
return FALSE
|
||||
if(M.mind)
|
||||
if(ishuman(M) && (M.mind.assigned_role in list("Captain", "Chaplain")))
|
||||
return 0
|
||||
return FALSE
|
||||
if(is_sacrifice_target(M.mind))
|
||||
return 0
|
||||
return FALSE
|
||||
if(M.mind.enslaved_to && !iscultist(M.mind.enslaved_to))
|
||||
return 0
|
||||
return FALSE
|
||||
else
|
||||
return 0
|
||||
return FALSE
|
||||
if(M.isloyal() || issilicon(M) || isbot(M) || isdrone(M) || is_servant_of_ratvar(M))
|
||||
return 0 //can't convert machines, shielded, or ratvar's dogs
|
||||
return 1
|
||||
return FALSE //can't convert machines, shielded, or ratvar's dogs
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/cult
|
||||
name = "cult"
|
||||
@@ -47,14 +44,13 @@
|
||||
<span class='notice'>Crew</span>: Prevent the cult from expanding and drive it out."
|
||||
|
||||
var/finished = 0
|
||||
var/eldergod = 1 //for the summon god objective
|
||||
|
||||
var/acolytes_needed = 10 //for the survive objective
|
||||
var/acolytes_survived = 0
|
||||
|
||||
var/datum/mind/sacrifice_target = null//The target to be sacrificed
|
||||
var/list/cultists_to_cult = list() //the cultists we'll convert
|
||||
|
||||
|
||||
/datum/game_mode/cult/pre_setup()
|
||||
cult_objectives += "sacrifice"
|
||||
cult_objectives += "eldergod"
|
||||
@@ -82,22 +78,6 @@
|
||||
return (cultists_to_cult.len>=required_enemies)
|
||||
|
||||
|
||||
/datum/game_mode/cult/proc/memorize_cult_objectives(datum/mind/cult_mind)
|
||||
for(var/obj_count = 1,obj_count <= cult_objectives.len,obj_count++)
|
||||
var/explanation
|
||||
switch(cult_objectives[obj_count])
|
||||
if("survive")
|
||||
explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station."
|
||||
if("sacrifice")
|
||||
if(sacrifice_target)
|
||||
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it."
|
||||
else
|
||||
explanation = "Free objective."
|
||||
if("eldergod")
|
||||
explanation = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie' with nine acolytes on it. You must do this after sacrificing your target."
|
||||
to_chat(cult_mind.current, "<B>Objective #[obj_count]</B>: [explanation]")
|
||||
cult_mind.memory += "<B>Objective #[obj_count]</B>: [explanation]<BR>"
|
||||
|
||||
/datum/game_mode/cult/post_setup()
|
||||
modePlayer += cultists_to_cult
|
||||
if("sacrifice" in cult_objectives)
|
||||
@@ -108,9 +88,18 @@
|
||||
if(player.mind && !(player.mind in cultists_to_cult))
|
||||
possible_targets += player.mind
|
||||
if(possible_targets.len > 0)
|
||||
sacrifice_target = pick(possible_targets)
|
||||
if(!sacrifice_target)
|
||||
GLOB.sac_mind = pick(possible_targets)
|
||||
if(!GLOB.sac_mind)
|
||||
message_admins("Cult Sacrifice: ERROR - Null target chosen!")
|
||||
else
|
||||
var/datum/job/sacjob = SSjob.GetJob(GLOB.sac_mind.assigned_role)
|
||||
var/datum/preferences/sacface = GLOB.sac_mind.current.client.prefs
|
||||
var/icon/reshape = get_flat_human_icon(null, sacjob, sacface)
|
||||
reshape.Shift(SOUTH, 4)
|
||||
reshape.Shift(EAST, 1)
|
||||
reshape.Crop(7,4,26,31)
|
||||
reshape.Crop(-5,-3,26,30)
|
||||
GLOB.sac_image = reshape
|
||||
else
|
||||
message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
|
||||
for(var/datum/mind/cult_mind in cultists_to_cult)
|
||||
@@ -198,7 +187,7 @@
|
||||
if(cult_objectives.Find("eldergod"))
|
||||
cult_fail += eldergod //1 by default, 0 if the elder god has been summoned at least once
|
||||
if(cult_objectives.Find("sacrifice"))
|
||||
if(sacrifice_target && !GLOB.sacrificed.Find(sacrifice_target)) //if the target has been GLOB.sacrificed, ignore this step. otherwise, add 1 to cult_fail
|
||||
if(GLOB.sac_mind && GLOB.sac_complete) //if the target has been GLOB.sacrificed, ignore this step. otherwise, add 1 to cult_fail
|
||||
cult_fail++
|
||||
return cult_fail //if any objectives aren't met, failure
|
||||
|
||||
@@ -243,16 +232,12 @@
|
||||
SSblackbox.add_details("cult_objective","cult_survive|FAIL|[acolytes_needed]")
|
||||
SSticker.news_report = CULT_FAILURE
|
||||
if("sacrifice")
|
||||
if(sacrifice_target)
|
||||
if(sacrifice_target in GLOB.sacrificed)
|
||||
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. <span class='greenannounce'>Success!</span>"
|
||||
SSblackbox.add_details("cult_objective","cult_sacrifice|SUCCESS")
|
||||
else if(sacrifice_target && sacrifice_target.current)
|
||||
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. <span class='boldannounce'>Fail.</span>"
|
||||
SSblackbox.add_details("cult_objective","cult_sacrifice|FAIL")
|
||||
else
|
||||
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. <span class='boldannounce'>Fail (Gibbed).</span>"
|
||||
SSblackbox.add_details("cult_objective","cult_sacrifice|FAIL|GIBBED")
|
||||
if(GLOB.sac_complete)
|
||||
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. <span class='greenannounce'>Success!</span>"
|
||||
SSblackbox.add_details("cult_objective","cult_sacrifice|SUCCESS")
|
||||
else
|
||||
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. <span class='boldannounce'>Fail.</span>"
|
||||
SSblackbox.add_details("cult_objective","cult_sacrifice|FAIL")
|
||||
if("eldergod")
|
||||
if(!eldergod)
|
||||
explanation = "Summon Nar-Sie. <span class='greenannounce'>Success!</span>"
|
||||
@@ -269,12 +254,45 @@
|
||||
return 1
|
||||
|
||||
|
||||
/datum/game_mode/proc/auto_declare_completion_cult()
|
||||
if( cult.len || (SSticker && istype(SSticker.mode,/datum/game_mode/cult)) )
|
||||
var/text = "<br><font size=3><b>The cultists were:</b></font>"
|
||||
for(var/datum/mind/cultist in cult)
|
||||
text += printplayer(cultist)
|
||||
|
||||
text += "<br>"
|
||||
|
||||
to_chat(world, text)
|
||||
/datum/game_mode/proc/datum_cult_completion()
|
||||
var/text = ""
|
||||
var/acolytes_survived = 0
|
||||
for(var/datum/mind/cult_mind in cult)
|
||||
if (cult_mind.current && cult_mind.current.stat != DEAD)
|
||||
if(cult_mind.current.onCentcom() || cult_mind.current.onSyndieBase())
|
||||
acolytes_survived++
|
||||
var/cult_fail = 0
|
||||
cult_fail += eldergod
|
||||
if(!GLOB.sac_complete)
|
||||
cult_fail++
|
||||
if(!cult_fail)
|
||||
SSblackbox.set_details("round_end_result","win - cult win")
|
||||
SSblackbox.set_val("round_end_result",acolytes_survived)
|
||||
to_chat(world, "<span class='greentext'>The cult has succeeded! Nar-sie has snuffed out another torch in the void!</span>")
|
||||
else
|
||||
SSblackbox.set_details("round_end_result","loss - staff stopped the cult")
|
||||
SSblackbox.set_val("round_end_result",acolytes_survived)
|
||||
to_chat(world, "<span class='redtext'>The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!</span>")
|
||||
if(cult_objectives.len)
|
||||
text += "<br><b>The cultists' objectives were:</b>"
|
||||
for(var/obj_count in 1 to 2)
|
||||
var/explanation
|
||||
switch(cult_objectives[obj_count])
|
||||
if("sacrifice")
|
||||
if(GLOB.sac_complete)
|
||||
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. <span class='greenannounce'>Success!</span>"
|
||||
SSblackbox.add_details("cult_objective","cult_sacrifice|SUCCESS")
|
||||
else
|
||||
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. <span class='boldannounce'>Fail.</span>"
|
||||
SSblackbox.add_details("cult_objective","cult_sacrifice|FAIL")
|
||||
if("eldergod")
|
||||
if(!eldergod)
|
||||
explanation = "Summon Nar-Sie. <span class='greenannounce'>Success!</span>"
|
||||
SSblackbox.add_details("cult_objective","cult_narsie|SUCCESS")
|
||||
SSticker.news_report = CULT_SUMMON
|
||||
else
|
||||
explanation = "Summon Nar-Sie. <span class='boldannounce'>Fail.</span>"
|
||||
SSblackbox.add_details("cult_objective","cult_narsie|FAIL")
|
||||
SSticker.news_report = CULT_FAILURE
|
||||
text += "<br><B>Objective #[obj_count]</B>: [explanation]"
|
||||
to_chat(world, text)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Contains cult communion, guide, and cult master abilities
|
||||
#define MARK_COOLDOWN
|
||||
|
||||
/datum/action/innate/cultcomm
|
||||
name = "Communion"
|
||||
@@ -19,11 +21,22 @@
|
||||
cultist_commune(usr, input)
|
||||
|
||||
/proc/cultist_commune(mob/living/user, message)
|
||||
var/my_message
|
||||
if(!message)
|
||||
return
|
||||
user.whisper("O bidai nabora se[pick("'","`")]sma!")
|
||||
user.whisper("O bidai nabora se[pick("'","`")]sma!", language = /datum/language/common)
|
||||
user.whisper(html_decode(message))
|
||||
var/my_message = "<span class='cultitalic'><b>[(ishuman(user) ? "Acolyte" : "Construct")] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]:</b> [message]</span>"
|
||||
var/title = "Acolyte"
|
||||
var/span = "cultitalic"
|
||||
if(user.mind && user.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER))
|
||||
span = "cultlarge"
|
||||
if(ishuman(user))
|
||||
title = "Master"
|
||||
else
|
||||
title = "Lord"
|
||||
else if(!ishuman(user))
|
||||
title = "Construct"
|
||||
my_message = "<span class='[span]'><b>[title] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]:</b> [message]</span>"
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
if(iscultist(M))
|
||||
to_chat(M, my_message)
|
||||
@@ -65,3 +78,159 @@
|
||||
popup.set_content(text)
|
||||
popup.open()
|
||||
return 1
|
||||
|
||||
/mob/living/proc/cult_master()
|
||||
set category = "Cultist"
|
||||
set name = "Assert Leadership"
|
||||
pollCultists(src) // This proc handles the distribution of cult master actions
|
||||
|
||||
/datum/action/innate/cultmast
|
||||
background_icon_state = "bg_demon"
|
||||
buttontooltipstyle = "cult"
|
||||
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_CONSCIOUS
|
||||
|
||||
/datum/action/innate/cultmast/IsAvailable()
|
||||
if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER))
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/cultmast/finalreck
|
||||
name = "Final Reckoning"
|
||||
desc = "A single-use spell that brings the entire cult to the master's location."
|
||||
button_icon_state = "sintouch"
|
||||
|
||||
/datum/action/innate/cultmast/finalreck/Activate()
|
||||
for(var/i in 1 to 4)
|
||||
chant(i)
|
||||
var/list/destinations = list()
|
||||
for(var/turf/T in orange(1, owner))
|
||||
if(!is_blocked_turf(T, TRUE))
|
||||
destinations += T
|
||||
if(!LAZYLEN(destinations))
|
||||
to_chat(owner, "<span class='warning'>You need more space to summon the cult!</span>")
|
||||
return
|
||||
if(do_after(owner, 30, target = owner))
|
||||
for(var/datum/mind/B in SSticker.mode.cult)
|
||||
if(B.current && B.current.stat != DEAD)
|
||||
var/turf/mobloc = get_turf(B.current)
|
||||
switch(i)
|
||||
if(1)
|
||||
new /obj/effect/overlay/temp/cult/sparks(mobloc, B.current.dir)
|
||||
playsound(mobloc, "sparks", 50, 1)
|
||||
if(2)
|
||||
new /obj/effect/overlay/temp/dir_setting/cult/phase/out(mobloc, B.current.dir)
|
||||
playsound(mobloc, "sparks", 75, 1)
|
||||
if(3)
|
||||
new /obj/effect/overlay/temp/dir_setting/cult/phase(mobloc, B.current.dir)
|
||||
playsound(mobloc, "sparks", 100, 1)
|
||||
if(4)
|
||||
playsound(mobloc, 'sound/magic/exit_blood.ogg', 100, 1)
|
||||
if(B.current != owner)
|
||||
B.current.setDir(SOUTH)
|
||||
var/turf/final = pick(destinations)
|
||||
new /obj/effect/overlay/temp/cult/blood(final)
|
||||
addtimer(CALLBACK(B.current, /mob/.proc/reckon, final), 10)
|
||||
else
|
||||
return
|
||||
GLOB.reckoning_complete = TRUE
|
||||
Remove(owner)
|
||||
|
||||
/mob/proc/reckon(turf/final)
|
||||
new /obj/effect/overlay/temp/cult/blood/out(get_turf(src))
|
||||
forceMove(final)
|
||||
|
||||
/datum/action/innate/cultmast/finalreck/proc/chant(chant_number)
|
||||
switch(chant_number)
|
||||
if(1)
|
||||
owner.say("C'arta forbici!", language = /datum/language/common)
|
||||
if(2)
|
||||
owner.say("Pleggh e'ntrath!", language = /datum/language/common)
|
||||
playsound(get_turf(owner),'sound/magic/clockwork/narsie_attack.ogg', 50, 1)
|
||||
if(3)
|
||||
owner.say("Barhah hra zar'garis!", language = /datum/language/common)
|
||||
playsound(get_turf(owner),'sound/magic/clockwork/narsie_attack.ogg', 75, 1)
|
||||
if(4)
|
||||
owner.say("N'ath reth sh'yro eth d'rekkathnor!!!", language = /datum/language/common)
|
||||
playsound(get_turf(owner),'sound/magic/clockwork/narsie_attack.ogg', 100, 1)
|
||||
|
||||
/datum/action/innate/cultmast/cultmark
|
||||
name = "Mark Target"
|
||||
desc = "Marks a target for the cult."
|
||||
button_icon_state = "cult_mark"
|
||||
var/obj/effect/proc_holder/cultmark/CM
|
||||
var/cooldown = 0
|
||||
var/base_cooldown = 1200
|
||||
|
||||
/datum/action/innate/cultmast/cultmark/New()
|
||||
CM = new()
|
||||
CM.attached_action = src
|
||||
..()
|
||||
|
||||
/datum/action/innate/cultmast/cultmark/IsAvailable()
|
||||
if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER))
|
||||
return 0
|
||||
if(cooldown > world.time)
|
||||
if(!CM.active)
|
||||
owner << "<span class='cultlarge'><b>You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can mark another target!</b></span>"
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/cultmast/cultmark/Destroy()
|
||||
QDEL_NULL(CM)
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/cultmast/cultmark/Activate()
|
||||
CM.toggle(owner) //the important bit
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/cultmark
|
||||
active = FALSE
|
||||
ranged_mousepointer = 'icons/effects/cult_target.dmi'
|
||||
var/datum/action/innate/cultmast/cultmark/attached_action
|
||||
|
||||
/obj/effect/proc_holder/cultmark/Destroy()
|
||||
attached_action = null
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/cultmark/proc/toggle(mob/user)
|
||||
if(active)
|
||||
remove_ranged_ability("<span class='cult'>You cease the marking ritual.</span>")
|
||||
else
|
||||
add_ranged_ability(user, "<span class='cult'>You prepare to mark a target for your cult...</span>")
|
||||
|
||||
/obj/effect/proc_holder/cultmark/InterceptClickOn(mob/living/caller, params, atom/target)
|
||||
if(..())
|
||||
return
|
||||
if(ranged_ability_user.incapacitated())
|
||||
remove_ranged_ability()
|
||||
return
|
||||
var/turf/T = get_turf(ranged_ability_user)
|
||||
if(!isturf(T))
|
||||
return FALSE
|
||||
if(target in view(7, get_turf(ranged_ability_user)))
|
||||
GLOB.blood_target = target
|
||||
var/area/A = get_area(target)
|
||||
attached_action.cooldown = world.time + attached_action.base_cooldown
|
||||
addtimer(CALLBACK(attached_action.owner, /mob.proc/update_action_buttons_icon), attached_action.base_cooldown)
|
||||
GLOB.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER)
|
||||
GLOB.blood_target_image.appearance_flags = RESET_COLOR
|
||||
GLOB.blood_target_image.pixel_x = -target.pixel_x
|
||||
GLOB.blood_target_image.pixel_y = -target.pixel_y
|
||||
for(var/datum/mind/B in SSticker.mode.cult)
|
||||
if(B.current && B.current.stat != DEAD && B.current.client)
|
||||
to_chat(B.current, "<span class='cultlarge'><b>Master [ranged_ability_user] has marked [GLOB.blood_target] in the [A.name] as the cult's top priority, get there immediately!</b></span>")
|
||||
B.current << pick(sound('sound/hallucinations/over_here2.ogg',0,1,75), sound('sound/hallucinations/over_here3.ogg',0,1,75))
|
||||
B.current.client.images += GLOB.blood_target_image
|
||||
attached_action.owner.update_action_buttons_icon()
|
||||
remove_ranged_ability("<span class='cult'>The marking rite is complete! It will last for 90 seconds.</span>")
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/reset_blood_target), 900, TIMER_OVERRIDE)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/proc/reset_blood_target()
|
||||
for(var/datum/mind/B in SSticker.mode.cult)
|
||||
if(B.current && B.current.stat != DEAD && B.current.client)
|
||||
if(GLOB.blood_target)
|
||||
to_chat(B.current,"<span class='cultlarge'><b>The blood mark has expired!</b></span>")
|
||||
B.current.client.images -= GLOB.blood_target_image
|
||||
QDEL_NULL(GLOB.blood_target)
|
||||
@@ -213,7 +213,7 @@
|
||||
flags_inv = HIDEJUMPSUIT
|
||||
allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade)
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
armor = list(melee = -50, bullet = -50, laser = -100,energy = -50, bomb = -50, bio = -50, rad = -50, fire = 0, acid = 0)
|
||||
armor = list(melee = -50, bullet = -50, laser = -50,energy = -50, bomb = -50, bio = -50, rad = -50, fire = 0, acid = 0)
|
||||
slowdown = -1
|
||||
hoodtype = /obj/item/clothing/head/hooded/berserkerhood
|
||||
|
||||
|
||||
@@ -197,35 +197,30 @@ This file contains the arcane tome files.
|
||||
if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated() || !check_rune_turf(Turf, user))
|
||||
return
|
||||
if(ispath(rune_to_scribe, /obj/effect/rune/narsie))
|
||||
if(SSticker.mode.name == "cult")
|
||||
var/datum/game_mode/cult/cult_mode = SSticker.mode
|
||||
if(!("eldergod" in cult_mode.cult_objectives))
|
||||
to_chat(user, "<span class='warning'>Nar-Sie does not wish to be summoned!</span>")
|
||||
return
|
||||
if(cult_mode.sacrifice_target && !(cult_mode.sacrifice_target in GLOB.sacrificed))
|
||||
to_chat(user, "<span class='warning'>The sacrifice is not complete. The portal would lack the power to open if you tried!</span>")
|
||||
return
|
||||
if(!cult_mode.eldergod)
|
||||
to_chat(user, "<span class='cultlarge'>\"I am already here. There is no need to try to summon me now.\"</span>")
|
||||
return
|
||||
if((loc.z && loc.z != ZLEVEL_STATION) || !A.blob_allowed)
|
||||
to_chat(user, "<span class='warning'>The Geometer is not interested in lesser locations; the station is the prize!</span>")
|
||||
return
|
||||
var/confirm_final = alert(user, "This is the FINAL step to summon Nar-Sie, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for Nar-Sie!", "No")
|
||||
if(confirm_final == "No")
|
||||
to_chat(user, "<span class='cult'>You decide to prepare further before scribing the rune.</span>")
|
||||
return
|
||||
Turf = get_turf(user)
|
||||
A = get_area(src)
|
||||
if(!check_rune_turf(Turf, user) || (loc.z && loc.z != ZLEVEL_STATION)|| !A.blob_allowed)
|
||||
return
|
||||
priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensionsal Affairs", 'sound/AI/spanomalies.ogg')
|
||||
for(var/B in spiral_range_turfs(1, user, 1))
|
||||
var/obj/structure/emergency_shield/sanguine/N = new(B)
|
||||
shields += N
|
||||
else
|
||||
if(!("eldergod" in SSticker.mode.cult_objectives))
|
||||
to_chat(user, "<span class='warning'>Nar-Sie does not wish to be summoned!</span>")
|
||||
return
|
||||
if(!GLOB.sac_complete)
|
||||
to_chat(user, "<span class='warning'>The sacrifice is not complete. The portal would lack the power to open if you tried!</span>")
|
||||
return
|
||||
if(!SSticker.mode.eldergod)
|
||||
to_chat(user, "<span class='cultlarge'>\"I am already here. There is no need to try to summon me now.\"</span>")
|
||||
return
|
||||
if((loc.z && loc.z != ZLEVEL_STATION) || !A.blob_allowed)
|
||||
to_chat(user, "<span class='warning'>The Geometer is not interested in lesser locations; the station is the prize!</span>")
|
||||
return
|
||||
var/confirm_final = alert(user, "This is the FINAL step to summon Nar-Sie; it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for Nar-Sie!", "No")
|
||||
if(confirm_final == "No")
|
||||
to_chat(user, "<span class='cult'>You decide to prepare further before scribing the rune.</span>")
|
||||
return
|
||||
Turf = get_turf(user)
|
||||
A = get_area(src)
|
||||
if(!check_rune_turf(Turf, user) || (loc.z && loc.z != ZLEVEL_STATION)|| !A.blob_allowed)
|
||||
return
|
||||
priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg')
|
||||
for(var/B in spiral_range_turfs(1, user, 1))
|
||||
var/obj/structure/emergency_shield/sanguine/N = new(B)
|
||||
shields += N
|
||||
user.visible_message("<span class='warning'>[user] [user.blood_volume ? "cuts open their arm and begins writing in their own blood":"begins sketching out a strange design"]!</span>", \
|
||||
"<span class='cult'>You [user.blood_volume ? "slice open your arm and ":""]begin drawing a sigil of the Geometer.</span>")
|
||||
if(user.blood_volume)
|
||||
|
||||
@@ -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)
|
||||
@@ -309,10 +308,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()
|
||||
|
||||
@@ -398,23 +398,23 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
return 1
|
||||
|
||||
/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers)
|
||||
var/big_sac = FALSE
|
||||
if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || is_sacrifice_target(sacrificial.mind)) && invokers.len < 3)
|
||||
for(var/M in invokers)
|
||||
to_chat(M, "<span class='cultitalic'>[sacrificial] is too greatly linked to the world! You need three acolytes!</span>")
|
||||
log_game("Offer rune failed - not enough acolytes and target is living or sac target")
|
||||
return FALSE
|
||||
var/sacrifice_fulfilled = FALSE
|
||||
|
||||
if(sacrificial.mind)
|
||||
GLOB.sacrificed += sacrificial.mind
|
||||
if(is_sacrifice_target(sacrificial.mind))
|
||||
sacrifice_fulfilled = TRUE
|
||||
GLOB.sac_complete = TRUE
|
||||
big_sac = TRUE
|
||||
else
|
||||
GLOB.sacrificed += sacrificial
|
||||
|
||||
new /obj/effect/overlay/temp/cult/sac(get_turf(src))
|
||||
for(var/M in invokers)
|
||||
if(sacrifice_fulfilled)
|
||||
if(big_sac)
|
||||
to_chat(M, "<span class='cultlarge'>\"Yes! This is the one I desire! You have done well.\"</span>")
|
||||
else
|
||||
if(ishuman(sacrificial) || iscyborg(sacrificial))
|
||||
@@ -451,7 +451,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
scribe_delay = 450 //how long the rune takes to create
|
||||
scribe_damage = 40.1 //how much damage you take doing it
|
||||
var/used
|
||||
var/ignore_gamemode = FALSE
|
||||
var/ignore_gamemode = TRUE
|
||||
|
||||
/obj/effect/rune/narsie/Initialize(mapload, set_keyword)
|
||||
. = ..()
|
||||
@@ -490,7 +490,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
//BEGIN THE SUMMONING
|
||||
used = 1
|
||||
..()
|
||||
send_to_playing_players('sound/effects/dimensional_rend.ogg') //There used to be a message for this but every time it was changed it got edgier so I removed it
|
||||
send_to_playing_players('sound/effects/dimensional_rend.ogg')
|
||||
var/turf/T = get_turf(src)
|
||||
sleep(40)
|
||||
if(src)
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
//Supply Talisman: Has a few unique effects. Granted only to starter cultists.
|
||||
/obj/item/weapon/paper/talisman/supply
|
||||
cultist_name = "Supply Talisman"
|
||||
cultist_desc = "A multi-use talisman that can create various objects. Intended to increase the cult's strength early on."
|
||||
invocation = null
|
||||
uses = 3
|
||||
var/list/possible_summons = list(
|
||||
/datum/cult_supply/tome,
|
||||
/datum/cult_supply/metal,
|
||||
/datum/cult_supply/talisman/teleport,
|
||||
/datum/cult_supply/talisman/emp,
|
||||
/datum/cult_supply/talisman/stun,
|
||||
/datum/cult_supply/talisman/veil,
|
||||
/datum/cult_supply/soulstone,
|
||||
/datum/cult_supply/construct_shell
|
||||
)
|
||||
|
||||
/obj/item/weapon/paper/talisman/supply/invoke(mob/living/user, successfuluse = 1)
|
||||
var/list/dat = list()
|
||||
dat += "<B>There are [uses] bloody runes on the parchment.</B><BR>"
|
||||
dat += "Please choose the chant to be imbued into the fabric of reality.<BR>"
|
||||
dat += "<HR>"
|
||||
for(var/s in possible_summons)
|
||||
var/datum/cult_supply/S = s
|
||||
dat += "<a href='?src=\ref[src];id=[initial(S.id)]'>[initial(S.invocation)]</a> - [initial(S.desc)]<br>"
|
||||
var/datum/browser/popup = new(user, "talisman", "", 400, 400)
|
||||
popup.set_content(dat.Join(""))
|
||||
popup.open()
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/paper/talisman/supply/Topic(href, href_list)
|
||||
world.log << "[usr], [href], [href_list]"
|
||||
if(QDELETED(src) || usr.incapacitated() || !in_range(src, usr))
|
||||
return
|
||||
|
||||
var/id = href_list["id"]
|
||||
var/datum/cult_supply/match
|
||||
|
||||
for(var/s in possible_summons)
|
||||
var/datum/cult_supply/S = s
|
||||
if(initial(S.id) == id)
|
||||
match = S
|
||||
break
|
||||
|
||||
if(!match)
|
||||
to_chat(usr, "<span class='userdanger'>The fabric of reality quivers in agony.</span>")
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
var/summon_type = initial(match.summon_type)
|
||||
|
||||
|
||||
var/atom/movable/AM = new summon_type(T)
|
||||
if(istype(AM, /obj/item))
|
||||
usr.put_in_hands(AM)
|
||||
|
||||
uses--
|
||||
if(uses <= 0)
|
||||
to_chat(usr, "<span class='warning'>[src] crumbles to dust.</span>")
|
||||
burn()
|
||||
|
||||
/obj/item/weapon/paper/talisman/supply/weak
|
||||
cultist_name = "Lesser Supply Talisman"
|
||||
uses = 2
|
||||
|
||||
/obj/item/weapon/paper/talisman/supply/weak/Initialize(mapload)
|
||||
. = ..()
|
||||
// no runed metal from lesser talismans.
|
||||
possible_summons -= /datum/cult_supply/metal
|
||||
|
||||
/datum/cult_supply
|
||||
var/id = "used_popcorn"
|
||||
var/invocation = "Pla'ceho'lder."
|
||||
var/desc = "Summons a generic supply item, to aid the cult."
|
||||
var/summon_type = /obj/item/trash/popcorn // wait this isn't useful
|
||||
|
||||
/datum/cult_supply/tome
|
||||
id = "arcane_tome"
|
||||
invocation = "N'ath reth sh'yro eth d'raggathnor!"
|
||||
desc = "Summons an arcane tome, used to scribe runes."
|
||||
summon_type = /obj/item/weapon/tome
|
||||
|
||||
/datum/cult_supply/metal
|
||||
id = "runed_metal"
|
||||
invocation = "Bar'tea eas!"
|
||||
desc = "Provides 5 runed metal, which can build a variety of cult structures."
|
||||
summon_type = /obj/item/stack/sheet/runed_metal/five
|
||||
|
||||
/datum/cult_supply/talisman/teleport
|
||||
id = "teleport_talisman"
|
||||
invocation = "Sas'so c'arta forbici!"
|
||||
desc = "Allows you to move to a selected teleportation rune."
|
||||
summon_type = /obj/item/weapon/paper/talisman/teleport
|
||||
|
||||
/datum/cult_supply/talisman/emp
|
||||
id = "emp_talisman"
|
||||
invocation = "Ta'gh fara'qha fel d'amar det!"
|
||||
desc = "Allows you to destroy technology in a short range."
|
||||
summon_type = /obj/item/weapon/paper/talisman/emp
|
||||
|
||||
/datum/cult_supply/talisman/stun
|
||||
id = "stun_talisman"
|
||||
invocation = "Fuu ma'jin!"
|
||||
desc = "Allows you to stun a person by attacking them with the talisman. Does not work on people holding a holy weapon!"
|
||||
summon_type = /obj/item/weapon/paper/talisman/stun
|
||||
|
||||
/datum/cult_supply/talisman/veil
|
||||
id = "veil_talisman"
|
||||
invocation = "Kla'atu barada nikt'o!"
|
||||
desc = "Two use talisman, first use makes all nearby runes invisible, secnd use reveals nearby hidden runes."
|
||||
summon_type = /obj/item/weapon/paper/talisman/true_sight
|
||||
|
||||
/datum/cult_supply/soulstone
|
||||
id = "soulstone"
|
||||
invocation = "Kal'om neth!"
|
||||
desc = "Summons a soul stone, used to capture the spirits of dead or dying humans."
|
||||
summon_type = /obj/item/device/soulstone
|
||||
|
||||
/datum/cult_supply/construct_shell
|
||||
id = "construct_shell"
|
||||
invocation = "Daa'ig osk!"
|
||||
desc = "Summons a construct shell for use with soulstone-captured souls. It is too large to carry on your person."
|
||||
summon_type = /obj/structure/constructshell
|
||||
|
||||
@@ -45,74 +45,6 @@
|
||||
var/mob/living/carbon/C = user
|
||||
C.apply_damage(10, BRUTE, "head")
|
||||
|
||||
//Supply Talisman: Has a few unique effects. Granted only to starter cultists.
|
||||
/obj/item/weapon/paper/talisman/supply
|
||||
cultist_name = "Supply Talisman"
|
||||
cultist_desc = "A multi-use talisman that can create various objects. Intended to increase the cult's strength early on."
|
||||
invocation = null
|
||||
uses = 3
|
||||
|
||||
/obj/item/weapon/paper/talisman/supply/invoke(mob/living/user, successfuluse = 1)
|
||||
var/dat = "<B>There are [uses] bloody runes on the parchment.</B><BR>"
|
||||
dat += "Please choose the chant to be imbued into the fabric of reality.<BR>"
|
||||
dat += "<HR>"
|
||||
dat += "<A href='?src=\ref[src];rune=newtome'>N'ath reth sh'yro eth d'raggathnor!</A> - Summons an arcane tome, used to scribe runes and communicate with other cultists.<BR>"
|
||||
dat += "<A href='?src=\ref[src];rune=metal'>Bar'tea eas!</A> - Provides 5 runed metal.<BR>"
|
||||
dat += "<A href='?src=\ref[src];rune=teleport'>Sas'so c'arta forbici!</A> - Allows you to move to a selected teleportation rune.<BR>"
|
||||
dat += "<A href='?src=\ref[src];rune=emp'>Ta'gh fara'qha fel d'amar det!</A> - Allows you to destroy technology in a short range.<BR>"
|
||||
dat += "<A href='?src=\ref[src];rune=runestun'>Fuu ma'jin!</A> - Allows you to stun a person by attacking them with the talisman.<BR>"
|
||||
dat += "<A href='?src=\ref[src];rune=veiling'>Kla'atu barada nikt'o!</A> - Two use talisman, first use makes all nearby runes invisible, second use reveals nearby hidden runes.<BR>"
|
||||
dat += "<A href='?src=\ref[src];rune=soulstone'>Kal'om neth!</A> - Summons a soul stone, used to capure the spirits of dead or dying humans.<BR>"
|
||||
dat += "<A href='?src=\ref[src];rune=construct'>Daa'ig osk!</A> - Summons a construct shell for use with soulstone-captured souls. It is too large to carry on your person.<BR>"
|
||||
var/datum/browser/popup = new(user, "talisman", "", 400, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/paper/talisman/supply/Topic(href, href_list)
|
||||
if(src)
|
||||
if(usr.stat || usr.restrained() || !in_range(src, usr))
|
||||
return
|
||||
if(href_list["rune"])
|
||||
switch(href_list["rune"])
|
||||
if("newtome")
|
||||
var/obj/item/weapon/tome/T = new(usr)
|
||||
usr.put_in_hands(T)
|
||||
if("metal")
|
||||
if(istype(src, /obj/item/weapon/paper/talisman/supply/weak))
|
||||
usr.visible_message("<span class='cultitalic'>Lesser supply talismans lack the strength to materialize runed metal!</span>")
|
||||
return
|
||||
var/obj/item/stack/sheet/runed_metal/R = new(usr,5)
|
||||
usr.put_in_hands(R)
|
||||
if("teleport")
|
||||
var/obj/item/weapon/paper/talisman/teleport/T = new(usr)
|
||||
usr.put_in_hands(T)
|
||||
if("emp")
|
||||
var/obj/item/weapon/paper/talisman/emp/T = new(usr)
|
||||
usr.put_in_hands(T)
|
||||
if("runestun")
|
||||
var/obj/item/weapon/paper/talisman/stun/T = new(usr)
|
||||
usr.put_in_hands(T)
|
||||
if("soulstone")
|
||||
var/obj/item/device/soulstone/T = new(usr)
|
||||
usr.put_in_hands(T)
|
||||
if("construct")
|
||||
new /obj/structure/constructshell(get_turf(usr))
|
||||
if("veiling")
|
||||
var/obj/item/weapon/paper/talisman/true_sight/T = new(usr)
|
||||
usr.put_in_hands(T)
|
||||
src.uses--
|
||||
if(src.uses <= 0)
|
||||
if(iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
C.drop_item()
|
||||
visible_message("<span class='warning'>[src] crumbles to dust.</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/paper/talisman/supply/weak
|
||||
cultist_name = "Lesser Supply Talisman"
|
||||
uses = 2
|
||||
|
||||
//Rite of Translocation: Same as rune
|
||||
/obj/item/weapon/paper/talisman/teleport
|
||||
cultist_name = "Talisman of Teleportation"
|
||||
@@ -147,9 +79,10 @@
|
||||
if(is_blocked_turf(target, TRUE))
|
||||
to_chat(user, "<span class='warning'>The target rune is blocked. Attempting to teleport to it would be massively unwise.</span>")
|
||||
return ..(user, 0)
|
||||
user.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [user.p_they()] disappear in a flash of red light!</span>", \
|
||||
"<span class='cultitalic'>You speak the words of the talisman and find yourself somewhere else!</span>")
|
||||
user.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [user.p_they()] disappear with a sharp crack!</span>", \
|
||||
"<span class='cultitalic'>You speak the words of the talisman and find yourself somewhere else!</span>", "<i>You hear a sharp crack.</i>")
|
||||
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>")
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "devil"
|
||||
config_tag = "devil"
|
||||
antag_flag = ROLE_DEVIL
|
||||
protected_jobs = list("Lawyer", "Librarian", "Chaplain", "Head of Security", "Captain", "AI")
|
||||
protected_jobs = list("Lawyer", "Curator", "Chaplain", "Head of Security", "Captain", "AI")
|
||||
required_players = 0
|
||||
required_enemies = 1
|
||||
recommended_enemies = 4
|
||||
|
||||
@@ -85,7 +85,6 @@
|
||||
SSblackbox.set_details("game_mode","[SSticker.mode]")
|
||||
if(GLOB.revdata.commit)
|
||||
SSblackbox.set_details("revision","[GLOB.revdata.commit]")
|
||||
SSblackbox.set_details("server_ip","[world.internet_address]:[world.port]")
|
||||
if(report)
|
||||
addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h))
|
||||
generate_station_goals()
|
||||
@@ -258,6 +257,8 @@
|
||||
if(escaped_total > 0)
|
||||
SSblackbox.set_val("escaped_total",escaped_total)
|
||||
send2irc("Server", "Round just ended.")
|
||||
if(cult.len && !istype(SSticker.mode,/datum/game_mode/cult))
|
||||
datum_cult_completion()
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define DOM_BLOCKED_SPAM_CAP 6
|
||||
|
||||
/obj/machinery/dominator
|
||||
name = "dominator"
|
||||
desc = "A visibly sinister device. Looks like you can break it if you hit it enough."
|
||||
@@ -13,9 +15,20 @@
|
||||
var/datum/gang/gang
|
||||
var/operating = 0 //0=standby or broken, 1=takeover
|
||||
var/warned = 0 //if this device has set off the warning at <3 minutes yet
|
||||
var/spam_prevention = DOM_BLOCKED_SPAM_CAP //first message is immediate
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
var/obj/effect/countdown/dominator/countdown
|
||||
|
||||
/proc/dominator_excessive_walls(atom/A)
|
||||
var/open = 0
|
||||
for(var/turf/T in circleviewturfs(center=A,radius=3))
|
||||
if(!istype(T, /turf/closed))
|
||||
open++
|
||||
if(open < 40)
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/dominator/tesla_act()
|
||||
qdel(src)
|
||||
|
||||
@@ -48,6 +61,16 @@
|
||||
if(gang && gang.is_dominating)
|
||||
var/time_remaining = gang.domination_time_remaining()
|
||||
if(time_remaining > 0)
|
||||
if(dominator_excessive_walls(src))
|
||||
gang.domination_timer += 2
|
||||
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
|
||||
if(spam_prevention < DOM_BLOCKED_SPAM_CAP)
|
||||
spam_prevention++
|
||||
else
|
||||
gang.message_gangtools("Warning: There are too many walls around your gang's dominator, its signal is being blocked!")
|
||||
say("Error: Takeover signal is currently blocked! There are too many walls within 3 standard units of this device.")
|
||||
spam_prevention = 0
|
||||
return
|
||||
. = TRUE
|
||||
playsound(loc, 'sound/items/timer.ogg', 10, 0)
|
||||
if(!warned && (time_remaining < 180))
|
||||
|
||||
@@ -249,7 +249,7 @@ GLOBAL_LIST_INIT(gang_colors_pool, list("red","orange","yellow","green","blue","
|
||||
return gang_bosses
|
||||
|
||||
/proc/determine_domination_time(var/datum/gang/G)
|
||||
return max(180,900 - (round((G.territory.len/GLOB.start_state.num_territories)*100, 1) * 12))
|
||||
return max(180,480 - (round((G.territory.len/GLOB.start_state.num_territories)*100, 1) * 9))
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//Announces the end of the game with all relavent information stated//
|
||||
@@ -312,7 +312,9 @@ GLOBAL_LIST_INIT(gang_colors_pool, list("red","orange","yellow","green","blue","
|
||||
G.domination(0.5)
|
||||
priority_announce("Multiple station takeover attempts have made simultaneously. Conflicting takeover attempts appears to have restarted.","Network Alert")
|
||||
else
|
||||
var/datum/gang/G = winners[1]
|
||||
G.is_dominating = FALSE
|
||||
SSticker.mode.explosion_in_progress = 1
|
||||
SSticker.station_explosion_cinematic(1)
|
||||
SSticker.station_explosion_cinematic(1,"gang war", null)
|
||||
SSticker.mode.explosion_in_progress = 0
|
||||
SSticker.force_ending = pick(winners)
|
||||
SSticker.force_ending = TRUE
|
||||
|
||||
@@ -108,10 +108,16 @@
|
||||
/datum/gang_item/weapon/ammo/get_cost_display(mob/living/carbon/user, datum/gang/gang, obj/item/device/gangtool/gangtool)
|
||||
return " ↳" + ..() //this is pretty hacky but it looks nice on the popup
|
||||
|
||||
/datum/gang_item/weapon/shuriken
|
||||
name = "Shuriken"
|
||||
id = "shuriken"
|
||||
cost = 3
|
||||
item_path = /obj/item/weapon/throwing_star
|
||||
|
||||
/datum/gang_item/weapon/switchblade
|
||||
name = "Switchblade"
|
||||
id = "switchblade"
|
||||
cost = 10
|
||||
cost = 5
|
||||
item_path = /obj/item/weapon/switchblade
|
||||
|
||||
/datum/gang_item/weapon/pistol
|
||||
@@ -125,6 +131,18 @@
|
||||
id = "pistol_ammo"
|
||||
cost = 10
|
||||
item_path = /obj/item/ammo_box/magazine/m10mm
|
||||
|
||||
/datum/gang_item/weapon/sniper
|
||||
name = ".50cal Sniper Rifle"
|
||||
id = "sniper"
|
||||
cost = 40
|
||||
item_path = /obj/item/weapon/gun/ballistic/automatic/sniper_rifle
|
||||
|
||||
/datum/gang_item/weapon/ammo/sniper_ammo
|
||||
name = "Standard .50cal Sniper Rounds"
|
||||
id = "sniper_ammo"
|
||||
cost = 15
|
||||
item_path = /obj/item/ammo_box/magazine/sniper_rounds
|
||||
|
||||
/datum/gang_item/weapon/uzi
|
||||
name = "Uzi SMG"
|
||||
@@ -138,30 +156,8 @@
|
||||
id = "uzi_ammo"
|
||||
cost = 40
|
||||
item_path = /obj/item/ammo_box/magazine/uzim9mm
|
||||
|
||||
//SLEEPING CARP
|
||||
|
||||
/datum/gang_item/weapon/bostaff
|
||||
name = "Bo Staff"
|
||||
id = "bostaff"
|
||||
cost = 10
|
||||
item_path = /obj/item/weapon/twohanded/bostaff
|
||||
|
||||
/datum/gang_item/weapon/sleeping_carp_scroll
|
||||
name = "Sleeping Carp Scroll (one-use)"
|
||||
id = "sleeping_carp_scroll"
|
||||
cost = 30
|
||||
item_path = /obj/item/weapon/sleeping_carp_scroll
|
||||
spawn_msg = "<span class='notice'>Anyone who reads the <b>sleeping carp scroll</b> will learn secrets of the sleeping carp martial arts style.</span>"
|
||||
|
||||
/datum/gang_item/weapon/wrestlingbelt
|
||||
name = "Wrestling Belt"
|
||||
id = "wrastling_belt"
|
||||
cost = 20
|
||||
item_path = /obj/item/weapon/storage/belt/champion/wrestling
|
||||
spawn_msg = "<span class='notice'>Anyone wearing the <b>wresting belt</b> will know how to be effective with wrestling.</span>"
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////
|
||||
//EQUIPMENT
|
||||
///////////////////
|
||||
@@ -175,6 +171,12 @@
|
||||
id = "spraycan"
|
||||
cost = 5
|
||||
item_path = /obj/item/toy/crayon/spraycan/gang
|
||||
|
||||
/datum/gang_item/equipment/sharpener
|
||||
name = "Sharpener"
|
||||
id = "whetstone"
|
||||
cost = 3
|
||||
item_path = /obj/item/weapon/sharpener
|
||||
|
||||
/datum/gang_item/equipment/necklace
|
||||
name = "Gold Necklace"
|
||||
@@ -182,12 +184,31 @@
|
||||
cost = 1
|
||||
item_path = /obj/item/clothing/neck/necklace/dope
|
||||
|
||||
|
||||
/datum/gang_item/equipment/emp
|
||||
name = "EMP Grenade"
|
||||
id = "EMP"
|
||||
cost = 5
|
||||
item_path = /obj/item/weapon/grenade/empgrenade
|
||||
|
||||
/datum/gang_item/equipment/c4
|
||||
name = "C4 Explosive"
|
||||
id = "c4"
|
||||
cost = 10
|
||||
cost = 7
|
||||
item_path = /obj/item/weapon/grenade/plastic/c4
|
||||
|
||||
/datum/gang_item/equipment/frag
|
||||
name = "Fragmentation Grenade"
|
||||
id = "frag nade"
|
||||
cost = 10
|
||||
item_path = /obj/item/weapon/grenade/syndieminibomb/concussion/frag
|
||||
|
||||
/datum/gang_item/equipment/stimpack
|
||||
name = "Black Market Stimulants"
|
||||
id = "stimpack"
|
||||
cost = 15
|
||||
item_path = /obj/item/weapon/reagent_containers/syringe/stimulants
|
||||
|
||||
/datum/gang_item/equipment/implant_breaker
|
||||
name = "Implant Breaker"
|
||||
id = "implant_breaker"
|
||||
@@ -284,7 +305,11 @@
|
||||
if(obj.density)
|
||||
to_chat(user, "<span class='warning'>There's not enough room here!</span>")
|
||||
return FALSE
|
||||
|
||||
|
||||
if(dominator_excessive_walls(user))
|
||||
to_chat(user, "span class='warning'>The <b>dominator</b> will not function here! The <b>dominator</b> requires an open space within three standard units so that walls do not interfere with the signal.</span>")
|
||||
return FALSE
|
||||
|
||||
if(!(usrarea.type in gang.territory|gang.territory_new))
|
||||
to_chat(user, "<span class='warning'>The <b>dominator</b> can be spawned only on territory controlled by your gang!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
explanation_text = "Your brain is broken... you can only communicate in"
|
||||
|
||||
/datum/objective/abductee/speech/New()
|
||||
var/style = pick(list("pantomime", "rhyme", "haiku", "extended metaphors", "riddles", "extremely literal terms", "sound effects", "military jargon"))
|
||||
var/style = pick(list("pantomime", "rhyme", "haiku", "extended metaphors", "riddles", "extremely literal terms", "sound effects", "military jargon", "three word sentences"))
|
||||
explanation_text+= " [style]."
|
||||
|
||||
/datum/objective/abductee/capture
|
||||
@@ -146,3 +146,25 @@
|
||||
|
||||
/datum/objective/abductee/sixthsense
|
||||
explanation_text = "You died back there and went to heaven... or is it hell? No one here seems to know they're dead. Convince them, and maybe you can escape this limbo."
|
||||
|
||||
/datum/objective/abductee/toupefallacy
|
||||
explanation_text = "There are alien parasites masquerading as people's hair. Save people from this invasion."
|
||||
|
||||
/datum/objective/abductee/everyoneisthesame
|
||||
explanation_text = "There is only one other person in existence, he is just really good at pretending to be multiple people."
|
||||
|
||||
/datum/objective/abductee/forbiddennumber
|
||||
explanation_text = "Numbers, how do they work?" //Shouldn't ever see this.
|
||||
|
||||
/datum/objective/abductee/forbiddennumber/New()
|
||||
var/number = rand(2,10)
|
||||
explanation_text = "Ignore anything in a set of [number], they don't exist."
|
||||
|
||||
/datum/objective/abductee/foreignname
|
||||
explanation_text = "No matter how they say it, other people keep mispronouncing your name. Be sure to correct them whenever possible."
|
||||
|
||||
/datum/objective/abductee/pairoff
|
||||
explanation_text = "Being alone and in large groups are both frightening. Try to be alone with only one other person whenever possible."
|
||||
|
||||
/datum/objective/abductee/takeblame
|
||||
explanation_text = "Try to get formally executed for a crime you didn't commit, without a false confession."
|
||||
|
||||
@@ -116,12 +116,13 @@
|
||||
else
|
||||
dat += "<h3>Subject Status : </h3>"
|
||||
dat += "[occupant.name] => "
|
||||
switch(occupant.stat)
|
||||
if(0)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
switch(mob_occupant.stat)
|
||||
if(CONSCIOUS)
|
||||
dat += "<span class='good'>Conscious</span>"
|
||||
if(1)
|
||||
if(UNCONSCIOUS)
|
||||
dat += "<span class='average'>Unconscious</span>"
|
||||
else
|
||||
else // DEAD
|
||||
dat += "<span class='bad'>Deceased</span>"
|
||||
dat += "<br>"
|
||||
dat += "[flash]"
|
||||
@@ -146,9 +147,11 @@
|
||||
if(href_list["close"])
|
||||
close_machine()
|
||||
return
|
||||
if(occupant && occupant.stat != DEAD)
|
||||
if(href_list["experiment"])
|
||||
flash = Experiment(occupant,href_list["experiment"])
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant.stat != DEAD)
|
||||
if(href_list["experiment"])
|
||||
flash = Experiment(occupant,href_list["experiment"])
|
||||
updateUsrDialog()
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
icon = 'icons/mob/swarmer.dmi'
|
||||
desc = "A robot of unknown design, they seek only to consume materials and replicate themselves indefinitely."
|
||||
speak_emote = list("tones")
|
||||
initial_languages = list(/datum/language/swarmer)
|
||||
initial_language_holder = /datum/language_holder/swarmer
|
||||
bubble_icon = "swarmer"
|
||||
health = 40
|
||||
maxHealth = 40
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
var/icon_reveal = "revenant_revealed"
|
||||
var/icon_stun = "revenant_stun"
|
||||
var/icon_drain = "revenant_draining"
|
||||
var/stasis = 0
|
||||
var/stasis = FALSE
|
||||
incorporeal_move = 3
|
||||
invisibility = INVISIBILITY_REVENANT
|
||||
health = INFINITY //Revenants don't use health, they use essence instead
|
||||
@@ -205,6 +205,7 @@
|
||||
/mob/living/simple_animal/revenant/death()
|
||||
if(!revealed || stasis) //Revenants cannot die if they aren't revealed //or are already dead
|
||||
return 0
|
||||
stasis = TRUE
|
||||
to_chat(src, "<span class='revendanger'>NO! No... it's too late, you can feel your essence [pick("breaking apart", "drifting away")]...</span>")
|
||||
notransform = TRUE
|
||||
revealed = TRUE
|
||||
@@ -222,8 +223,7 @@
|
||||
R.client_to_revive = client //If the essence reforms, the old revenant is put back in the body
|
||||
R.revenant = src
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
revealed = 0
|
||||
stasis = 1
|
||||
revealed = FALSE
|
||||
ghostize(0)//Don't re-enter invisible corpse
|
||||
return
|
||||
|
||||
@@ -317,7 +317,7 @@
|
||||
incorporeal_move = 3
|
||||
invisibility = INVISIBILITY_REVENANT
|
||||
alpha=255
|
||||
stasis = 0
|
||||
stasis = FALSE
|
||||
|
||||
|
||||
//reforming
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
var/atom/movable/constant_target = null //The thing we're always focused on, if we're in the right mode
|
||||
var/target_x = 0 //The target coordinates if we're tracking those
|
||||
var/target_y = 0
|
||||
var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
|
||||
var/nuke_warning = FALSE // If we've set off a miniature alarm about an armed nuke
|
||||
var/mode = TRACK_NUKE_DISK //What are we looking for?
|
||||
|
||||
@@ -111,7 +112,7 @@
|
||||
var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here)
|
||||
if(closest_operative)
|
||||
target = closest_operative
|
||||
if(TRACK_ATOM)
|
||||
if(TRACK_ATOM)
|
||||
if(constant_target)
|
||||
target = constant_target
|
||||
if(TRACK_COORDINATES)
|
||||
@@ -129,7 +130,7 @@
|
||||
if(here.z != there.z)
|
||||
icon_state = "pinon[nuke_warning ? "alert" : ""]null"
|
||||
return
|
||||
if(here == there)
|
||||
if(get_dist_euclidian(here,there)<=minimum_range)
|
||||
icon_state = "pinon[nuke_warning ? "alert" : ""]direct"
|
||||
else
|
||||
setDir(get_dir(here, there))
|
||||
@@ -171,3 +172,6 @@
|
||||
desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives."
|
||||
mode = TRACK_OPERATIVES
|
||||
flags = NODROP
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -67,7 +67,14 @@
|
||||
/datum/objective/proc/update_explanation_text()
|
||||
//Default does nothing, override where needed
|
||||
|
||||
/datum/objective/proc/give_special_equipment()
|
||||
/datum/objective/proc/give_special_equipment(special_equipment)
|
||||
if(owner && owner.current)
|
||||
if(ishuman(owner.current))
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/list/slots = list ("backpack" = slot_in_backpack)
|
||||
for(var/eq_path in special_equipment)
|
||||
var/obj/O = new eq_path
|
||||
H.equip_in_one_of_slots(O, slots)
|
||||
|
||||
/datum/objective/assassinate
|
||||
var/target_role_type=0
|
||||
@@ -94,6 +101,14 @@
|
||||
else
|
||||
explanation_text = "Free Objective"
|
||||
|
||||
/datum/objective/assassinate/internal
|
||||
var/stolen = 0 //Have we already eliminated this target?
|
||||
|
||||
/datum/objective/assassinate/internal/update_explanation_text()
|
||||
..()
|
||||
if(target && !target.current)
|
||||
explanation_text = "Assassinate [target.name], who was obliterated"
|
||||
|
||||
|
||||
/datum/objective/mutiny
|
||||
var/target_role_type=0
|
||||
@@ -468,7 +483,7 @@ GLOBAL_LIST_EMPTY(possible_items)
|
||||
steal_target = targetinfo.targetitem
|
||||
explanation_text = "Steal [targetinfo.name]."
|
||||
dangerrating = targetinfo.difficulty
|
||||
give_special_equipment()
|
||||
give_special_equipment(targetinfo.special_equipment)
|
||||
return steal_target
|
||||
else
|
||||
explanation_text = "Free objective"
|
||||
@@ -511,15 +526,6 @@ GLOBAL_LIST_EMPTY(possible_items)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/objective/steal/give_special_equipment()
|
||||
if(owner && owner.current && targetinfo)
|
||||
if(ishuman(owner.current))
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/list/slots = list ("backpack" = slot_in_backpack)
|
||||
for(var/eq_path in targetinfo.special_equipment)
|
||||
var/obj/O = new eq_path
|
||||
H.equip_in_one_of_slots(O, slots)
|
||||
|
||||
|
||||
GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
/datum/objective/steal/special //ninjas are so special they get their own subtype good for them
|
||||
@@ -695,6 +701,9 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
explanation_text = "Destroy [target.name], the experimental AI."
|
||||
else
|
||||
explanation_text = "Free Objective"
|
||||
|
||||
/datum/objective/destroy/internal
|
||||
var/stolen = FALSE //Have we already eliminated this target?
|
||||
|
||||
/datum/objective/steal_five_of_type
|
||||
explanation_text = "Steal at least five items!"
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#define PINPOINTER_MINIMUM_RANGE 15
|
||||
#define PINPOINTER_EXTRA_RANDOM_RANGE 10
|
||||
#define PINPOINTER_PING_TIME 40
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs
|
||||
name = "Internal Affairs"
|
||||
config_tag = "internal_affairs"
|
||||
employer = "Internal Affairs"
|
||||
required_players = 25
|
||||
required_enemies = 5
|
||||
required_players = 25
|
||||
required_enemies = 5
|
||||
recommended_enemies = 8
|
||||
reroll_friendly = 0
|
||||
traitor_name = "Nanotrasen Internal Affairs Agent"
|
||||
@@ -18,15 +22,189 @@
|
||||
var/list/target_list = list()
|
||||
var/list/late_joining_list = list()
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/post_setup()
|
||||
var/i = 0
|
||||
for(var/datum/mind/traitor in traitors)
|
||||
i++
|
||||
if(i + 1 > traitors.len)
|
||||
i = 0
|
||||
target_list[traitor] = traitors[i + 1]
|
||||
target_list[traitor] = traitors[i+1]
|
||||
..()
|
||||
|
||||
|
||||
/datum/status_effect/agent_pinpointer
|
||||
id = "agent_pinpointer"
|
||||
duration = -1
|
||||
tick_interval = PINPOINTER_PING_TIME
|
||||
alert_type = /obj/screen/alert/status_effect/agent_pinpointer
|
||||
var/minimum_range = PINPOINTER_MINIMUM_RANGE
|
||||
var/mob/scan_target = null
|
||||
|
||||
/obj/screen/alert/status_effect/agent_pinpointer
|
||||
name = "Internal Affairs Integrated Pinpointer"
|
||||
desc = "Even stealthier than a normal implant."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "pinon"
|
||||
|
||||
/datum/status_effect/agent_pinpointer/proc/point_to_target() //If we found what we're looking for, show the distance and direction
|
||||
if(!scan_target)
|
||||
linked_alert.icon_state = "pinonnull"
|
||||
return
|
||||
var/turf/here = get_turf(owner)
|
||||
var/turf/there = get_turf(scan_target)
|
||||
if(here.z != there.z)
|
||||
linked_alert.icon_state = "pinonnull"
|
||||
return
|
||||
if(get_dist_euclidian(here,there)<=minimum_range + rand(0, PINPOINTER_EXTRA_RANDOM_RANGE))
|
||||
linked_alert.icon_state = "pinondirect"
|
||||
else
|
||||
linked_alert.setDir(get_dir(here, there))
|
||||
switch(get_dist(here, there))
|
||||
if(1 to 8)
|
||||
linked_alert.icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
linked_alert.icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
linked_alert.icon_state = "pinonfar"
|
||||
|
||||
|
||||
/datum/status_effect/agent_pinpointer/proc/scan_for_target()
|
||||
scan_target = null
|
||||
if(owner)
|
||||
if(owner.mind)
|
||||
if(owner.mind.objectives)
|
||||
for(var/datum/objective/objective_ in owner.mind.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
var/mob/current = objective.target.current
|
||||
if(current&¤t.stat!=DEAD)
|
||||
scan_target = current
|
||||
break
|
||||
|
||||
|
||||
/datum/status_effect/agent_pinpointer/tick()
|
||||
if(!owner)
|
||||
qdel(src)
|
||||
return
|
||||
scan_for_target()
|
||||
point_to_target()
|
||||
|
||||
/proc/give_pinpointer(datum/mind/owner)
|
||||
if(owner && owner.current)
|
||||
owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer)
|
||||
|
||||
|
||||
/datum/internal_agent_state
|
||||
var/traitored = FALSE
|
||||
var/datum/mind/owner = null
|
||||
var/list/datum/mind/targets_stolen = list()
|
||||
|
||||
/proc/is_internal_objective(datum/objective/O)
|
||||
return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal))
|
||||
|
||||
/proc/replace_escape_objective(datum/mind/owner)
|
||||
if(!owner||!owner.objectives)
|
||||
return
|
||||
for (var/objective_ in owner.objectives)
|
||||
if(!(istype(objective_, /datum/objective/escape)||istype(objective_,/datum/objective/survive)))
|
||||
continue
|
||||
owner.objectives -= objective_
|
||||
var/datum/objective/martyr/martyr_objective = new
|
||||
martyr_objective.owner = owner
|
||||
owner.objectives += martyr_objective
|
||||
|
||||
/proc/reinstate_escape_objective(datum/mind/owner)
|
||||
if(!owner||!owner.objectives)
|
||||
return
|
||||
for (var/objective_ in owner.objectives)
|
||||
if(!istype(objective_, /datum/objective/martyr))
|
||||
continue
|
||||
owner.objectives -= objective_
|
||||
if(issilicon(owner))
|
||||
var/datum/objective/survive/survive_objective = new
|
||||
survive_objective.owner = owner
|
||||
owner.objectives += survive_objective
|
||||
else
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
owner.objectives += escape_objective
|
||||
|
||||
/datum/internal_agent_state/proc/steal_targets(datum/mind/victim)
|
||||
if(!owner.current||owner.current.stat==DEAD) //Should already be guaranteed if this is only called from steal_targets_timer_func, but better to be safe code than sorry code
|
||||
return
|
||||
var/already_traitored = traitored
|
||||
to_chat(owner.current, "<span class='userdanger'> Target eliminated: [victim.name]</span>")
|
||||
for(var/objective_ in victim.objectives)
|
||||
if(istype(objective_, /datum/objective/assassinate/internal))
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(objective.target==owner)
|
||||
traitored = TRUE
|
||||
else if(targets_stolen.Find(objective.target) == 0)
|
||||
var/datum/objective/assassinate/internal/new_objective = new
|
||||
new_objective.owner = owner
|
||||
new_objective.target = objective.target
|
||||
new_objective.update_explanation_text()
|
||||
owner.objectives += new_objective
|
||||
targets_stolen += objective.target
|
||||
var/status_text = objective.check_completion() ? "neutralised" : "active"
|
||||
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
|
||||
else if(istype(objective_, /datum/objective/destroy/internal))
|
||||
var/datum/objective/destroy/internal/objective = objective_
|
||||
var/datum/objective/destroy/internal/new_objective = new
|
||||
if(objective.target==owner)
|
||||
traitored = TRUE
|
||||
else if(targets_stolen.Find(objective.target) == 0)
|
||||
new_objective.owner = owner
|
||||
new_objective.target = objective.target
|
||||
new_objective.update_explanation_text()
|
||||
owner.objectives += new_objective
|
||||
targets_stolen += objective.target
|
||||
var/status_text = objective.check_completion() ? "neutralised" : "active"
|
||||
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
|
||||
if(traitored&&!already_traitored)
|
||||
for(var/objective_ in owner.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(!objective.check_completion())
|
||||
traitored = FALSE
|
||||
return
|
||||
to_chat(owner.current,"<span class='userdanger'> All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.</span>")
|
||||
replace_escape_objective(owner)
|
||||
|
||||
|
||||
|
||||
/datum/internal_agent_state/proc/steal_targets_timer_func()
|
||||
if(owner&&owner.current&&owner.current.stat!=DEAD)
|
||||
for(var/objective_ in owner.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(!objective.target)
|
||||
continue
|
||||
if(objective.check_completion())
|
||||
if(objective.stolen)
|
||||
continue
|
||||
else
|
||||
steal_targets(objective.target)
|
||||
objective.stolen = TRUE
|
||||
else
|
||||
if(objective.stolen)
|
||||
var/fail_msg = "<span class='userdanger'>Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! </span>"
|
||||
if(traitored)
|
||||
fail_msg += "<span class='userdanger'> The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated.</span>"
|
||||
reinstate_escape_objective(owner)
|
||||
traitored = FALSE
|
||||
to_chat(owner.current, fail_msg)
|
||||
objective.stolen = FALSE
|
||||
add_steal_targets_timer(owner)
|
||||
|
||||
/datum/internal_agent_state/proc/add_steal_targets_timer()
|
||||
var/datum/callback/C = new(src, .steal_targets_timer_func)
|
||||
addtimer(C, 30)
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/forge_traitor_objectives(datum/mind/traitor)
|
||||
|
||||
if(target_list.len && target_list[traitor]) // Is a double agent
|
||||
@@ -34,13 +212,13 @@
|
||||
// Assassinate
|
||||
var/datum/mind/target_mind = target_list[traitor]
|
||||
if(issilicon(target_mind.current))
|
||||
var/datum/objective/destroy/destroy_objective = new
|
||||
var/datum/objective/destroy/internal/destroy_objective = new
|
||||
destroy_objective.owner = traitor
|
||||
destroy_objective.target = target_mind
|
||||
destroy_objective.update_explanation_text()
|
||||
traitor.objectives += destroy_objective
|
||||
else
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
var/datum/objective/assassinate/internal/kill_objective = new
|
||||
kill_objective.owner = traitor
|
||||
kill_objective.target = target_mind
|
||||
kill_objective.update_explanation_text()
|
||||
@@ -55,6 +233,11 @@
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = traitor
|
||||
traitor.objectives += escape_objective
|
||||
var/datum/internal_agent_state/state = new
|
||||
state.owner=traitor
|
||||
state.add_steal_targets_timer()
|
||||
if(!issilicon(traitor.current))
|
||||
give_pinpointer(traitor)
|
||||
|
||||
else
|
||||
..() // Give them standard objectives.
|
||||
@@ -106,14 +289,18 @@
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/greet_traitor(datum/mind/traitor)
|
||||
var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>You are the [traitor_name].</font></B>")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.</font></B>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>You are the [traitor_name].</span>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.</span>")
|
||||
to_chat(traitor.current, "<B><font size=5 color=red>While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.</font></B>")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.</font></B>")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</font></B>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.</span>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
|
||||
traitor.announce_objectives()
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/give_codewords(mob/living/traitor_mob)
|
||||
return
|
||||
return
|
||||
|
||||
#undef PINPOINTER_EXTRA_RANDOM_RANGE
|
||||
#undef PINPOINTER_MINIMUM_RANGE
|
||||
#undef PINPOINTER_PING_TIME
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
if(!ishuman(M))//If target is not a human.
|
||||
return ..()
|
||||
if(iscultist(M))
|
||||
to_chat(user, "<span class='cultlarge'>\"Come now, do not capture your fellow's soul.\"</span>")
|
||||
to_chat(user, "<span class='cultlarge'>\"Come now, do not capture your bretheren's soul.\"</span>")
|
||||
return
|
||||
add_logs(user, M, "captured [M.name]'s soul", src)
|
||||
|
||||
@@ -132,11 +132,11 @@
|
||||
|
||||
if("VICTIM")
|
||||
var/mob/living/carbon/human/T = target
|
||||
if(SSticker.mode.name == "cult" && T.mind == SSticker.mode:sacrifice_target)
|
||||
if(is_sacrifice_target(T.mind))
|
||||
if(iscultist(user))
|
||||
to_chat(user, "<span class='cult'><b>\"This soul is mine.</b></span> <span class='cultlarge'>SACRIFICE THEM!\"</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>The soulstone doesn't work for no apparent reason.</span>")
|
||||
to_chat(user, "<span class='danger'>The soulstone seems to reject this soul.</span>")
|
||||
return 0
|
||||
if(contents.len)
|
||||
to_chat(user, "<span class='userdanger'>Capture failed!</span>: The soulstone is full! Free an existing soul to make room.")
|
||||
@@ -188,7 +188,10 @@
|
||||
|
||||
else
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder/noncult, A, user, 0, T.loc)
|
||||
|
||||
for(var/datum/mind/B in SSticker.mode.cult)
|
||||
if(B == A.mind)
|
||||
SSticker.mode.cult -= A.mind
|
||||
SSticker.mode.update_cult_icons_removed(A.mind)
|
||||
qdel(T)
|
||||
user.drop_item()
|
||||
qdel(src)
|
||||
@@ -200,6 +203,9 @@
|
||||
var/mob/living/simple_animal/hostile/construct/newstruct = new ctype((loc_override) ? (loc_override) : (get_turf(target)))
|
||||
if(stoner)
|
||||
newstruct.faction |= "\ref[stoner]"
|
||||
newstruct.master = stoner
|
||||
var/datum/action/innate/seek_master/SM = new()
|
||||
SM.Grant(newstruct)
|
||||
newstruct.key = target.key
|
||||
if(newstruct.mind && ((stoner && iscultist(stoner)) || cultoverride) && SSticker && SSticker.mode)
|
||||
SSticker.mode.add_cultist(newstruct.mind, 0)
|
||||
@@ -207,6 +213,9 @@
|
||||
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>")
|
||||
newstruct.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
|
||||
var/obj/screen/alert/bloodsense/BS = newstruct.alerts["bloodsense"]
|
||||
BS.Cviewer = newstruct
|
||||
newstruct.cancel_camera()
|
||||
|
||||
|
||||
@@ -244,7 +253,7 @@
|
||||
break
|
||||
|
||||
if(!chosen_ghost) //Failing that, we grab a ghost
|
||||
var/list/consenting_candidates = pollCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, poll_time = 50)
|
||||
var/list/consenting_candidates = pollGhostCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, poll_time = 50)
|
||||
if(consenting_candidates.len)
|
||||
chosen_ghost = pick(consenting_candidates)
|
||||
if(!T)
|
||||
|
||||
@@ -778,6 +778,9 @@
|
||||
icon_state ="booksmoke"
|
||||
desc = "This book is overflowing with the dank arts."
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/smoke/lesser //Chaplain smoke book
|
||||
spell = /obj/effect/proc_holder/spell/targeted/smoke/lesser
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/smoke/recoil(mob/user)
|
||||
..()
|
||||
to_chat(user,"<span class='caution'>Your stomach rumbles...</span>")
|
||||
@@ -786,6 +789,7 @@
|
||||
if(user.nutrition <= 0)
|
||||
user.nutrition = 0
|
||||
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/blind
|
||||
spell = /obj/effect/proc_holder/spell/targeted/trigger/blind
|
||||
spellname = "blind"
|
||||
|
||||
@@ -79,7 +79,8 @@
|
||||
/obj/machinery/sleeper/close_machine(mob/user)
|
||||
if((isnull(user) || istype(user)) && state_open && !panel_open)
|
||||
..(user)
|
||||
if(occupant && occupant.stat != DEAD)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant && mob_occupant.stat != DEAD)
|
||||
to_chat(occupant, "<span class='notice'><b>You feel cool air surround you. You go numb as your senses turn inward.</b></span>")
|
||||
|
||||
/obj/machinery/sleeper/emp_act(severity)
|
||||
@@ -128,27 +129,30 @@
|
||||
data["chems"] += list(list("name" = R.name, "id" = R.id, "allowed" = chem_allowed(chem)))
|
||||
|
||||
data["occupant"] = list()
|
||||
if(occupant)
|
||||
data["occupant"]["name"] = occupant.name
|
||||
data["occupant"]["stat"] = occupant.stat
|
||||
data["occupant"]["health"] = occupant.health
|
||||
data["occupant"]["maxHealth"] = occupant.maxHealth
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant)
|
||||
data["occupant"]["name"] = mob_occupant.name
|
||||
data["occupant"]["stat"] = mob_occupant.stat
|
||||
data["occupant"]["health"] = mob_occupant.health
|
||||
data["occupant"]["maxHealth"] = mob_occupant.maxHealth
|
||||
data["occupant"]["minHealth"] = HEALTH_THRESHOLD_DEAD
|
||||
data["occupant"]["bruteLoss"] = occupant.getBruteLoss()
|
||||
data["occupant"]["oxyLoss"] = occupant.getOxyLoss()
|
||||
data["occupant"]["toxLoss"] = occupant.getToxLoss()
|
||||
data["occupant"]["fireLoss"] = occupant.getFireLoss()
|
||||
data["occupant"]["cloneLoss"] = occupant.getCloneLoss()
|
||||
data["occupant"]["brainLoss"] = occupant.getBrainLoss()
|
||||
data["occupant"]["bruteLoss"] = mob_occupant.getBruteLoss()
|
||||
data["occupant"]["oxyLoss"] = mob_occupant.getOxyLoss()
|
||||
data["occupant"]["toxLoss"] = mob_occupant.getToxLoss()
|
||||
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
|
||||
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
|
||||
data["occupant"]["brainLoss"] = mob_occupant.getBrainLoss()
|
||||
data["occupant"]["reagents"] = list()
|
||||
if(occupant.reagents.reagent_list.len)
|
||||
for(var/datum/reagent/R in occupant.reagents.reagent_list)
|
||||
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
|
||||
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
|
||||
return data
|
||||
|
||||
/obj/machinery/sleeper/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/mob_occupant = occupant
|
||||
|
||||
switch(action)
|
||||
if("door")
|
||||
if(state_open)
|
||||
@@ -158,9 +162,9 @@
|
||||
. = TRUE
|
||||
if("inject")
|
||||
var/chem = params["chem"]
|
||||
if(!is_operational() || !occupant)
|
||||
if(!is_operational() || !mob_occupant)
|
||||
return
|
||||
if(occupant.health < min_health && chem != "epinephrine")
|
||||
if(mob_occupant.health < min_health && chem != "epinephrine")
|
||||
return
|
||||
if(inject_chem(chem))
|
||||
. = TRUE
|
||||
@@ -177,10 +181,11 @@
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/proc/chem_allowed(chem)
|
||||
if(!occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(!mob_occupant)
|
||||
return
|
||||
var/amount = occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency
|
||||
var/occ_health = occupant.health > min_health || chem == "epinephrine"
|
||||
var/amount = mob_occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency
|
||||
var/occ_health = mob_occupant.health > min_health || chem == "epinephrine"
|
||||
return amount && occ_health
|
||||
|
||||
/obj/machinery/sleeper/proc/reset_chem_buttons()
|
||||
|
||||
@@ -121,10 +121,12 @@
|
||||
|
||||
/obj/machinery/clonepod/examine(mob/user)
|
||||
..()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mess)
|
||||
to_chat(user, "It's filled with blood and viscera. You swear you can see it moving...")
|
||||
if (is_operational() && (!isnull(occupant)) && (occupant.stat != DEAD))
|
||||
to_chat(user, "Current clone cycle is [round(get_completion())]% complete.")
|
||||
if(is_operational() && mob_occupant)
|
||||
if(mob_occupant.stat != DEAD)
|
||||
to_chat(user, "Current clone cycle is [round(get_completion())]% complete.")
|
||||
|
||||
/obj/machinery/clonepod/return_air()
|
||||
// We want to simulate the clone not being in contact with
|
||||
@@ -136,7 +138,10 @@
|
||||
return GM
|
||||
|
||||
/obj/machinery/clonepod/proc/get_completion()
|
||||
. = (100 * ((occupant.health + 100) / (heal_level + 100)))
|
||||
. = FALSE
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant)
|
||||
. = (100 * ((mob_occupant.health + 100) / (heal_level + 100)))
|
||||
|
||||
/obj/machinery/clonepod/attack_ai(mob/user)
|
||||
return examine(user)
|
||||
@@ -172,11 +177,11 @@
|
||||
|
||||
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
|
||||
|
||||
if(clonemind.changeling)
|
||||
var/obj/item/organ/brain/B = H.getorganslot("brain")
|
||||
B.vital = FALSE
|
||||
B.decoy_override = TRUE
|
||||
|
||||
if(clonemind.changeling)
|
||||
var/obj/item/organ/brain/B = H.getorganslot("brain")
|
||||
B.vital = FALSE
|
||||
B.decoy_override = TRUE
|
||||
|
||||
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
|
||||
|
||||
if(efficiency > 2)
|
||||
@@ -204,13 +209,13 @@
|
||||
|
||||
clonemind.transfer_to(H)
|
||||
|
||||
if(grab_ghost_when == CLONER_FRESH_CLONE)
|
||||
H.grab_ghost()
|
||||
to_chat(H, "<span class='notice'><b>Consciousness slowly creeps over you as your body regenerates.</b><br><i>So this is what cloning feels like?</i></span>")
|
||||
if(grab_ghost_when == CLONER_FRESH_CLONE)
|
||||
H.grab_ghost()
|
||||
to_chat(H, "<span class='notice'><b>Consciousness slowly creeps over you as your body regenerates.</b><br><i>So this is what cloning feels like?</i></span>")
|
||||
|
||||
if(grab_ghost_when == CLONER_MATURE_CLONE)
|
||||
H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
|
||||
to_chat(H.get_ghost(TRUE), "<span class='notice'>Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.</span>")
|
||||
H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
|
||||
to_chat(H.get_ghost(TRUE), "<span class='notice'>Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.</span>")
|
||||
|
||||
if(H)
|
||||
H.faction |= factions
|
||||
@@ -223,25 +228,26 @@
|
||||
|
||||
//Grow clones to maturity then kick them out. FREELOADERS
|
||||
/obj/machinery/clonepod/process()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
|
||||
if(!is_operational()) //Autoeject if power is lost
|
||||
if (occupant)
|
||||
if(mob_occupant)
|
||||
go_out()
|
||||
connected_message("Clone Ejected: Loss of power.")
|
||||
|
||||
else if((occupant) && (occupant.loc == src))
|
||||
if((occupant.stat == DEAD) || (occupant.suiciding) || occupant.hellbound) //Autoeject corpses and suiciding dudes.
|
||||
else if(mob_occupant && (mob_occupant.loc == src))
|
||||
if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes.
|
||||
connected_message("Clone Rejected: Deceased.")
|
||||
SPEAK("The cloning of [occupant.real_name] has been \
|
||||
SPEAK("The cloning of [mob_occupant.real_name] has been \
|
||||
aborted due to unrecoverable tissue failure.")
|
||||
go_out()
|
||||
|
||||
else if(occupant.cloneloss > (100 - heal_level))
|
||||
occupant.Paralyse(4)
|
||||
else if(mob_occupant.cloneloss > (100 - heal_level))
|
||||
mob_occupant.Paralyse(4)
|
||||
|
||||
//Slowly get that clone healed and finished.
|
||||
occupant.adjustCloneLoss(-((speed_coeff/2) * config.damage_multiplier))
|
||||
var/progress = CLONE_INITIAL_DAMAGE - occupant.getCloneLoss()
|
||||
mob_occupant.adjustCloneLoss(-((speed_coeff/2) * config.damage_multiplier))
|
||||
var/progress = CLONE_INITIAL_DAMAGE - mob_occupant.getCloneLoss()
|
||||
// To avoid the default cloner making incomplete clones
|
||||
progress += (100 - MINIMUM_HEAL_LEVEL)
|
||||
var/milestone = CLONE_INITIAL_DAMAGE / flesh_number
|
||||
@@ -252,24 +258,24 @@
|
||||
var/obj/item/I = pick_n_take(unattached_flesh)
|
||||
if(isorgan(I))
|
||||
var/obj/item/organ/O = I
|
||||
O.Insert(occupant)
|
||||
O.Insert(mob_occupant)
|
||||
else if(isbodypart(I))
|
||||
var/obj/item/bodypart/BP = I
|
||||
BP.attach_limb(occupant)
|
||||
BP.attach_limb(mob_occupant)
|
||||
|
||||
//Premature clones may have brain damage.
|
||||
occupant.adjustBrainLoss(-((speed_coeff/2) * config.damage_multiplier))
|
||||
mob_occupant.adjustBrainLoss(-((speed_coeff/2) * config.damage_multiplier))
|
||||
|
||||
check_brine()
|
||||
|
||||
use_power(7500) //This might need tweaking.
|
||||
|
||||
else if((occupant.cloneloss <= (100 - heal_level)))
|
||||
else if((mob_occupant.cloneloss <= (100 - heal_level)))
|
||||
connected_message("Cloning Process Complete.")
|
||||
SPEAK("The cloning cycle of [occupant.real_name] is complete.")
|
||||
SPEAK("The cloning cycle of [mob_occupant.real_name] is complete.")
|
||||
go_out()
|
||||
|
||||
else if ((!occupant) || (occupant.loc != src))
|
||||
else if (!mob_occupant || mob_occupant.loc != src)
|
||||
occupant = null
|
||||
if (!mess && !panel_open)
|
||||
icon_state = "pod_0"
|
||||
@@ -305,16 +311,19 @@
|
||||
to_chat(user, "<font color = #666633>-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-</font color>")
|
||||
return
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(W.GetID())
|
||||
if(!check_access(W))
|
||||
to_chat(user, "<span class='danger'>Access Denied.</span>")
|
||||
return
|
||||
if(!(occupant || mess))
|
||||
if(!(mob_occupant || mess))
|
||||
to_chat(user, "<span class='danger'>Error: Pod has no occupant.</span>")
|
||||
return
|
||||
else
|
||||
connected_message("Authorized Ejection")
|
||||
SPEAK("An authorized ejection of [clonemind.name] has occurred.")
|
||||
|
||||
SPEAK("An authorized ejection of [clonemind.name] has occurred.")
|
||||
|
||||
to_chat(user, "<span class='notice'>You force an emergency ejection. </span>")
|
||||
go_out()
|
||||
else
|
||||
@@ -339,54 +348,63 @@
|
||||
|
||||
/obj/machinery/clonepod/proc/go_out()
|
||||
countdown.stop()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
|
||||
if(mess) //Clean that mess and dump those gibs!
|
||||
mess = FALSE
|
||||
new /obj/effect/gibspawner/generic(loc)
|
||||
new /obj/effect/gibspawner/generic(loc)
|
||||
audible_message("<span class='italics'>You hear a splat.</span>")
|
||||
icon_state = "pod_0"
|
||||
return
|
||||
|
||||
if(!occupant)
|
||||
if(!mob_occupant)
|
||||
return
|
||||
|
||||
if(grab_ghost_when == CLONER_MATURE_CLONE)
|
||||
occupant.grab_ghost()
|
||||
to_chat(occupant, "<span class='notice'><b>There is a bright flash!</b><br><i>You feel like a new being.</i></span>")
|
||||
occupant.flash_act()
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(grab_ghost_when == CLONER_MATURE_CLONE)
|
||||
mob_occupant.grab_ghost()
|
||||
to_chat(occupant, "<span class='notice'><b>There is a bright flash!</b><br><i>You feel like a new being.</i></span>")
|
||||
mob_occupant.flash_act()
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
occupant.forceMove(T)
|
||||
icon_state = "pod_0"
|
||||
occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
|
||||
mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
|
||||
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/clonepod/proc/malfunction()
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant)
|
||||
connected_message("Critical Error!")
|
||||
SPEAK("Critical error! Please contact a Thinktronic Systems \
|
||||
technician, as your warranty may be affected.")
|
||||
mess = TRUE
|
||||
for(var/obj/item/O in unattached_flesh)
|
||||
qdel(O)
|
||||
|
||||
for(var/obj/item/O in unattached_flesh)
|
||||
qdel(O)
|
||||
|
||||
icon_state = "pod_g"
|
||||
if(occupant.mind != clonemind)
|
||||
clonemind.transfer_to(occupant)
|
||||
occupant.grab_ghost() // We really just want to make you suffer.
|
||||
flash_color(occupant, flash_color="#960000", flash_time=100)
|
||||
to_chat(occupant, "<span class='warning'><b>Agony blazes across your consciousness as your body is torn apart.</b><br><i>Is this what dying is like? Yes it is.</i></span>")
|
||||
if(mob_occupant.mind != clonemind)
|
||||
clonemind.transfer_to(mob_occupant)
|
||||
mob_occupant.grab_ghost() // We really just want to make you suffer.
|
||||
flash_color(mob_occupant, flash_color="#960000", flash_time=100)
|
||||
to_chat(mob_occupant, "<span class='warning'><b>Agony blazes across your consciousness as your body is torn apart.</b><br><i>Is this what dying is like? Yes it is.</i></span>")
|
||||
playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 50, 0)
|
||||
occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
|
||||
QDEL_IN(occupant, 40)
|
||||
mob_occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
|
||||
QDEL_IN(mob_occupant, 40)
|
||||
|
||||
/obj/machinery/clonepod/relaymove(mob/user)
|
||||
if(user.stat == CONSCIOUS)
|
||||
go_out()
|
||||
|
||||
/obj/machinery/clonepod/emp_act(severity)
|
||||
if((occupant || mess) && prob(100/(severity*efficiency)))
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant && prob(100/(severity*efficiency)))
|
||||
connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
|
||||
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [clonemind.name] prematurely." ,0))
|
||||
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [mob_occupant.real_name] prematurely." ,0))
|
||||
|
||||
go_out()
|
||||
..()
|
||||
|
||||
|
||||
@@ -186,21 +186,23 @@
|
||||
// Scanner
|
||||
if (!isnull(src.scanner))
|
||||
|
||||
var/mob/living/scanner_occupant = scanner.occupant
|
||||
|
||||
dat += "<h3>Scanner Functions</h3>"
|
||||
|
||||
dat += "<div class='statusDisplay'>"
|
||||
if (!src.scanner.occupant)
|
||||
if(!scanner_occupant)
|
||||
dat += "Scanner Unoccupied"
|
||||
else if(loading)
|
||||
dat += "[src.scanner.occupant] => Scanning..."
|
||||
dat += "[scanner_occupant] => Scanning..."
|
||||
else
|
||||
if (src.scanner.occupant.ckey != scantemp_ckey)
|
||||
if(scanner_occupant.ckey != scantemp_ckey)
|
||||
scantemp = "Ready to Scan"
|
||||
scantemp_ckey = src.scanner.occupant.ckey
|
||||
dat += "[src.scanner.occupant] => [scantemp]"
|
||||
scantemp_ckey = scanner_occupant.ckey
|
||||
dat += "[scanner_occupant] => [scantemp]"
|
||||
dat += "</div>"
|
||||
|
||||
if (src.scanner.occupant)
|
||||
if(scanner_occupant)
|
||||
dat += "<a href='byond://?src=\ref[src];scan=1'>Start Scan</a>"
|
||||
dat += "<br><a href='byond://?src=\ref[src];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
|
||||
else
|
||||
|
||||
@@ -56,7 +56,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
jobs["Bartender"] = 61
|
||||
jobs["Cook"] = 62
|
||||
jobs["Botanist"] = 63
|
||||
jobs["Librarian"] = 64
|
||||
jobs["Curator"] = 64
|
||||
jobs["Chaplain"] = 65
|
||||
jobs["Clown"] = 66
|
||||
jobs["Mime"] = 67
|
||||
|
||||
@@ -113,7 +113,8 @@
|
||||
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
|
||||
R.ResetSecurityCodes()
|
||||
else
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) detonated [key_name(R, R.client)](<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[R.x];Y=[R.y];Z=[R.z]'>JMP</a>)!</span>")
|
||||
var/turf/T = get_turf(R)
|
||||
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] detonated [key_name(R, R.client)][ADMIN_JMP(T)]!</span>")
|
||||
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(R)]!</span>")
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
|
||||
@@ -127,7 +128,7 @@
|
||||
if(can_control(usr, R))
|
||||
var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm" && can_control(usr, R) && !..())
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) [R.canmove ? "locked down" : "released"] [key_name(R, R.client)](<A HREF='?_src_=holder;adminplayerobservefollow=\ref[R]'>FLW</A>)!</span>")
|
||||
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [R.canmove ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
|
||||
log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [key_name(R)]!")
|
||||
R.SetLockdown(!R.lockcharge)
|
||||
to_chat(R, "[!R.lockcharge ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
|
||||
|
||||
@@ -105,13 +105,14 @@
|
||||
..()
|
||||
|
||||
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant)
|
||||
if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \
|
||||
|| locate(/obj/machinery/computer/cloning, get_step(src, SOUTH)) \
|
||||
|| locate(/obj/machinery/computer/cloning, get_step(src, EAST)) \
|
||||
|| locate(/obj/machinery/computer/cloning, get_step(src, WEST)))
|
||||
if(!occupant.suiciding && !(occupant.disabilities & NOCLONE) && !occupant.hellbound)
|
||||
occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src)
|
||||
if(!mob_occupant.suiciding && !(mob_occupant.disabilities & NOCLONE) && !mob_occupant.hellbound)
|
||||
mob_occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src)
|
||||
|
||||
var/obj/machinery/computer/scan_consolenew/console
|
||||
for(dir in list(NORTH,EAST,SOUTH,WEST))
|
||||
@@ -157,4 +158,4 @@
|
||||
if(..(user,1,0)) //don't set the machine, since there's no dialog
|
||||
return
|
||||
|
||||
toggle_open(user)
|
||||
toggle_open(user)
|
||||
|
||||
@@ -136,13 +136,14 @@ The console is located at computer/gulag_teleporter.dm
|
||||
/obj/machinery/gulag_teleporter/proc/strip_occupant()
|
||||
if(linked_reclaimer)
|
||||
linked_reclaimer.stored_items[occupant] = list()
|
||||
for(var/obj/item/W in occupant)
|
||||
if(!is_type_in_typecache(W, required_items) && occupant.temporarilyRemoveItemFromInventory(W))
|
||||
var/mob/living/mob_occupant = occupant
|
||||
for(var/obj/item/W in mob_occupant)
|
||||
if(!is_type_in_typecache(W, required_items) && mob_occupant.temporarilyRemoveItemFromInventory(W))
|
||||
if(istype(W, /obj/item/weapon/restraints/handcuffs))
|
||||
W.forceMove(get_turf(src))
|
||||
continue
|
||||
if(linked_reclaimer)
|
||||
linked_reclaimer.stored_items[occupant] += W
|
||||
linked_reclaimer.stored_items[mob_occupant] += W
|
||||
linked_reclaimer.contents += W
|
||||
W.forceMove(linked_reclaimer)
|
||||
else
|
||||
|
||||
@@ -294,7 +294,9 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
|
||||
Hologram.Impersonation = user
|
||||
|
||||
Hologram.languages = user.languages
|
||||
|
||||
Hologram.language_holder = user.get_language_holder()
|
||||
|
||||
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.
|
||||
Hologram.anchored = 1//So space wind cannot drag it.
|
||||
@@ -319,7 +321,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad == src && speaker != HC.hologram)
|
||||
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans)
|
||||
|
||||
if(outgoing_call && speaker == outgoing_call.user)
|
||||
outgoing_call.hologram.say(raw_message)
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
diff a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm (rejected hunks)
|
||||
@@ -152,7 +152,7 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad == src)
|
||||
dat += "<a href='?src=\ref[src];disconnectcall=\ref[HC]'>Disconnect call from [HC.user].</a><br>"
|
||||
-
|
||||
+
|
||||
|
||||
var/datum/browser/popup = new(user, "holopad", name, 300, 130)
|
||||
popup.set_content(dat)
|
||||
@@ -192,7 +192,7 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
if(A)
|
||||
LAZYADD(callnames[A], I)
|
||||
callnames -= get_area(src)
|
||||
-
|
||||
+
|
||||
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames
|
||||
if(QDELETED(usr) || !result || outgoing_call)
|
||||
return
|
||||
@@ -201,7 +201,7 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
temp = "Dialing...<br>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
new /datum/holocall(usr, src, callnames[result])
|
||||
-
|
||||
+
|
||||
else if(href_list["connectcall"])
|
||||
var/datum/holocall/call_to_connect = locate(href_list["connectcall"])
|
||||
if(!QDELETED(call_to_connect))
|
||||
@@ -315,12 +315,12 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
for(var/mob/living/silicon/ai/master in masters)
|
||||
if(masters[master] && speaker != master)
|
||||
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
-
|
||||
+
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad == src && speaker != HC.hologram)
|
||||
- HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans)
|
||||
-
|
||||
+ HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
+
|
||||
if(outgoing_call && speaker == outgoing_call.user)
|
||||
outgoing_call.hologram.say(raw_message)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
Overview:
|
||||
Used to create objects that need a per step proc call. Default definition of 'New()'
|
||||
Used to create objects that need a per step proc call. Default definition of 'Initialize()'
|
||||
stores a reference to src machine in global 'machines list'. Default definition
|
||||
of 'Del' removes reference to src machine in global 'machines list'.
|
||||
of 'Destroy' removes reference to src machine in global 'machines list'.
|
||||
|
||||
Class Variables:
|
||||
use_power (num)
|
||||
@@ -44,7 +44,7 @@ Class Variables:
|
||||
EMPED:16 -- temporary broken by EMP pulse
|
||||
|
||||
Class Procs:
|
||||
New() 'game/machinery/machine.dm'
|
||||
Initialize() 'game/machinery/machine.dm'
|
||||
|
||||
Destroy() 'game/machinery/machine.dm'
|
||||
|
||||
@@ -118,14 +118,15 @@ Class Procs:
|
||||
var/panel_open = 0
|
||||
var/state_open = 0
|
||||
var/critical_machine = FALSE //If this machine is critical to station operation and should have the area be excempted from power failures.
|
||||
var/mob/living/occupant = null
|
||||
var/list/occupant_typecache = list(/mob/living) // turned into typecache in Initialize
|
||||
var/atom/movable/occupant = null
|
||||
var/unsecuring_tool = /obj/item/weapon/wrench
|
||||
var/interact_open = 0 // Can the machine be interacted with when in maint/when the panel is open.
|
||||
var/interact_offline = 0 // Can the machine be interacted with while de-powered.
|
||||
var/speed_process = 0 // Process as fast as possible?
|
||||
|
||||
/obj/machinery/Initialize()
|
||||
if (!armor)
|
||||
if(!armor)
|
||||
armor = list(melee = 25, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 70)
|
||||
. = ..()
|
||||
GLOB.machines += src
|
||||
@@ -135,6 +136,8 @@ Class Procs:
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
power_change()
|
||||
|
||||
occupant_typecache = typecacheof(occupant_typecache)
|
||||
|
||||
/obj/machinery/Destroy()
|
||||
GLOB.machines.Remove(src)
|
||||
if(!speed_process)
|
||||
@@ -176,16 +179,24 @@ Class Procs:
|
||||
L.update_canmove()
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/proc/close_machine(mob/living/target = null)
|
||||
/obj/machinery/proc/close_machine(atom/movable/target = null)
|
||||
state_open = 0
|
||||
density = 1
|
||||
if(!target)
|
||||
for(var/mob/living/carbon/C in loc)
|
||||
if(C.buckled || C.has_buckled_mobs())
|
||||
for(var/am in loc)
|
||||
if(!is_type_in_typecache(am, occupant_typecache))
|
||||
continue
|
||||
else
|
||||
target = C
|
||||
if(target && !target.buckled && !target.has_buckled_mobs())
|
||||
var/atom/movable/AM = am
|
||||
if(AM.has_buckled_mobs())
|
||||
continue
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = am
|
||||
if(L.buckled)
|
||||
continue
|
||||
target = am
|
||||
|
||||
var/mob/living/mobtarget = target
|
||||
if(target && !target.has_buckled_mobs() && (!isliving(target) || !mobtarget.buckled))
|
||||
occupant = target
|
||||
target.forceMove(src)
|
||||
updateUsrDialog()
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#define TURRET_STUN 0
|
||||
#define TURRET_LETHAL 1
|
||||
|
||||
#define POPUP_ANIM_TIME 5
|
||||
#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad
|
||||
|
||||
/obj/machinery/porta_turret
|
||||
name = "turret"
|
||||
icon = 'icons/obj/turrets.dmi'
|
||||
@@ -422,7 +425,7 @@
|
||||
raising = 1
|
||||
if(cover)
|
||||
flick("popup", cover)
|
||||
sleep(10)
|
||||
sleep(POPUP_ANIM_TIME)
|
||||
raising = 0
|
||||
if(cover)
|
||||
cover.icon_state = "openTurretCover"
|
||||
@@ -438,7 +441,7 @@
|
||||
raising = 1
|
||||
if(cover)
|
||||
flick("popdown", cover)
|
||||
sleep(10)
|
||||
sleep(POPDOWN_ANIM_TIME)
|
||||
raising = 0
|
||||
if(cover)
|
||||
cover.icon_state = "turretCover"
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
var/atom/movable/AM = i
|
||||
var/obj/item/bodypart/head/as_head = AM
|
||||
var/obj/item/device/mmi/as_mmi = AM
|
||||
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain)
|
||||
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /mob/living/brain)
|
||||
if(isliving(AM) || brain_holder)
|
||||
if(emagged)
|
||||
if(!brain_holder)
|
||||
|
||||
@@ -211,13 +211,13 @@
|
||||
uv = TRUE
|
||||
locked = TRUE
|
||||
update_icon()
|
||||
if(occupant)
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(uv_super)
|
||||
occupant.adjustFireLoss(rand(20, 36))
|
||||
mob_occupant.adjustFireLoss(rand(20, 36))
|
||||
else
|
||||
occupant.adjustFireLoss(rand(10, 16))
|
||||
if(iscarbon(occupant))
|
||||
occupant.emote("scream")
|
||||
mob_occupant.adjustFireLoss(rand(10, 16))
|
||||
mob_occupant.emote("scream")
|
||||
addtimer(CALLBACK(src, .proc/cook), 50)
|
||||
else
|
||||
uv_cycles = initial(uv_cycles)
|
||||
@@ -368,14 +368,15 @@
|
||||
else if(!helmet && !mask && !suit && !storage && !occupant)
|
||||
return
|
||||
else
|
||||
if(occupant)
|
||||
to_chat(occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!occupant.stat ? "alive" : "away"]!</span>")
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
|
||||
cook()
|
||||
. = TRUE
|
||||
if("dispense")
|
||||
if(!state_open)
|
||||
return
|
||||
|
||||
|
||||
var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
|
||||
var/item_name = params["item"]
|
||||
if(item_name in valid_items)
|
||||
|
||||
@@ -737,8 +737,8 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
|
||||
icon_state = "sustenance"
|
||||
products = list(/obj/item/weapon/reagent_containers/food/snacks/tofu = 24,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/ice = 12,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/candy_corn = 6,
|
||||
/obj/item/weapon/reagent_containers/glass/beaker/waterbottle = 10)
|
||||
/obj/item/weapon/reagent_containers/food/snacks/candy_corn = 6,
|
||||
/obj/item/weapon/reagent_containers/glass/beaker/waterbottle = 10)
|
||||
contraband = list(/obj/item/weapon/kitchen/knife = 6,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/coffee = 12,
|
||||
/obj/item/weapon/tank/internals/emergency_oxygen = 6,
|
||||
@@ -755,7 +755,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
|
||||
products = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola = 10,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb = 10,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist = 10,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up = 10,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/pwr_game = 10,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime = 10,/obj/item/weapon/reagent_containers/glass/beaker/waterbottle = 10)
|
||||
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime = 10,/obj/item/weapon/reagent_containers/glass/beaker/waterbottle = 10)
|
||||
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko = 6,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/shamblers = 6)
|
||||
premium = list(/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/filled/nuka_cola = 1,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/air = 1)
|
||||
refill_canister = /obj/item/weapon/vending_refill/cola
|
||||
@@ -947,7 +947,8 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
|
||||
/obj/item/seeds/tea = 3,/obj/item/seeds/tobacco = 3,/obj/item/seeds/tomato = 3,
|
||||
/obj/item/seeds/tower = 3,/obj/item/seeds/watermelon = 3,/obj/item/seeds/wheat = 3,/obj/item/seeds/whitebeet = 3)
|
||||
contraband = list(/obj/item/seeds/amanita = 2,/obj/item/seeds/glowshroom = 2,/obj/item/seeds/liberty = 2,/obj/item/seeds/nettle = 2,
|
||||
/obj/item/seeds/plump = 2,/obj/item/seeds/reishi = 2,/obj/item/seeds/cannabis = 3, /obj/item/seeds/random = 2)
|
||||
/obj/item/seeds/plump = 2,/obj/item/seeds/reishi = 2,/obj/item/seeds/cannabis = 3,/obj/item/seeds/starthistle = 2,
|
||||
/obj/item/seeds/random = 2)
|
||||
premium = list(/obj/item/weapon/reagent_containers/spray/waterflower = 1)
|
||||
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
@@ -1128,7 +1129,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
|
||||
/obj/item/clothing/head/beanie=1, /obj/item/clothing/head/beanie/black=1, /obj/item/clothing/head/beanie/red=1, /obj/item/clothing/head/beanie/green=1, /obj/item/clothing/head/beanie/darkblue=1,
|
||||
/obj/item/clothing/head/beanie/purple=1, /obj/item/clothing/head/beanie/yellow=1, /obj/item/clothing/head/beanie/orange=1, /obj/item/clothing/head/beanie/cyan=1, /obj/item/clothing/head/beanie/christmas=1,
|
||||
/obj/item/clothing/head/beanie/striped=1, /obj/item/clothing/head/beanie/stripedred=1, /obj/item/clothing/head/beanie/stripedblue=1, /obj/item/clothing/head/beanie/stripedgreen=1,
|
||||
/obj/item/clothing/suit/jacket/letterman_red=1)
|
||||
/obj/item/clothing/suit/jacket/letterman_red=1, /obj/item/clothing/head/hunter=2)
|
||||
contraband = list(/obj/item/clothing/under/syndicate/tacticool=1,/obj/item/clothing/mask/balaclava=1,/obj/item/clothing/head/ushanka=1,/obj/item/clothing/under/soviet=1,/obj/item/weapon/storage/belt/fannypack/black=2,/obj/item/clothing/suit/jacket/letterman_syndie=1,/obj/item/clothing/under/jabroni=1, /obj/item/clothing/suit/vapeshirt=1, /obj/item/clothing/under/geisha=1)
|
||||
premium = list(/obj/item/clothing/under/suit_jacket/checkered=1,/obj/item/clothing/head/mailman=1,/obj/item/clothing/under/rank/mailman=1,/obj/item/clothing/suit/jacket/leather=1,/obj/item/clothing/suit/jacket/leather/overcoat=1,/obj/item/clothing/under/pants/mustangjeans=1,/obj/item/clothing/neck/necklace/dope=3,/obj/item/clothing/suit/jacket/letterman_nanotrasen=1)
|
||||
refill_canister = /obj/item/weapon/vending_refill/clothing
|
||||
|
||||
@@ -337,8 +337,8 @@
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/proj_init(var/obj/item/weapon/grenade/flashbang/F)
|
||||
var/turf/T = get_turf(src)
|
||||
message_admins("[key_name(chassis.occupant, chassis.occupant.client)](<A HREF='?_src_=holder;adminmoreinfo=\ref[chassis.occupant]'>?</A>) fired a [src] in ([T.x],[T.y],[T.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</a>)",0,1)
|
||||
log_game("[key_name(chassis.occupant)] fired a [src] ([T.x],[T.y],[T.z])")
|
||||
message_admins("[ADMIN_LOOKUPFLW(chassis.occupant)] fired a [src] in [ADMIN_COORDJMP(T)]",0,1)
|
||||
log_game("[key_name(chassis.occupant)] fired a [src] [COORD(T)]")
|
||||
addtimer(CALLBACK(F, /obj/item/weapon/grenade/flashbang.proc/prime), det_time)
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/clusterbang //Because I am a heartless bastard -Sieve //Heartless? for making the poor man's honkblast? - Kaze
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
name = "footprints"
|
||||
icon = 'icons/effects/footprints.dmi'
|
||||
icon_state = "nothingwhatsoever"
|
||||
desc = "where might they lead?"
|
||||
desc = "WHOSE FOOTPRINTS ARE THESE?"
|
||||
random_icon_states = null
|
||||
var/entered_dirs = 0
|
||||
var/exited_dirs = 0
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
/obj/effect/particle_effect/smoke/proc/spread_smoke()
|
||||
var/turf/t_loc = get_turf(src)
|
||||
if(!t_loc)
|
||||
return
|
||||
return
|
||||
var/list/newsmokes = list()
|
||||
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
|
||||
var/obj/effect/particle_effect/smoke/foundsmoke = locate() in T //Don't spread smoke where there's already smoke!
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
name = "Head of Personnel"
|
||||
|
||||
/obj/effect/landmark/start/librarian
|
||||
name = "Librarian"
|
||||
name = "Curator"
|
||||
|
||||
/obj/effect/landmark/start/lawyer
|
||||
name = "Lawyer"
|
||||
|
||||
@@ -230,7 +230,15 @@
|
||||
name = "blood sparks"
|
||||
icon_state = "bloodsparkles"
|
||||
|
||||
/obj/effect/overlay/temp/dir_setting/cult/phase
|
||||
/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"
|
||||
@@ -323,11 +331,30 @@
|
||||
/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
|
||||
|
||||
@@ -336,7 +363,6 @@
|
||||
damage *= multiplier
|
||||
duration = max(round(damage * 0.2), 1)
|
||||
. = ..()
|
||||
set_light(1.5, 2, LIGHT_COLOR_ORANGE)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit/true/Initialize(mapload, caster, multiplier)
|
||||
. = ..()
|
||||
@@ -593,6 +619,18 @@
|
||||
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"
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
return
|
||||
if (istype(M, /atom/movable))
|
||||
if(ismegafauna(M))
|
||||
message_admins("[M] (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</A>) has teleported through [src].")
|
||||
message_admins("[M] [ADMIN_FLW(M)] has teleported through [src].")
|
||||
do_teleport(M, target, precision) ///You will appear adjacent to the beacon
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range = 0 ,silent = 0, smoke = 1)
|
||||
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range, silent = 0, smoke = 1)
|
||||
set waitfor = 0
|
||||
src = null //so we don't abort once src is deleted
|
||||
epicenter = get_turf(epicenter)
|
||||
if(!epicenter)
|
||||
return
|
||||
|
||||
if(isnull(flame_range))
|
||||
flame_range = light_impact_range
|
||||
if(isnull(flash_range))
|
||||
flash_range = devastation_range
|
||||
|
||||
// Archive the uncapped explosion for the doppler array
|
||||
var/orig_dev_range = devastation_range
|
||||
var/orig_heavy_range = heavy_impact_range
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
desc = "An official document entrusting the governance of the station \
|
||||
and surrounding space to the Captain. "
|
||||
var/used = FALSE
|
||||
var/name_type = "station"
|
||||
|
||||
var/unlimited_uses = FALSE
|
||||
var/ignores_timeout = FALSE
|
||||
@@ -33,10 +34,10 @@
|
||||
|
||||
/obj/item/station_charter/attack_self(mob/living/user)
|
||||
if(used)
|
||||
to_chat(user, "This charter has already been used to name the station.")
|
||||
to_chat(user, "The [name_type] has already been named.")
|
||||
return
|
||||
if(!ignores_timeout && (world.time-SSticker.round_start_time > STATION_RENAME_TIME_LIMIT)) //5 minutes
|
||||
to_chat(user, "The crew has already settled into the shift. It probably wouldn't be good to rename the station right now.")
|
||||
to_chat(user, "The crew has already settled into the shift. It probably wouldn't be good to rename the [name_type] right now.")
|
||||
return
|
||||
if(response_timer_id)
|
||||
to_chat(user, "You're still waiting for approval from your employers about your proposed name change, it'd be best to wait for now.")
|
||||
@@ -60,7 +61,7 @@
|
||||
to_chat(user, "Your name has been sent to your employers for approval.")
|
||||
// Autoapproves after a certain time
|
||||
response_timer_id = addtimer(CALLBACK(src, .proc/rename_station, new_name, user.name, user.real_name, key_name(user)), approval_time, TIMER_STOPPABLE)
|
||||
to_chat(GLOB.admins, "<span class='adminnotice'><b><font color=orange>CUSTOM STATION RENAME:</font></b>[key_name_admin(user)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) proposes to rename the station to [new_name] (will autoapprove in [approval_time / 10] seconds). [ADMIN_SMITE(user)] (<A HREF='?_src_=holder;reject_custom_name=\ref[src]'>REJECT</A>) (<a href='?_src_=holder;CentcommReply=\ref[user]'>RPLY</a>)</span>")
|
||||
to_chat(GLOB.admins, "<span class='adminnotice'><b><font color=orange>CUSTOM STATION RENAME:</font></b>[ADMIN_LOOKUPFLW(user)] proposes to rename the [name_type] to [new_name] (will autoapprove in [approval_time / 10] seconds). [ADMIN_SMITE(user)] (<A HREF='?_src_=holder;reject_custom_name=\ref[src]'>REJECT</A>) [ADMIN_CENTCOM_REPLY(user)]</span>")
|
||||
|
||||
/obj/item/station_charter/proc/reject_proposed(user)
|
||||
if(!user)
|
||||
@@ -94,4 +95,27 @@
|
||||
unlimited_uses = TRUE
|
||||
ignores_timeout = TRUE
|
||||
|
||||
|
||||
/obj/item/weapon/station_charter/flag
|
||||
name = "nanotrasen banner"
|
||||
icon = 'icons/obj/items.dmi'
|
||||
var/name_type = "planet"
|
||||
icon_state = "banner"
|
||||
item_state = "banner"
|
||||
desc = "A cunning device used to claim ownership of planets."
|
||||
w_class = 5
|
||||
force = 15
|
||||
|
||||
/obj/item/station_charter/flag/rename_station(designation, uname, ureal_name, ukey)
|
||||
set_station_name(designation)
|
||||
minor_announce("[ureal_name] has designated the planet as [station_name()]", "Captain's Banner", 0)
|
||||
log_game("[ukey] has renamed the planet as [station_name()].")
|
||||
name = "banner of [station_name()]"
|
||||
desc = "The banner bears the official coat of arms of Nanotrasen, signifying that [station_name()] has been claimed by Captain [uname] in the name of the company."
|
||||
SSblackbox.set_details("station_renames","[station_name()]")
|
||||
if(!unlimited_uses)
|
||||
used = TRUE
|
||||
|
||||
|
||||
|
||||
#undef STATION_RENAME_TIME_LIMIT
|
||||
|
||||
@@ -161,11 +161,11 @@
|
||||
icon_state = "pda-roboticist"
|
||||
default_cartridge = /obj/item/weapon/cartridge/roboticist
|
||||
|
||||
/obj/item/device/pda/librarian
|
||||
name = "librarian PDA"
|
||||
/obj/item/device/pda/curator
|
||||
name = "curator PDA"
|
||||
icon_state = "pda-library"
|
||||
icon_alert = "pda-r-library"
|
||||
default_cartridge = /obj/item/weapon/cartridge/librarian
|
||||
default_cartridge = /obj/item/weapon/cartridge/curator
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a WGW-11 series e-reader."
|
||||
note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!"
|
||||
silent = 1 //Quiet in the library!
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
access_mime = 1
|
||||
var/mime_charges = 5
|
||||
|
||||
/obj/item/weapon/cartridge/librarian
|
||||
/obj/item/weapon/cartridge/curator
|
||||
name = "\improper Lib-Tweet cartridge"
|
||||
icon_state = "cart-s"
|
||||
access_newscaster = 1
|
||||
|
||||
@@ -7,10 +7,14 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
slot_flags = SLOT_BELT
|
||||
origin_tech = "materials=2;magnets=1;bluespace=2"
|
||||
unique_rename = TRUE
|
||||
var/gpstag = "COM0"
|
||||
var/emped = FALSE
|
||||
var/turf/locked_location
|
||||
var/tracking = TRUE
|
||||
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
|
||||
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
|
||||
|
||||
|
||||
/obj/item/device/gps/Initialize()
|
||||
..()
|
||||
@@ -27,6 +31,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
cut_overlay("working")
|
||||
add_overlay("emp")
|
||||
addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early
|
||||
SStgui.close_uis(src) //Close the UI control if it is open.
|
||||
|
||||
/obj/item/device/gps/proc/reboot()
|
||||
emped = FALSE
|
||||
@@ -34,6 +39,9 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
add_overlay("working")
|
||||
|
||||
/obj/item/device/gps/AltClick(mob/user)
|
||||
toggletracking(user)
|
||||
|
||||
/obj/item/device/gps/proc/toggletracking(mob/user)
|
||||
if(!user.canUseTopic(src, be_close=TRUE))
|
||||
return //user not valid to use gps
|
||||
if(emped)
|
||||
@@ -48,45 +56,89 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
to_chat(user, "[src] is now tracking, and visible to other GPS devices.")
|
||||
tracking = TRUE
|
||||
|
||||
/obj/item/device/gps/attack_self(mob/user)
|
||||
if(!tracking)
|
||||
to_chat(user, "[src] is turned off. Use alt+click to toggle it back on.")
|
||||
return
|
||||
|
||||
var/obj/item/device/gps/t = ""
|
||||
var/gps_window_height = 110 + GLOB.GPS_list.len * 20 // Variable window height, depending on how many GPS units there are to show
|
||||
/obj/item/device/gps/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
|
||||
if(emped)
|
||||
t += "ERROR"
|
||||
else
|
||||
t += "<BR><A href='?src=\ref[src];tag=1'>Set Tag</A> "
|
||||
t += "<BR>Tag: [gpstag]"
|
||||
if(locked_location && locked_location.loc)
|
||||
t += "<BR>Bluespace coordinates saved: [locked_location.loc]"
|
||||
gps_window_height += 20
|
||||
|
||||
for(var/obj/item/device/gps/G in GLOB.GPS_list)
|
||||
var/turf/pos = get_turf(G)
|
||||
var/area/gps_area = get_area(G)
|
||||
var/tracked_gpstag = G.gpstag
|
||||
if(G.emped == 1)
|
||||
t += "<BR>[tracked_gpstag]: ERROR"
|
||||
else if(G.tracking)
|
||||
t += "<BR>[tracked_gpstag]: [format_text(gps_area.name)] ([pos.x], [pos.y], [pos.z])"
|
||||
else
|
||||
continue
|
||||
var/datum/browser/popup = new(user, "GPS", name, 360, min(gps_window_height, 800))
|
||||
popup.set_content(t)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
to_chat(user, "[src] fizzles weakly.")
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
var/gps_window_height = 300 + GLOB.GPS_list.len * 20 // Variable window height, depending on how many GPS units there are to show
|
||||
ui = new(user, src, ui_key, "gps", "Global Positioning System", 600, gps_window_height, master_ui, state) //width, height
|
||||
ui.open()
|
||||
|
||||
ui.set_autoupdate(state = updating)
|
||||
|
||||
|
||||
/obj/item/device/gps/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["power"] = tracking
|
||||
data["tag"] = gpstag
|
||||
data["updating"] = updating
|
||||
data["globalmode"] = global_mode
|
||||
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
|
||||
return data
|
||||
|
||||
var/turf/curr = get_turf(src)
|
||||
data["current"] = "[get_area_name(curr)] ([curr.x], [curr.y], [curr.z])"
|
||||
|
||||
var/list/signals = list()
|
||||
data["signals"] = list()
|
||||
|
||||
for(var/gps in GLOB.GPS_list)
|
||||
var/obj/item/device/gps/G = gps
|
||||
if(G.emped || !G.tracking || G == src)
|
||||
continue
|
||||
var/turf/pos = get_turf(G)
|
||||
if(!global_mode && pos.z != curr.z)
|
||||
continue
|
||||
var/area/gps_area = get_area_name(G)
|
||||
var/list/signal = list()
|
||||
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
|
||||
signal["area"] = format_text(gps_area)
|
||||
signal["coord"] = "[pos.x], [pos.y], [pos.z]"
|
||||
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
|
||||
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
|
||||
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
|
||||
var/direction = uppertext(dir2text(get_dir(curr, pos))) //Direction text (East, etc). Not as precise, but still helpful.
|
||||
if(!direction)
|
||||
direction = "CENTER"
|
||||
signal["degrees"] = "N/A"
|
||||
signal["direction"] = direction
|
||||
|
||||
signals += list(signal) //Add this signal to the list of signals
|
||||
data["signals"] = signals
|
||||
return data
|
||||
|
||||
|
||||
|
||||
/obj/item/device/gps/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("rename")
|
||||
var/a = input("Please enter desired tag.", name, gpstag) as text
|
||||
a = uppertext(copytext(sanitize(a), 1, 5))
|
||||
gpstag = a
|
||||
name = "global positioning system ([gpstag])"
|
||||
. = TRUE
|
||||
if("power")
|
||||
toggletracking(usr)
|
||||
. = TRUE
|
||||
if("updating")
|
||||
updating = !updating
|
||||
. = TRUE
|
||||
if("globalmode")
|
||||
global_mode = !global_mode
|
||||
. = TRUE
|
||||
|
||||
/obj/item/device/gps/Topic(href, href_list)
|
||||
..()
|
||||
if(href_list["tag"] )
|
||||
var/a = input("Please enter desired tag.", name, gpstag) as text
|
||||
a = uppertext(copytext(sanitize(a), 1, 5))
|
||||
a = copytext(sanitize(a), 1, 20)
|
||||
if(in_range(src, usr))
|
||||
gpstag = a
|
||||
name = "global positioning system ([gpstag])"
|
||||
attack_self(usr)
|
||||
|
||||
/obj/item/device/gps/science
|
||||
@@ -157,4 +209,4 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
clear()
|
||||
tagged = null
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
. = ..()
|
||||
. = ..()
|
||||
@@ -95,8 +95,8 @@
|
||||
"[user] activates \the [src]!", \
|
||||
"<span class='notice'>You activate \the [src].</span>",
|
||||
"<span class='italics'>You hear a click.</span>")
|
||||
message_admins("Power sink activated by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
log_game("Power sink activated by [key_name(user)] at ([x],[y],[z])")
|
||||
message_admins("Power sink activated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(src)]")
|
||||
log_game("Power sink activated by [key_name(user)] at [COORD(src)]")
|
||||
set_mode(OPERATING)
|
||||
|
||||
if(OPERATING)
|
||||
|
||||
@@ -178,21 +178,21 @@
|
||||
|
||||
var/log_attacher = ""
|
||||
if(attacher)
|
||||
log_attacher = "(<A HREF='?_src_=holder;adminmoreinfo=\ref[attacher]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[attacher]'>FLW</A>)"
|
||||
log_attacher = "[ADMIN_QUE(attacher)] [ADMIN_FLW(attacher)]"
|
||||
|
||||
var/mob/mob = get_mob_by_key(src.fingerprintslast)
|
||||
var/last_touch_info = ""
|
||||
if(mob)
|
||||
last_touch_info = "(<A HREF='?_src_=holder;adminmoreinfo=\ref[mob]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[mob]'>FLW</A>)"
|
||||
last_touch_info = "[ADMIN_QUE(mob)] [ADMIN_FLW(mob)]"
|
||||
|
||||
var/log_str3 = " Last touched by: [key_name_admin(mob)]"
|
||||
|
||||
var/bomb_message = "[log_str1] <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name]</a> [log_str2][log_attacher] [log_str3][last_touch_info]"
|
||||
var/bomb_message = "[log_str1] [A.name][ADMIN_JMP(bombturf)] [log_str2][log_attacher] [log_str3][last_touch_info]"
|
||||
|
||||
GLOB.bombers += bomb_message
|
||||
|
||||
message_admins(bomb_message, 0, 1)
|
||||
log_game("[log_str1] [A.name]([A.x],[A.y],[A.z]) [log_str2] [log_str3]")
|
||||
log_game("[log_str1] [A.name][COORD(bombturf)] [log_str2] [log_str3]")
|
||||
merge_gases()
|
||||
spawn(20) // In case one tank bursts
|
||||
for (var/i=0,i<5,i++)
|
||||
|
||||
@@ -29,6 +29,7 @@ Mineral Sheets
|
||||
GLOBAL_LIST_INIT(sandstone_recipes, list ( \
|
||||
new/datum/stack_recipe("pile of dirt", /obj/machinery/hydroponics/soil, 3, time = 10, one_per_turf = 1, on_floor = 1), \
|
||||
new/datum/stack_recipe("sandstone door", /obj/structure/mineral_door/sandstone, 10, one_per_turf = 1, on_floor = 1), \
|
||||
new/datum/stack_recipe("aesthetic volcanic floor tile", /obj/item/stack/tile/basalt, 2, 2, 4, 20), \
|
||||
new/datum/stack_recipe("Assistant Statue", /obj/structure/statue/sandstone/assistant, 5, one_per_turf = 1, on_floor = 1), \
|
||||
new/datum/stack_recipe("Breakdown into sand", /obj/item/weapon/ore/glass, 1, one_per_turf = 0, on_floor = 1), \
|
||||
/* new/datum/stack_recipe("sandstone wall", ???), \
|
||||
@@ -154,8 +155,9 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \
|
||||
|
||||
/obj/item/stack/sheet/mineral/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
|
||||
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
|
||||
message_admins("Plasma sheets ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Plasma sheets ignited by [key_name(user)] in ([x],[y],[z])")
|
||||
var/turf/T = get_turf(src)
|
||||
message_admins("Plasma sheets ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
|
||||
log_game("Plasma sheets ignited by [key_name(user)] in [COORD(T)]")
|
||||
fire_act()
|
||||
else
|
||||
return ..()
|
||||
@@ -334,12 +336,20 @@ GLOBAL_LIST_INIT(snow_recipes, list ( \
|
||||
/*
|
||||
* Adamantine
|
||||
*/
|
||||
GLOBAL_LIST_INIT(adamantine_recipes, list(
|
||||
new /datum/stack_recipe("artificial golem shell", /obj/item/golem_shell/artificial, req_amount=1, res_amount=1),
|
||||
))
|
||||
|
||||
/obj/item/stack/sheet/mineral/adamantine
|
||||
name = "adamantine"
|
||||
icon_state = "sheet-adamantine"
|
||||
singular_name = "adamantine sheet"
|
||||
origin_tech = "materials=4"
|
||||
|
||||
/obj/item/stack/sheet/mineral/adamantine/Initialize(mapload, new_amount, merge = TRUE)
|
||||
recipes = GLOB.adamantine_recipes
|
||||
..()
|
||||
|
||||
/*
|
||||
* Mythril
|
||||
*/
|
||||
|
||||
@@ -286,13 +286,16 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list ( \
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/stack/sheet/runed_metal/fifty
|
||||
amount = 50
|
||||
|
||||
/obj/item/stack/sheet/runed_metal/Initialize(mapload, new_amount, merge = TRUE)
|
||||
recipes = GLOB.runed_metal_recipes
|
||||
return ..()
|
||||
|
||||
/obj/item/stack/sheet/runed_metal/fifty
|
||||
amount = 50
|
||||
|
||||
/obj/item/stack/sheet/runed_metal/five
|
||||
amount = 5
|
||||
|
||||
/*
|
||||
* Brass
|
||||
*/
|
||||
@@ -328,7 +331,7 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \
|
||||
|
||||
/obj/item/stack/tile/brass/Initialize(mapload, new_amount, merge = TRUE)
|
||||
recipes = GLOB.brass_recipes
|
||||
..()
|
||||
. = ..()
|
||||
pixel_x = 0
|
||||
pixel_y = 0
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
var/turf_type = null
|
||||
var/mineralType = null
|
||||
|
||||
/obj/item/stack/tile/New(loc, amount)
|
||||
..()
|
||||
/obj/item/stack/tile/Initialize(mapload, amount)
|
||||
. = ..()
|
||||
pixel_x = rand(-3, 3)
|
||||
pixel_y = rand(-3, 3) //randomize a little
|
||||
|
||||
@@ -88,6 +88,14 @@
|
||||
turf_type = /turf/open/floor/wood
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
//Basalt
|
||||
/obj/item/stack/tile/basalt
|
||||
name = "basalt tile"
|
||||
singular_name = "basalt floor tile"
|
||||
desc = "Artificially made ashy soil themed on a hostile enviroment."
|
||||
icon_state = "tile_basalt"
|
||||
origin_tech = "materials=1"
|
||||
turf_type = /turf/open/floor/grass/fakebasalt
|
||||
|
||||
//Carpets
|
||||
/obj/item/stack/tile/carpet
|
||||
|
||||
@@ -1218,9 +1218,9 @@
|
||||
icon_state = "lawyer"
|
||||
toysay = "My client is a dirty traitor!"
|
||||
|
||||
/obj/item/toy/figure/librarian
|
||||
name = "Librarian action figure"
|
||||
icon_state = "librarian"
|
||||
/obj/item/toy/figure/curator
|
||||
name = "Curator action figure"
|
||||
icon_state = "curator"
|
||||
toysay = "One day while..."
|
||||
|
||||
/obj/item/toy/figure/md
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
/obj/item/weapon/pie_cannon
|
||||
name = "pie cannon"
|
||||
desc = "Load cream pie for optimal results"
|
||||
force = 10
|
||||
icon_state = "piecannon"
|
||||
item_state = "powerfist"
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/pie/loaded = null
|
||||
|
||||
/obj/item/weapon/pie_cannon/attackby(obj/item/I, mob/living/L)
|
||||
if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/pie))
|
||||
if(!loaded)
|
||||
L.transferItemToLoc(I, src)
|
||||
loaded = I
|
||||
to_chat(L, "<span class='notice'>You load the [I] into the [src]!</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/pie_cannon/afterattack(atom/target, mob/living/user, flag, params)
|
||||
if(!loaded)
|
||||
return ..()
|
||||
var/obj/item/projectile/pie/launched = new /obj/item/projectile/pie(src)
|
||||
launched.P = loaded
|
||||
loaded.forceMove(launched)
|
||||
launched.appearance = loaded.appearance
|
||||
loaded = null
|
||||
launched.preparePixelProjectile(target, get_turf(target), user, params, 0)
|
||||
launched.forceMove(get_turf(src))
|
||||
launched.fire()
|
||||
user.visible_message("<span class='danger'>[user] fires the [src] at [target]!</span>")
|
||||
|
||||
/obj/item/projectile/pie
|
||||
name = "pie"
|
||||
desc = "Think fast!"
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/pie/P = null
|
||||
|
||||
/obj/item/projectile/pie/on_hit(atom/A)
|
||||
. = ..()
|
||||
if(P)
|
||||
A.visible_message("<span class='danger'>[P] smashes into [A] at high velocity!</span>")
|
||||
P.forceMove(get_turf(A))
|
||||
P.throw_impact(A)
|
||||
if(ismovableatom(A))
|
||||
var/atom/movable/AM = A
|
||||
if(!AM.anchored)
|
||||
AM.throw_at(get_edge_target_turf(get_dir(src, AM), 3, 2))
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
to_chat(user, "<span class='notice'>You start planting the bomb...</span>")
|
||||
|
||||
if(do_after(user, 50, target = AM))
|
||||
if(do_after(user, 50, target = AM))
|
||||
if(!user.temporarilyRemoveItemFromInventory(src))
|
||||
return
|
||||
src.target = AM
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
if(lit)
|
||||
START_PROCESSING(SSobj, src)
|
||||
if(!warned_admins)
|
||||
message_admins("[key_name_admin(usr)]<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) has lit a flamethrower.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] has lit a flamethrower.")
|
||||
warned_admins = 1
|
||||
if(href_list["amount"])
|
||||
throw_amount = throw_amount + text2num(href_list["amount"])
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
else if(clown_check(user))
|
||||
var/turf/bombturf = get_turf(src)
|
||||
var/area/A = get_area(bombturf)
|
||||
message_admins("[key_name_admin(usr)]<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) has primed a [name] for detonation at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>.")
|
||||
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]).")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] has primed a [name] for detonation at [A.name][ADMIN_JMP(bombturf)].")
|
||||
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(bombturf)].")
|
||||
to_chat(user, "<span class='warning'>You prime the [name]! [det_time / 10] second\s!</span>")
|
||||
playsound(user.loc, 'sound/weapons/armbomb.ogg', 60, 1)
|
||||
active = 1
|
||||
@@ -177,12 +177,12 @@
|
||||
var/mob/last = get_mob_by_ckey(nadeassembly.fingerprintslast)
|
||||
var/turf/T = get_turf(src)
|
||||
var/area/A = get_area(T)
|
||||
message_admins("grenade primed by an assembly, attached by [key_name_admin(M)]<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>(?)</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</A>) and last touched by [key_name_admin(last)]<A HREF='?_src_=holder;adminmoreinfo=\ref[last]'>(?)</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[last]'>FLW</A>) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[A.name] (JMP)</a>.")
|
||||
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
|
||||
message_admins("grenade primed by an assembly, attached by [ADMIN_LOOKUPFLW(M)] and last touched by [ADMIN_LOOKUPFLW(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] [ADMIN_JMP(T)]</a>.")
|
||||
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] [COORD(T)]")
|
||||
|
||||
var/turf/DT = get_turf(src)
|
||||
var/area/DA = get_area(DT)
|
||||
log_game("A grenade detonated at [DA.name] ([DT.x], [DT.y], [DT.z])")
|
||||
log_game("A grenade detonated at [DA.name] [COORD(DT)]")
|
||||
|
||||
update_mob()
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
to_chat(user, "<span class='notice'>You start planting the [src]. The timer is set to [det_time]...</span>")
|
||||
|
||||
if(do_after(user, 50, target = AM))
|
||||
if(do_after(user, 30, target = AM))
|
||||
if(!user.temporarilyRemoveItemFromInventory(src))
|
||||
return
|
||||
src.target = AM
|
||||
@@ -119,8 +119,8 @@
|
||||
qdel(src) //How?
|
||||
|
||||
/obj/item/weapon/grenade/plastic/suicide_act(mob/user)
|
||||
message_admins("[key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) suicided with [src] at ([user.x],[user.y],[user.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",0,1)
|
||||
message_admins("[key_name(user)] suicided with [src] at ([user.x],[user.y],[user.z])")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] suicided with [src] at [ADMIN_COORDJMP(user)]",0,1)
|
||||
log_game("[key_name(user)] suicided with [src] at [COORD(user)]")
|
||||
user.visible_message("<span class='suicide'>[user] activates the [src] and holds it above [user.p_their()] head! It looks like [user.p_theyre()] going out with a bang!</span>")
|
||||
var/message_say = "FOR NO RAISIN!"
|
||||
if(user.mind)
|
||||
@@ -165,4 +165,4 @@
|
||||
icon_state = "plasticx40"
|
||||
item_state = "plasticx4"
|
||||
directional = TRUE
|
||||
boom_sizes = list(0, 2, 5)
|
||||
boom_sizes = list(0, 2, 5)
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
..()
|
||||
|
||||
/obj/item/weapon/his_grace/CtrlClick(mob/user) //you can't pull his grace
|
||||
attack_hand(user)
|
||||
return
|
||||
|
||||
/obj/item/weapon/his_grace/examine(mob/user)
|
||||
..()
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
|
||||
possessed = TRUE
|
||||
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the spirit of [user.real_name]'s blade?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_POSSESSED_BLADE)
|
||||
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the spirit of [user.real_name]'s blade?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_POSSESSED_BLADE)
|
||||
var/mob/dead/observer/theghost = null
|
||||
|
||||
if(LAZYLEN(candidates))
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
active = TRUE
|
||||
var/turf/boomturf = get_turf(imp_in)
|
||||
var/area/A = get_area(boomturf)
|
||||
message_admins("[key_name_admin(imp_in)]<A HREF='?_src_=holder;adminmoreinfo=\ref[imp_in]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[imp_in]'>FLW</A>) has activated their [name] at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[imp_in.x];Y=[imp_in.y];Z=[imp_in.z]'>[A.name] (JMP)</a>.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(imp_in)] has activated their [name] at [A.name] [ADMIN_JMP(boomturf)].")
|
||||
//If the delay is short, just blow up already jeez
|
||||
if(delay <= 7)
|
||||
explosion(src,heavy,medium,weak,weak, flame_range = weak)
|
||||
|
||||
@@ -41,9 +41,10 @@
|
||||
data["open"] = state_open
|
||||
|
||||
data["occupant"] = list()
|
||||
if(occupant)
|
||||
data["occupant"]["name"] = occupant.name
|
||||
data["occupant"]["stat"] = occupant.stat
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
data["occupant"]["name"] = mob_occupant.name
|
||||
data["occupant"]["stat"] = mob_occupant.stat
|
||||
|
||||
data["special_name"] = special ? special_name : null
|
||||
data["ready_implants"] = ready_implants
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
var/brightness_on = 3
|
||||
|
||||
/obj/item/weapon/melee/energy/Initialize()
|
||||
..()
|
||||
. = ..()
|
||||
if(LAZYLEN(possible_colors))
|
||||
item_color = pick(possible_colors)
|
||||
switch(item_color)//Only run this check if the color was picked randomly, so that colors can be manually set for non-random colored energy weapons.
|
||||
@@ -183,8 +183,8 @@
|
||||
light_color = "#40ceff"
|
||||
possible_colors = null
|
||||
|
||||
/obj/item/weapon/melee/energy/sword/cyborg/saw/New()
|
||||
..()
|
||||
/obj/item/weapon/melee/energy/sword/cyborg/saw/Initialize()
|
||||
. = ..()
|
||||
icon_state = "esaw_0"
|
||||
item_color = null
|
||||
|
||||
@@ -207,19 +207,9 @@
|
||||
|
||||
|
||||
/obj/item/weapon/melee/energy/sword/saber/attackby(obj/item/weapon/W, mob/living/user, params)
|
||||
if(istype(W, /obj/item/weapon/melee/energy/sword/saber))
|
||||
to_chat(user, "<span class='notice'>You attach the ends of the two energy swords, making a single double-bladed weapon! You're cool.</span>")
|
||||
var/obj/item/weapon/melee/energy/sword/saber/other_esword = W
|
||||
var/obj/item/weapon/twohanded/dualsaber/newSaber = new(user.loc)
|
||||
if(hacked || other_esword.hacked)
|
||||
newSaber.hacked = TRUE
|
||||
newSaber.item_color = "rainbow"
|
||||
qdel(W)
|
||||
qdel(src)
|
||||
user.put_in_hands(newSaber)
|
||||
else if(istype(W, /obj/item/device/multitool))
|
||||
if(hacked == 0)
|
||||
hacked = 1
|
||||
if(istype(W, /obj/item/device/multitool))
|
||||
if(!hacked)
|
||||
hacked = TRUE
|
||||
item_color = "rainbow"
|
||||
to_chat(user, "<span class='warning'>RNBW_ENGAGE</span>")
|
||||
|
||||
@@ -253,14 +243,12 @@
|
||||
sharpness = IS_SHARP
|
||||
|
||||
//Most of the other special functions are handled in their own files. aka special snowflake code so kewl
|
||||
/obj/item/weapon/melee/energy/blade/New()
|
||||
/obj/item/weapon/melee/energy/blade/Initialize()
|
||||
. = ..()
|
||||
spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
|
||||
/obj/item/weapon/melee/energy/blade/dropped()
|
||||
..()
|
||||
|
||||
/obj/item/weapon/melee/energy/blade/attack_self(mob/user)
|
||||
return
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
|
||||
#define PCANNON_FIREALL 1
|
||||
#define PCANNON_FILO 2
|
||||
#define PCANNON_FIFO 3
|
||||
/obj/item/weapon/pneumatic_cannon
|
||||
name = "pneumatic cannon"
|
||||
desc = "A gas-powered cannon that can fire any object loaded into it."
|
||||
@@ -16,7 +20,15 @@
|
||||
var/gasPerThrow = 3 //How much gas is drawn from a tank's pressure to fire
|
||||
var/list/loadedItems = list() //The items loaded into the cannon that will be fired out
|
||||
var/pressureSetting = 1 //How powerful the cannon is - higher pressure = more gas but more powerful throws
|
||||
var/checktank = TRUE
|
||||
var/range_multiplier = 1
|
||||
var/throw_amount = 20 //How many items to throw per fire
|
||||
var/fire_mode = PCANNON_FIREALL
|
||||
var/automatic = FALSE
|
||||
var/clumsyCheck = TRUE
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/CanItemAutoclick()
|
||||
return automatic
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/examine(mob/user)
|
||||
..()
|
||||
@@ -30,6 +42,8 @@
|
||||
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/attackby(obj/item/weapon/W, mob/user, params)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
if(istype(W, /obj/item/weapon/tank/internals))
|
||||
if(!tank)
|
||||
var/obj/item/weapon/tank/internals/IT = W
|
||||
@@ -55,19 +69,31 @@
|
||||
to_chat(user, "<span class='warning'>\The [src] can't hold any more items!</span>")
|
||||
else if(istype(W, /obj/item))
|
||||
var/obj/item/IW = W
|
||||
if((loadedWeightClass + IW.w_class) > maxWeightClass)
|
||||
to_chat(user, "<span class='warning'>\The [IW] won't fit into \the [src]!</span>")
|
||||
return
|
||||
if(IW.w_class > src.w_class)
|
||||
to_chat(user, "<span class='warning'>\The [IW] is too large to fit into \the [src]!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You load \the [IW] into \the [src].</span>")
|
||||
loadedItems.Add(IW)
|
||||
loadedWeightClass += IW.w_class
|
||||
load_item(IW, user)
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/proc/can_load_item(obj/item/I, mob/user)
|
||||
if((loadedWeightClass + I.w_class) > maxWeightClass) //Only make messages if there's a user
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>\The [I] won't fit into \the [src]!</span>")
|
||||
return FALSE
|
||||
if(I.w_class > w_class)
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>\The [I] is too large to fit into \the [src]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/proc/load_item(obj/item/I, mob/user)
|
||||
if(!can_load_item(I, user))
|
||||
return FALSE
|
||||
if(user) //Only use transfer proc if there's a user, otherwise just set loc.
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return FALSE
|
||||
to_chat(user, "<span class='notice'>You load \the [I] into \the [src].</span>")
|
||||
else
|
||||
I.forceMove(src)
|
||||
loadedItems += I
|
||||
loadedWeightClass += I.w_class
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/afterattack(atom/target, mob/living/carbon/human/user, flag, params)
|
||||
if(flag && user.a_intent == INTENT_HARM) //melee attack
|
||||
@@ -76,7 +102,6 @@
|
||||
return
|
||||
Fire(user, target)
|
||||
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/proc/Fire(mob/living/carbon/human/user, var/atom/target)
|
||||
if(!istype(user) && !target)
|
||||
return
|
||||
@@ -90,13 +115,13 @@
|
||||
if(!loadedItems || !loadedWeightClass)
|
||||
to_chat(user, "<span class='warning'>\The [src] has nothing loaded.</span>")
|
||||
return
|
||||
if(!tank)
|
||||
if(!tank && checktank)
|
||||
to_chat(user, "<span class='warning'>\The [src] can't fire without a source of gas.</span>")
|
||||
return
|
||||
if(tank && !tank.air_contents.remove(gasPerThrow * pressureSetting))
|
||||
to_chat(user, "<span class='warning'>\The [src] lets out a weak hiss and doesn't react!</span>")
|
||||
return
|
||||
if(user.disabilities & CLUMSY && prob(75))
|
||||
if(user.disabilities & CLUMSY && prob(75) && clumsyCheck)
|
||||
user.visible_message("<span class='warning'>[user] loses their grip on [src], causing it to go off!</span>", "<span class='userdanger'>[src] slips out of your hands and goes off!</span>")
|
||||
user.drop_item()
|
||||
if(prob(10))
|
||||
@@ -109,17 +134,48 @@
|
||||
user.visible_message("<span class='danger'>[user] fires \the [src]!</span>", \
|
||||
"<span class='danger'>You fire \the [src]!</span>")
|
||||
add_logs(user, target, "fired at", src)
|
||||
var/turf/T = get_target(target, get_turf(src))
|
||||
playsound(src.loc, 'sound/weapons/sonic_jackhammer.ogg', 50, 1)
|
||||
for(var/obj/item/ITD in loadedItems) //Item To Discharge
|
||||
loadedItems.Remove(ITD)
|
||||
loadedWeightClass -= ITD.w_class
|
||||
ITD.throw_speed = pressureSetting * 2
|
||||
ITD.loc = get_turf(src)
|
||||
ITD.throw_at(target, pressureSetting * 5, pressureSetting * 2,user)
|
||||
fire_items(T, user)
|
||||
if(pressureSetting >= 3 && user)
|
||||
user.visible_message("<span class='warning'>[user] is thrown down by the force of the cannon!</span>", "<span class='userdanger'>[src] slams into your shoulder, knocking you down!")
|
||||
user.Weaken(3)
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/proc/fire_items(turf/target, mob/user)
|
||||
if(fire_mode == PCANNON_FIREALL)
|
||||
for(var/obj/item/ITD in loadedItems) //Item To Discharge
|
||||
if(!throw_item(target, ITD, user))
|
||||
break
|
||||
else
|
||||
for(var/i in 1 to throw_amount)
|
||||
if(!loadedItems.len)
|
||||
break
|
||||
var/obj/item/I
|
||||
if(fire_mode == PCANNON_FILO)
|
||||
I = loadedItems[loadedItems.len]
|
||||
else
|
||||
I = loadedItems[1]
|
||||
if(!throw_item(target, I, user))
|
||||
break
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/proc/throw_item(turf/target, obj/item/I, mob/user)
|
||||
if(!istype(I))
|
||||
return FALSE
|
||||
loadedItems -= I
|
||||
loadedWeightClass -= I.w_class
|
||||
I.forceMove(get_turf(src))
|
||||
I.throw_at(target, pressureSetting * 10 * range_multiplier, pressureSetting * 2, user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/proc/get_target(turf/target, turf/starting)
|
||||
if(range_multiplier == 1)
|
||||
return target
|
||||
var/x_o = (target.x - starting.x)
|
||||
var/y_o = (target.y - starting.y)
|
||||
var/new_x = Clamp((starting.x + (x_o * range_multiplier)), 0, world.maxx)
|
||||
var/new_y = Clamp((starting.y + (y_o * range_multiplier)), 0, world.maxy)
|
||||
var/turf/newtarget = locate(new_x, new_y, starting.z)
|
||||
return newtarget
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/ghetto //Obtainable by improvised methods; more gas per use, less capacity, but smaller
|
||||
name = "improvised pneumatic cannon"
|
||||
@@ -164,3 +220,35 @@
|
||||
return
|
||||
add_overlay(tank.icon_state)
|
||||
src.update_icon()
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/proc/fill_with_type(type, amount)
|
||||
if(!ispath(type, /obj/item))
|
||||
return FALSE
|
||||
var/loaded = 0
|
||||
for(var/i in 1 to amount)
|
||||
var/obj/item/I = new type
|
||||
if(!load_item(I, null))
|
||||
qdel(I)
|
||||
return loaded
|
||||
loaded++
|
||||
CHECK_TICK
|
||||
return loaded
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/pie
|
||||
name = "pie cannon"
|
||||
desc = "Load cream pie for optimal results"
|
||||
force = 10
|
||||
icon_state = "piecannon"
|
||||
gasPerThrow = 0
|
||||
checktank = FALSE
|
||||
range_multiplier = 3
|
||||
fire_mode = PCANNON_FIFO
|
||||
throw_amount = 1
|
||||
maxWeightClass = 100 //50 pies. :^)
|
||||
clumsyCheck = FALSE
|
||||
|
||||
/obj/item/weapon/pneumatic_cannon/pie/can_load_item(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/pie))
|
||||
return ..()
|
||||
to_chat(user, "<span class='warning'>[src] only accepts pies!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
//////////////////////////////////
|
||||
//dakimakuras
|
||||
//////////////////////////////////
|
||||
|
||||
/obj/item/weapon/storage/daki
|
||||
name = "dakimakura"
|
||||
desc = "A large pillow depicting a girl in a compromising position. Featuring as many dimensions as you."
|
||||
icon = 'icons/obj/daki.dmi'
|
||||
icon_state = "daki_base"
|
||||
slot_flags = SLOT_BACK
|
||||
storage_slots = 3
|
||||
w_class = 4
|
||||
max_w_class = 3
|
||||
max_combined_w_class = 21
|
||||
var/cooldowntime = 20
|
||||
var/static/list/dakimakura_options = list("Callie","Casca","Chaika","Elisabeth","Foxy Grandpa","Haruko","Holo","Ian","Jolyne","Kurisu","Marie","Mugi","Nar'Sie","Patchouli","Plutia","Rei","Reisen","Naga","Squid","Squigly","Tomoko","Toriel","Umaru","Yaranaika","Yoko") //Kurisu is the ideal girl." - Me, Logos.
|
||||
|
||||
/obj/item/weapon/storage/daki/attack_self(mob/living/user)
|
||||
var/body_choice
|
||||
var/custom_name
|
||||
|
||||
if(icon_state == "daki_base")
|
||||
body_choice = input("Pick a body.") in dakimakura_options
|
||||
icon_state = "daki_[body_choice]"
|
||||
custom_name = stripped_input(user, "What's her name?")
|
||||
if(length(custom_name) > MAX_NAME_LEN)
|
||||
to_chat(user,"<span class='danger'>Name is too long!</span>")
|
||||
return FALSE
|
||||
if(custom_name)
|
||||
name = custom_name
|
||||
desc = "A large pillow depicting [custom_name] in a compromising position. Featuring as many dimensions as you."
|
||||
else
|
||||
switch(user.a_intent)
|
||||
if(INTENT_HELP)
|
||||
user.visible_message("<span class='notice'>[user] hugs the [name].</span>")
|
||||
playsound(src, "rustle", 50, 1, -5)
|
||||
if(INTENT_DISARM)
|
||||
user.visible_message("<span class='notice'>[user] kisses the [name].</span>")
|
||||
playsound(src, "rustle", 50, 1, -5)
|
||||
if(INTENT_GRAB)
|
||||
user.visible_message("<span class='warning'>[user] holds the [name]!</span>")
|
||||
playsound(src, 'sound/items/bikehorn.ogg', 50, 1)
|
||||
if(INTENT_HARM)
|
||||
user.visible_message("<span class='danger'>[user] punches the [name]!</span>")
|
||||
playsound(src, 'sound/effects/shieldbash.ogg', 50, 1)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
|
||||
////////////////////////////
|
||||
@@ -5,10 +5,6 @@
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
rustle_jimmies = FALSE
|
||||
|
||||
/obj/item/weapon/storage/internal/ClickAccessible(mob/user, depth=1)
|
||||
if(loc)
|
||||
return loc.ClickAccessible(user, depth)
|
||||
|
||||
/obj/item/weapon/storage/internal/Adjacent(A)
|
||||
if(loc)
|
||||
return loc.Adjacent(A)
|
||||
@@ -53,7 +49,7 @@
|
||||
/obj/item/weapon/implanter, /obj/item/weapon/screwdriver, /obj/item/weapon/weldingtool/mini,
|
||||
/obj/item/device/firing_pin
|
||||
)
|
||||
//can hold both regular pens and energy daggers. made for your every-day tactical librarians/murderers.
|
||||
//can hold both regular pens and energy daggers. made for your every-day tactical curators/murderers.
|
||||
priority = FALSE
|
||||
quickdraw = TRUE
|
||||
silent = TRUE
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
return
|
||||
|
||||
// this must come before the screen objects only block, dunno why it wasn't before
|
||||
if(over_object == M && (src.ClickAccessible(M, depth=STORAGE_VIEW_DEPTH) || Adjacent(M)))
|
||||
if(over_object == M && M.CanReach(src,view_only = TRUE))
|
||||
orient2hud(M)
|
||||
if(M.s_active)
|
||||
M.s_active.close(M)
|
||||
|
||||
@@ -92,8 +92,7 @@
|
||||
new /obj/item/pizzabox/bomb
|
||||
|
||||
if("darklord") //20 tc + tk + summon item close enough for now
|
||||
new /obj/item/weapon/melee/energy/sword/saber(src)
|
||||
new /obj/item/weapon/melee/energy/sword/saber(src)
|
||||
new /obj/item/weapon/twohanded/dualsaber(src)
|
||||
new /obj/item/weapon/dnainjector/telemut/darkbundle(src)
|
||||
new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
|
||||
new /obj/item/weapon/card/id/syndicate(src)
|
||||
@@ -219,8 +218,8 @@
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/polonium(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/venom(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/neurotoxin2(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/formaldehyde(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/spewium(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/formaldehyde(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/spewium(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/cyanide(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/histamine(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/initropidril(src)
|
||||
@@ -297,3 +296,10 @@
|
||||
/obj/item/weapon/storage/box/syndie_kit/mimery/PopulateContents()
|
||||
new /obj/item/weapon/spellbook/oneuse/mimery_blockade(src)
|
||||
new /obj/item/weapon/spellbook/oneuse/mimery_guns(src)
|
||||
|
||||
/obj/item/weapon/storage/box/syndie_kit/holoparasite
|
||||
name = "box"
|
||||
|
||||
/obj/item/weapon/storage/box/syndie_kit/holoparasite/PopulateContents()
|
||||
new /obj/item/weapon/guardiancreator/tech/choose/traitor(src)
|
||||
new /obj/item/weapon/paper/guardian(src)
|
||||
@@ -262,11 +262,11 @@
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 70)
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/hacked = 0
|
||||
var/brightness_on = 6//TWICE AS BRIGHT AS A REGULAR ESWORD
|
||||
var/brightness_on = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD
|
||||
var/list/possible_colors = list("red", "blue", "green", "purple")
|
||||
|
||||
/obj/item/weapon/twohanded/dualsaber/Initialize()
|
||||
..()
|
||||
. = ..()
|
||||
if(LAZYLEN(possible_colors))
|
||||
item_color = pick(possible_colors)
|
||||
switch(item_color)
|
||||
|
||||
@@ -390,7 +390,7 @@
|
||||
desc = "A chainsaw that has replaced your arm."
|
||||
icon_state = "chainsaw_on"
|
||||
item_state = "mounted_chainsaw"
|
||||
flags = NODROP | ABSTRACT
|
||||
flags = NODROP | ABSTRACT | DROPDEL
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
force = 21
|
||||
throwforce = 0
|
||||
@@ -400,10 +400,17 @@
|
||||
attack_verb = list("sawed", "torn", "cut", "chopped", "diced")
|
||||
hitsound = 'sound/weapons/chainsawhit.ogg'
|
||||
|
||||
/obj/item/weapon/mounted_chainsaw/dropped()
|
||||
..()
|
||||
/obj/item/weapon/mounted_chainsaw/Destroy()
|
||||
var/obj/item/bodypart/part
|
||||
new /obj/item/weapon/twohanded/required/chainsaw(get_turf(src))
|
||||
qdel(src)
|
||||
if(iscarbon(loc))
|
||||
var/mob/living/carbon/holder = loc
|
||||
var/index = holder.get_held_index_of_item(src)
|
||||
if(index)
|
||||
part = holder.hand_bodyparts[index]
|
||||
. = ..()
|
||||
if(part)
|
||||
part.drop_limb()
|
||||
|
||||
/obj/item/weapon/statuebust
|
||||
name = "bust"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
var/persistence_replacement //have something WAY too amazing to live to the next round? Set a new path here. Overuse of this var will make me upset.
|
||||
var/unique_rename = FALSE // can you customize the description/name of the thing?
|
||||
|
||||
|
||||
var/dangerous_possession = FALSE //Admin possession yes/no
|
||||
|
||||
/obj/vv_edit_var(vname, vval)
|
||||
|
||||
@@ -106,6 +106,11 @@ LINEN BINS
|
||||
icon_state = "sheetrd"
|
||||
item_color = "director"
|
||||
|
||||
// for Free Golems.
|
||||
/obj/item/weapon/bedsheet/rd/royal_cape
|
||||
name = "Royal Cape of the Liberator"
|
||||
desc = "Majestic."
|
||||
|
||||
/obj/item/weapon/bedsheet/medical
|
||||
name = "medical blanket"
|
||||
desc = "It's a sterilized* blanket commonly used in the Medbay. *Sterilization is voided if a virologist is present onboard the station."
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
else
|
||||
new /obj/item/weapon/storage/backpack/satchel/cap(src)
|
||||
new /obj/item/clothing/neck/cloak/cap(src)
|
||||
new /obj/item/weapon/storage/daki(src)
|
||||
new /obj/item/weapon/storage/backpack/dufflebag/captain(src)
|
||||
new /obj/item/clothing/head/crown/fancy(src)
|
||||
new /obj/item/clothing/suit/captunic(src)
|
||||
|
||||
@@ -11,30 +11,31 @@
|
||||
max_integrity = 200
|
||||
integrity_failure = 50
|
||||
var/obj/item/showpiece = null
|
||||
var/alert = 0
|
||||
var/open = 0
|
||||
var/alert = TRUE
|
||||
var/open = FALSE
|
||||
var/openable = TRUE
|
||||
var/obj/item/weapon/electronics/airlock/electronics
|
||||
var/start_showpiece_type = null //add type for items on display
|
||||
|
||||
/obj/structure/displaycase/Initialize()
|
||||
. = ..()
|
||||
/obj/structure/displaycase/Initialize()
|
||||
. = ..()
|
||||
if(start_showpiece_type)
|
||||
showpiece = new start_showpiece_type (src)
|
||||
update_icon()
|
||||
|
||||
/obj/structure/displaycase/Destroy()
|
||||
if(electronics)
|
||||
QDEL_NULL(electronics)
|
||||
QDEL_NULL(electronics)
|
||||
if(showpiece)
|
||||
QDEL_NULL(showpiece)
|
||||
QDEL_NULL(showpiece)
|
||||
return ..()
|
||||
|
||||
/obj/structure/displaycase/examine(mob/user)
|
||||
..()
|
||||
if(alert)
|
||||
to_chat(user, "<span class='notice'>Hooked up with an anti-theft system.</span>")
|
||||
if(showpiece)
|
||||
to_chat(user, "<span class='notice'>There's [showpiece] inside.</span>")
|
||||
if(showpiece)
|
||||
to_chat(user, "<span class='notice'>There's [showpiece] inside.</span>")
|
||||
|
||||
|
||||
/obj/structure/displaycase/proc/dump()
|
||||
@@ -81,8 +82,8 @@
|
||||
try
|
||||
getFlatIcon(A,defdir=4)
|
||||
catch
|
||||
return 0
|
||||
return 1
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/structure/displaycase/proc/get_flat_icon_directional(atom/A)
|
||||
//Get flatIcon even if dir is mismatched for directionless icons
|
||||
@@ -113,7 +114,7 @@
|
||||
return
|
||||
|
||||
/obj/structure/displaycase/attackby(obj/item/weapon/W, mob/user, params)
|
||||
if(W.GetID() && !broken)
|
||||
if(W.GetID() && !broken && openable)
|
||||
if(allowed(user))
|
||||
to_chat(user, "<span class='notice'>You [open ? "close":"open"] the [src]</span>")
|
||||
toggle_lock(user)
|
||||
@@ -132,7 +133,7 @@
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] is already in good condition!</span>")
|
||||
return
|
||||
else if(!alert && istype(W,/obj/item/weapon/crowbar)) //Only applies to the lab cage and player made display cases
|
||||
else if(!alert && istype(W,/obj/item/weapon/crowbar) && openable) //Only applies to the lab cage and player made display cases
|
||||
if(broken)
|
||||
if(showpiece)
|
||||
to_chat(user, "<span class='notice'>Remove the displayed object first.</span>")
|
||||
@@ -145,8 +146,7 @@
|
||||
to_chat(user, "<span class='notice'>You [open ? "close":"open"] the [src]</span>")
|
||||
toggle_lock(user)
|
||||
else if(open && !showpiece)
|
||||
if(user.drop_item())
|
||||
W.loc = src
|
||||
if(user.transferItemToLoc(W, src))
|
||||
showpiece = W
|
||||
to_chat(user, "<span class='notice'>You put [W] on display</span>")
|
||||
update_icon()
|
||||
@@ -175,7 +175,7 @@
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
if (showpiece && (broken || open))
|
||||
to_chat(user, "<span class='notice'>You deactivate the hover field built into the case.</span>")
|
||||
dump()
|
||||
dump()
|
||||
src.add_fingerprint(user)
|
||||
update_icon()
|
||||
return
|
||||
@@ -247,96 +247,115 @@
|
||||
desc = "A glass lab container for storing interesting creatures."
|
||||
start_showpiece_type = /obj/item/clothing/mask/facehugger/lamarr
|
||||
req_access = list(GLOB.access_rd)
|
||||
|
||||
|
||||
|
||||
/obj/structure/displaycase/trophy
|
||||
name = "trophy display case"
|
||||
desc = "Store your trophies of accomplishment in here, and they will stay forever."
|
||||
var/trophy_message = ""
|
||||
var/placer_key = ""
|
||||
var/added_roundstart = TRUE
|
||||
alert = TRUE
|
||||
integrity_failure = 0
|
||||
|
||||
/obj/structure/displaycase/trophy/Initialize()
|
||||
. = ..()
|
||||
GLOB.trophy_cases += src
|
||||
|
||||
/obj/structure/displaycase/trophy/Destroy()
|
||||
GLOB.trophy_cases -= src
|
||||
return ..()
|
||||
|
||||
/obj/structure/displaycase/trophy/examine(mob/user)
|
||||
..()
|
||||
if(trophy_message)
|
||||
to_chat(user, "The plaque reads:")
|
||||
to_chat(user, trophy_message)
|
||||
|
||||
/obj/structure/displaycase/trophy/attackby(obj/item/weapon/W, mob/user, params)
|
||||
|
||||
if(!user.Adjacent(src)) //no TK museology
|
||||
return
|
||||
|
||||
if(!added_roundstart)
|
||||
to_chat(user, "You've already put something new in this case.")
|
||||
return
|
||||
|
||||
if(is_type_in_typecache(W, GLOB.blacklisted_cargo_types))
|
||||
to_chat(user, "<span class='danger'>The case rejects the [W].</span>")
|
||||
return
|
||||
|
||||
for(var/a in W.GetAllContents())
|
||||
if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types))
|
||||
to_chat(user, "<span class='danger'>The case rejects the [W].</span>")
|
||||
return
|
||||
|
||||
if(user.drop_item())
|
||||
|
||||
if(showpiece)
|
||||
to_chat(user, "You press a button, and [showpiece] descends into the floor of the case.")
|
||||
QDEL_NULL(showpiece)
|
||||
|
||||
to_chat(user, "You insert [W] into the case.")
|
||||
W.forceMove(src)
|
||||
showpiece = W
|
||||
added_roundstart = FALSE
|
||||
update_icon()
|
||||
|
||||
placer_key = user.ckey
|
||||
|
||||
trophy_message = W.desc //default value
|
||||
|
||||
var/chosen_plaque = stripped_input(user, "What would you like the plaque to say? Default value is item's description.", "Trophy Plaque")
|
||||
if(chosen_plaque)
|
||||
if(user.Adjacent(src))
|
||||
trophy_message = chosen_plaque
|
||||
to_chat(user, "You set the plaque's text.")
|
||||
else
|
||||
to_chat(user, "You are too far to set the plaque's text.")
|
||||
|
||||
SSpersistence.SaveTrophy(src)
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [W] is stuck to your hand, you can't put it in the [src.name]!</span>")
|
||||
|
||||
return
|
||||
|
||||
/obj/structure/displaycase/trophy/dump()
|
||||
if (showpiece)
|
||||
if(added_roundstart)
|
||||
visible_message("<span class='danger'>The [showpiece] crumbles to dust!</span>")
|
||||
new /obj/effect/decal/cleanable/ash(loc)
|
||||
QDEL_NULL(showpiece)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/showpiece_dummy
|
||||
name = "Cheap replica"
|
||||
|
||||
/obj/item/showpiece_dummy/Initialize(mapload, path)
|
||||
. = ..()
|
||||
var/obj/item/I = path
|
||||
name = initial(I.name)
|
||||
icon = initial(I.icon)
|
||||
icon_state = initial(I.icon_state)
|
||||
|
||||
/obj/structure/displaycase/trophy
|
||||
name = "trophy display case"
|
||||
desc = "Store your trophies of accomplishment in here, and they will stay forever."
|
||||
var/trophy_message = ""
|
||||
var/placer_key = ""
|
||||
var/added_roundstart = TRUE
|
||||
var/is_locked = TRUE
|
||||
|
||||
alert = TRUE
|
||||
integrity_failure = 0
|
||||
openable = FALSE
|
||||
|
||||
/obj/structure/displaycase/trophy/Initialize()
|
||||
. = ..()
|
||||
GLOB.trophy_cases += src
|
||||
|
||||
/obj/structure/displaycase/trophy/Destroy()
|
||||
GLOB.trophy_cases -= src
|
||||
return ..()
|
||||
|
||||
/obj/structure/displaycase/trophy/examine(mob/user)
|
||||
..()
|
||||
if(trophy_message)
|
||||
to_chat(user, "The plaque reads:")
|
||||
to_chat(user, trophy_message)
|
||||
|
||||
/obj/structure/displaycase/trophy/attackby(obj/item/weapon/W, mob/user, params)
|
||||
|
||||
if(!user.Adjacent(src)) //no TK museology
|
||||
return
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
if(user.is_holding_item_of_type(/obj/item/key/displaycase))
|
||||
if(added_roundstart)
|
||||
is_locked = !is_locked
|
||||
to_chat(user, "You [!is_locked ? "un" : ""]lock the case.")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>The lock is stuck shut!</span>")
|
||||
return
|
||||
|
||||
if(is_locked)
|
||||
to_chat(user, "<span class='danger'>The case is shut tight with an old fashioned physical lock. Maybe you should ask the curator for the key?</span>")
|
||||
return
|
||||
|
||||
if(!added_roundstart)
|
||||
to_chat(user, "You've already put something new in this case.")
|
||||
return
|
||||
|
||||
if(is_type_in_typecache(W, GLOB.blacklisted_cargo_types))
|
||||
to_chat(user, "<span class='danger'>The case rejects the [W].</span>")
|
||||
return
|
||||
|
||||
for(var/a in W.GetAllContents())
|
||||
if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types))
|
||||
to_chat(user, "<span class='danger'>The case rejects the [W].</span>")
|
||||
return
|
||||
|
||||
if(user.transferItemToLoc(W, src))
|
||||
|
||||
if(showpiece)
|
||||
to_chat(user, "You press a button, and [showpiece] descends into the floor of the case.")
|
||||
QDEL_NULL(showpiece)
|
||||
|
||||
to_chat(user, "You insert [W] into the case.")
|
||||
showpiece = W
|
||||
added_roundstart = FALSE
|
||||
update_icon()
|
||||
|
||||
placer_key = user.ckey
|
||||
|
||||
trophy_message = W.desc //default value
|
||||
|
||||
var/chosen_plaque = stripped_input(user, "What would you like the plaque to say? Default value is item's description.", "Trophy Plaque")
|
||||
if(chosen_plaque)
|
||||
if(user.Adjacent(src))
|
||||
trophy_message = chosen_plaque
|
||||
to_chat(user, "You set the plaque's text.")
|
||||
else
|
||||
to_chat(user, "You are too far to set the plaque's text.")
|
||||
|
||||
SSpersistence.SaveTrophy(src)
|
||||
return TRUE
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [W] is stuck to your hand, you can't put it in the [src.name]!</span>")
|
||||
|
||||
return
|
||||
|
||||
/obj/structure/displaycase/trophy/dump()
|
||||
if (showpiece)
|
||||
if(added_roundstart)
|
||||
visible_message("<span class='danger'>The [showpiece] crumbles to dust!</span>")
|
||||
new /obj/effect/decal/cleanable/ash(loc)
|
||||
QDEL_NULL(showpiece)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/key/displaycase
|
||||
name = "display case key"
|
||||
desc = "The key to the curator's display cases."
|
||||
|
||||
/obj/item/showpiece_dummy
|
||||
name = "Cheap replica"
|
||||
|
||||
/obj/item/showpiece_dummy/Initialize(mapload, path)
|
||||
. = ..()
|
||||
var/obj/item/I = path
|
||||
name = initial(I.name)
|
||||
icon = initial(I.icon)
|
||||
icon_state = initial(I.icon_state)
|
||||
|
||||
@@ -234,8 +234,9 @@
|
||||
|
||||
/obj/structure/falsewall/plasma/attackby(obj/item/weapon/W, mob/user, params)
|
||||
if(W.is_hot() > 300)
|
||||
message_admins("Plasma falsewall ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Plasma falsewall ignited by [key_name(user)] in ([x],[y],[z])")
|
||||
var/turf/T = get_turf(src)
|
||||
message_admins("Plasma falsewall ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
|
||||
log_game("Plasma falsewall ignited by [key_name(user)] in [COORD(T)]")
|
||||
burnbabyburn()
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -155,8 +155,6 @@
|
||||
name = "dust-caked golem shell"
|
||||
desc = "A humanoid shape, empty, lifeless, and full of potential."
|
||||
mob_name = "a free golem"
|
||||
anchored = 1
|
||||
density = 1
|
||||
can_transfer = FALSE
|
||||
mob_species = /datum/species/golem/adamantine
|
||||
|
||||
|
||||
@@ -188,8 +188,9 @@
|
||||
|
||||
/obj/structure/mineral_door/transparent/plasma/attackby(obj/item/weapon/W, mob/user, params)
|
||||
if(W.is_hot())
|
||||
message_admins("Plasma mineral door ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Plasma mineral door ignited by [key_name(user)] in ([x],[y],[z])")
|
||||
var/turf/T = get_turf(src)
|
||||
message_admins("Plasma mineral door ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
|
||||
log_game("Plasma mineral door ignited by [key_name(user)] in [COORD(T)]")
|
||||
TemperatureAct()
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -163,18 +163,20 @@
|
||||
PlasmaBurn(500)
|
||||
burn = TRUE
|
||||
if(burn)
|
||||
var/turf/T = get_turf(src)
|
||||
if(Proj.firer)
|
||||
message_admins("Plasma statue ignited by [key_name_admin(Proj.firer)](<A HREF='?_src_=holder;adminmoreinfo=\ref[Proj.firer]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[Proj.firer]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Plasma statue ignited by [key_name(Proj.firer)] in ([x],[y],[z])")
|
||||
message_admins("Plasma statue ignited by [ADMIN_LOOKUPFLW(Proj.firer)] in [ADMIN_COORDJMP(T)]",0,1)
|
||||
log_game("Plasma statue ignited by [key_name(Proj.firer)] in [COORD(T)]")
|
||||
else
|
||||
message_admins("Plasma statue ignited by [Proj]. No known firer.(<A HREF='?_src_=holder;adminmoreinfo=\ref[Proj.firer]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[Proj.firer]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Plasma statue ignited by [Proj] in ([x],[y],[z]). No known firer.")
|
||||
message_admins("Plasma statue ignited by [Proj]. No known firer, in [ADMIN_COORDJMP(T)]",0,1)
|
||||
log_game("Plasma statue ignited by [Proj] in [COORD(T)]. No known firer.")
|
||||
..()
|
||||
|
||||
/obj/structure/statue/plasma/attackby(obj/item/weapon/W, mob/user, params)
|
||||
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
|
||||
message_admins("Plasma statue ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Plasma statue ignited by [key_name(user)] in ([x],[y],[z])")
|
||||
var/turf/T = get_turf(src)
|
||||
message_admins("Plasma statue ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
|
||||
log_game("Plasma statue ignited by [key_name(user)] in [COORD(T)]")
|
||||
ignite(W.is_hot())
|
||||
else
|
||||
return ..()
|
||||
|
||||
+6
-6
@@ -35,10 +35,10 @@ GLOBAL_LIST_INIT(freqtospan, list(
|
||||
return 1
|
||||
|
||||
/atom/movable/proc/send_speech(message, range = 7, obj/source = src, bubble_type, list/spans, datum/language/message_language = null, message_mode)
|
||||
var/rendered = compose_message(src, message_language, message, , spans, message_mode)
|
||||
var/rendered = compose_message(src, message_language, message, , spans)
|
||||
for(var/_AM in get_hearers_in_view(range, source))
|
||||
var/atom/movable/AM = _AM
|
||||
AM.Hear(rendered, src, message_language, message, , spans, message_mode)
|
||||
AM.Hear(rendered, src, message_language, message, , spans)
|
||||
|
||||
//To get robot span classes, stuff like that.
|
||||
/atom/movable/proc/get_spans()
|
||||
@@ -58,10 +58,10 @@ GLOBAL_LIST_INIT(freqtospan, list(
|
||||
var/endspanpart = "</span>"
|
||||
|
||||
//Message
|
||||
var/messagepart = " <span class='message'>[lang_treat(speaker, message_language, raw_message, spans, message_mode)]</span></span>"
|
||||
var/messagepart = " <span class='message'>[lang_treat(speaker, message_language, raw_message, spans)]</span></span>"
|
||||
|
||||
var/languageicon = ""
|
||||
var/datum/language/D = get_language_instance(message_language)
|
||||
var/datum/language/D = GLOB.language_datum_instances[message_language]
|
||||
if(D.display_icon(src))
|
||||
languageicon = "[D.get_icon()] "
|
||||
|
||||
@@ -103,7 +103,7 @@ GLOBAL_LIST_INIT(freqtospan, list(
|
||||
return speaker.say_quote(raw_message, spans, message_mode)
|
||||
else if(language)
|
||||
var/atom/movable/AM = speaker.GetSource()
|
||||
var/datum/language/D = get_language_instance(language)
|
||||
var/datum/language/D = GLOB.language_datum_instances[language]
|
||||
raw_message = D.scramble(raw_message)
|
||||
if(AM)
|
||||
return AM.say_quote(raw_message, spans, message_mode)
|
||||
@@ -143,7 +143,7 @@ GLOBAL_LIST_INIT(freqtospan, list(
|
||||
return "0"
|
||||
|
||||
/atom/movable/proc/GetVoice()
|
||||
return name
|
||||
return "[src]" //Returns the atom's name, prepended with 'The' if it's not a proper noun
|
||||
|
||||
/atom/movable/proc/IsVocal()
|
||||
return 1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* In this file:
|
||||
* Wood floor
|
||||
* Grass floor
|
||||
* Fake Basalt
|
||||
* Carpet floor
|
||||
* Fake pits
|
||||
* Fake space
|
||||
@@ -67,6 +68,7 @@
|
||||
broken_states = list("sand")
|
||||
flags = NONE
|
||||
var/ore_type = /obj/item/weapon/ore/glass
|
||||
var/turfverb = "uproot"
|
||||
|
||||
/turf/open/floor/grass/Initialize()
|
||||
..()
|
||||
@@ -76,7 +78,7 @@
|
||||
if(istype(C, /obj/item/weapon/shovel) && params)
|
||||
new ore_type(src)
|
||||
new ore_type(src) //Make some sand if you shovel grass
|
||||
user.visible_message("<span class='notice'>[user] digs up [src].</span>", "<span class='notice'>You uproot [src].</span>")
|
||||
user.visible_message("<span class='notice'>[user] digs up [src].</span>", "<span class='notice'>You [src.turfverb] [src].</span>")
|
||||
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
|
||||
make_plating()
|
||||
if(..())
|
||||
@@ -93,7 +95,6 @@
|
||||
initial_gas_mix = "o2=22;n2=82;TEMP=180"
|
||||
slowdown = 2
|
||||
|
||||
|
||||
/turf/open/floor/grass/snow/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/weapon/crowbar))//You need to dig this turf out instead of crowbarring it
|
||||
return
|
||||
@@ -113,6 +114,24 @@
|
||||
icon_state = "basalt[rand(0, 12)]"
|
||||
set_basalt_light(src)
|
||||
|
||||
|
||||
/turf/open/floor/grass/fakebasalt //Heart is not a real planeteer power
|
||||
name = "aesthetic volcanic flooring"
|
||||
desc = "Safely recreated turf for your hellplanet-scaping"
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "basalt"
|
||||
floor_tile = /obj/item/stack/tile/basalt
|
||||
ore_type = /obj/item/weapon/ore/glass/basalt
|
||||
turfverb = "dig up"
|
||||
slowdown = 0
|
||||
|
||||
/turf/open/floor/grass/fakebasalt/Initialize()
|
||||
..()
|
||||
if(prob(15))
|
||||
icon_state = "basalt[rand(0, 12)]"
|
||||
set_basalt_light(src)
|
||||
|
||||
|
||||
/turf/open/floor/carpet
|
||||
name = "carpet"
|
||||
desc = "Soft velvet carpeting. Feels good between your toes."
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
|
||||
/turf/open/floor/mineral/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
|
||||
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
|
||||
message_admins("Plasma flooring was ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Plasma flooring was ignited by [key_name(user)] in ([x],[y],[z])")
|
||||
message_admins("Plasma flooring was ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(src)]",0,1)
|
||||
log_game("Plasma flooring was ignited by [key_name(user)] in [COORD(src)]")
|
||||
ignite(W.is_hot())
|
||||
return
|
||||
..()
|
||||
|
||||
@@ -407,14 +407,14 @@
|
||||
if(z != 5)
|
||||
notify_admins = 1
|
||||
if(!triggered_by_explosion)
|
||||
message_admins("[key_name_admin(user)]<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) has triggered a gibtonite deposit reaction at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has triggered a gibtonite deposit reaction at [A.name] [ADMIN_JMP(bombturf)].")
|
||||
else
|
||||
message_admins("An explosion has triggered a gibtonite deposit reaction at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>.")
|
||||
message_admins("An explosion has triggered a gibtonite deposit reaction at [A.name] [ADMIN_JMP(bombturf)].")
|
||||
|
||||
if(!triggered_by_explosion)
|
||||
log_game("[key_name(user)] has triggered a gibtonite deposit reaction at [A.name] ([A.x], [A.y], [A.z]).")
|
||||
log_game("[key_name(user)] has triggered a gibtonite deposit reaction at [A.name] [ADMIN_JMP(bombturf)].")
|
||||
else
|
||||
log_game("An explosion has triggered a gibtonite deposit reaction at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
|
||||
log_game("An explosion has triggered a gibtonite deposit reaction at [A.name] [COORD(bombturf)]")
|
||||
|
||||
countdown(notify_admins)
|
||||
|
||||
|
||||
@@ -101,8 +101,8 @@
|
||||
|
||||
/turf/closed/wall/mineral/plasma/attackby(obj/item/weapon/W, mob/user, params)
|
||||
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
|
||||
message_admins("Plasma wall ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Plasma wall ignited by [key_name(user)] in ([x],[y],[z])")
|
||||
message_admins("Plasma wall ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(src)]",0,1)
|
||||
log_game("Plasma wall ignited by [key_name(user)] in [COORD(src)]")
|
||||
ignite(W.is_hot())
|
||||
return
|
||||
..()
|
||||
|
||||
@@ -455,6 +455,8 @@
|
||||
O = new()
|
||||
O.underlays.Add(T)
|
||||
T.ChangeTurf(type)
|
||||
for(var/group in decals)
|
||||
T.add_decal(decals[group],group)
|
||||
if(underlays.len)
|
||||
T.underlays = O.underlays
|
||||
if(T.icon_state != icon_state)
|
||||
|
||||
Reference in New Issue
Block a user