Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into upstream-merge-26952

This commit is contained in:
LetterJay
2017-05-17 10:12:36 -05:00
454 changed files with 16010 additions and 8089 deletions
+2 -1
View File
@@ -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
View File
@@ -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())
+2 -1
View File
@@ -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))
+1 -3
View File
@@ -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))
+72 -54
View File
@@ -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)
+171 -2
View File
@@ -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)
+1 -1
View File
@@ -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
+22 -27
View File
@@ -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)
+9 -9
View File
@@ -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)
+124
View File
@@ -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
+3 -70
View File
@@ -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 ..()
+1 -1
View File
@@ -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
+2 -1
View File
@@ -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
+23
View File
@@ -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))
+5 -3
View File
@@ -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
+52 -27
View File
@@ -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 "&nbsp;&#8627;" + ..() //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
+6 -2
View File
@@ -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
+20 -11
View File
@@ -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!"
+197 -10
View File
@@ -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&&current.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
+14 -5
View File
@@ -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)
+4
View File
@@ -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"
+23 -18
View File
@@ -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()
+67 -49
View File
@@ -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()
..()
+8 -6
View File
@@ -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
+1 -1
View File
@@ -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
+3 -2
View File
@@ -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>")
+5 -4
View File
@@ -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)
+4 -3
View File
@@ -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
+4 -2
View File
@@ -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)
-44
View File
@@ -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)
+22 -11
View File
@@ -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"
+1 -1
View File
@@ -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)
+9 -8
View File
@@ -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)
+6 -5
View File
@@ -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
+2 -2
View File
@@ -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!
+1 -1
View File
@@ -94,7 +94,7 @@
name = "Head of Personnel"
/obj/effect/landmark/start/librarian
name = "Librarian"
name = "Curator"
/obj/effect/landmark/start/lawyer
name = "Lawyer"
+40 -2
View File
@@ -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"
+1 -1
View File
@@ -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
+6 -1
View File
@@ -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
+27 -3
View File
@@ -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!
+1 -1
View File
@@ -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
+83 -31
View File
@@ -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)
. = ..()
. = ..()
+2 -2
View File
@@ -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
+3 -3
View File
@@ -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
+46
View File
@@ -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)
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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)
+11 -4
View File
@@ -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"
+1 -1
View File
@@ -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)
+127 -108
View File
@@ -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)
+3 -2
View File
@@ -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 ..()
+8 -6
View File
@@ -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
View File
@@ -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
+21 -2
View File
@@ -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
..()
+4 -4
View File
@@ -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
..()
+2
View File
@@ -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)