Merge branch 'master' into upstream-merge-26140
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
if(!istype(H)) return 0
|
||||
var/obj/item/clothing/under/U = H.w_uniform
|
||||
if(!istype(U)) return 0
|
||||
if(U.sensor_mode <= 2) return 0
|
||||
if(U.sensor_mode <= SENSOR_VITALS) return 0
|
||||
return 1
|
||||
|
||||
/datum/atom_hud/data/human/medical/basic/add_to_single_hud(mob/M, mob/living/carbon/H)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
if(round_converted) //So badmin blobs later don't step on the dead natural blobs metaphorical toes
|
||||
..()
|
||||
if(blobwincount <= GLOB.blobs_legit.len)
|
||||
feedback_set_details("round_end_result","win - blob took over")
|
||||
SSblackbox.set_details("round_end_result","win - blob took over")
|
||||
to_chat(world, "<FONT size = 3><B>The blob has taken over the station!</B></FONT>")
|
||||
to_chat(world, "<B>The entire station was eaten by the Blob!</B>")
|
||||
log_game("Blob mode completed with a blob victory.")
|
||||
@@ -28,7 +28,7 @@
|
||||
SSticker.news_report = BLOB_WIN
|
||||
|
||||
else if(station_was_nuked)
|
||||
feedback_set_details("round_end_result","halfwin - nuke")
|
||||
SSblackbox.set_details("round_end_result","halfwin - nuke")
|
||||
to_chat(world, "<FONT size = 3><B>Partial Win: The station has been destroyed!</B></FONT>")
|
||||
to_chat(world, "<B>Directive 7-12 has been successfully carried out, preventing the Blob from spreading.</B>")
|
||||
log_game("Blob mode completed with a tie (station destroyed).")
|
||||
@@ -36,7 +36,7 @@
|
||||
SSticker.news_report = BLOB_NUKE
|
||||
|
||||
else if(!GLOB.blob_cores.len)
|
||||
feedback_set_details("round_end_result","loss - blob eliminated")
|
||||
SSblackbox.set_details("round_end_result","loss - blob eliminated")
|
||||
to_chat(world, "<FONT size = 3><B>The staff has won!</B></FONT>")
|
||||
to_chat(world, "<B>The alien organism has been eradicated from the station!</B>")
|
||||
log_game("Blob mode completed with a crew victory.")
|
||||
|
||||
@@ -254,19 +254,19 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
for(var/datum/objective/objective in changeling.objectives)
|
||||
if(objective.check_completion())
|
||||
text += "<br><b>Objective #[count]</b>: [objective.explanation_text] <font color='green'><b>Success!</b></font>"
|
||||
feedback_add_details("changeling_objective","[objective.type]|SUCCESS")
|
||||
SSblackbox.add_details("changeling_objective","[objective.type]|SUCCESS")
|
||||
else
|
||||
text += "<br><b>Objective #[count]</b>: [objective.explanation_text] <span class='danger'>Fail.</span>"
|
||||
feedback_add_details("changeling_objective","[objective.type]|FAIL")
|
||||
SSblackbox.add_details("changeling_objective","[objective.type]|FAIL")
|
||||
changelingwin = 0
|
||||
count++
|
||||
|
||||
if(changelingwin)
|
||||
text += "<br><font color='green'><b>The changeling was successful!</b></font>"
|
||||
feedback_add_details("changeling_success","SUCCESS")
|
||||
SSblackbox.add_details("changeling_success","SUCCESS")
|
||||
else
|
||||
text += "<br><span class='boldannounce'>The changeling has failed.</span>"
|
||||
feedback_add_details("changeling_success","FAIL")
|
||||
SSblackbox.add_details("changeling_success","FAIL")
|
||||
text += "<br>"
|
||||
|
||||
to_chat(world, text)
|
||||
|
||||
@@ -13,15 +13,13 @@
|
||||
var/req_dna = 0 //amount of dna needed to use this ability. Changelings always have atleast 1
|
||||
var/req_human = 0 //if you need to be human to use this ability
|
||||
var/req_stat = CONSCIOUS // CONSCIOUS, UNCONSCIOUS or DEAD
|
||||
var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss.
|
||||
var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet.
|
||||
var/always_keep = 0 // important for abilities like revive that screw you if you lose them.
|
||||
var/ignores_fakedeath = FALSE // usable with the FAKEDEATH flag
|
||||
|
||||
|
||||
/obj/effect/proc_holder/changeling/proc/on_purchase(mob/user, is_respec)
|
||||
if(!is_respec)
|
||||
feedback_add_details("changeling_power_purchase",name)
|
||||
SSblackbox.add_details("changeling_power_purchase",name)
|
||||
|
||||
/obj/effect/proc_holder/changeling/proc/on_refund(mob/user)
|
||||
return
|
||||
@@ -37,9 +35,9 @@
|
||||
return
|
||||
var/datum/changeling/c = user.mind.changeling
|
||||
if(sting_action(user, target))
|
||||
feedback_add_details("changeling_powers",name)
|
||||
SSblackbox.add_details("changeling_powers",name)
|
||||
sting_feedback(user, target)
|
||||
take_chemical_cost(c)
|
||||
c.chem_charges -= chemical_cost
|
||||
|
||||
/obj/effect/proc_holder/changeling/proc/sting_action(mob/user, mob/target)
|
||||
return 0
|
||||
@@ -47,10 +45,6 @@
|
||||
/obj/effect/proc_holder/changeling/proc/sting_feedback(mob/user, mob/target)
|
||||
return 0
|
||||
|
||||
/obj/effect/proc_holder/changeling/proc/take_chemical_cost(datum/changeling/changeling)
|
||||
changeling.chem_charges -= chemical_cost
|
||||
changeling.geneticdamage += genetic_damage
|
||||
|
||||
//Fairly important to remember to return 1 on success >.<
|
||||
/obj/effect/proc_holder/changeling/proc/can_sting(mob/user, mob/target)
|
||||
if(!ishuman(user) && !ismonkey(user)) //typecast everything from mob to carbon from this point onwards
|
||||
@@ -71,9 +65,6 @@
|
||||
if((user.status_flags & FAKEDEATH) && (!ignores_fakedeath))
|
||||
to_chat(user, "<span class='warning'>We are incapacitated.</span>")
|
||||
return 0
|
||||
if(c.geneticdamage > max_genetic_damage)
|
||||
to_chat(user, "<span class='warning'>Our genomes are still reassembling. We need time to recover first.</span>")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
//used in /mob/Stat()
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
mind.changeling.purchasedpowers+=S
|
||||
S.on_purchase(src, is_respec)
|
||||
if(is_respec)
|
||||
feedback_add_details("changeling_power_purchase","Readapt")
|
||||
SSblackbox.add_details("changeling_power_purchase","Readapt")
|
||||
|
||||
var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste
|
||||
if(ishuman(C))
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
chemical_cost = 0
|
||||
dna_cost = 0
|
||||
req_human = 1
|
||||
max_genetic_damage = 100
|
||||
|
||||
/obj/effect/proc_holder/changeling/absorbDNA/can_sting(mob/living/carbon/user)
|
||||
if(!..())
|
||||
@@ -42,13 +41,13 @@
|
||||
to_chat(target, "<span class='userdanger'>You feel a sharp stabbing pain!</span>")
|
||||
target.take_overall_damage(40)
|
||||
|
||||
feedback_add_details("changeling_powers","Absorb DNA|[i]")
|
||||
SSblackbox.add_details("changeling_powers","Absorb DNA|[i]")
|
||||
if(!do_mob(user, target, 150))
|
||||
to_chat(user, "<span class='warning'>Our absorption of [target] has been interrupted!</span>")
|
||||
changeling.isabsorbing = 0
|
||||
return
|
||||
|
||||
feedback_add_details("changeling_powers","Absorb DNA|4")
|
||||
SSblackbox.add_details("changeling_powers","Absorb DNA|4")
|
||||
user.visible_message("<span class='danger'>[user] sucks the fluids from [target]!</span>", "<span class='notice'>We have absorbed [target].</span>")
|
||||
to_chat(target, "<span class='userdanger'>You are absorbed by the changeling!</span>")
|
||||
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
chemical_cost = 30 //High cost to prevent spam
|
||||
dna_cost = 2
|
||||
req_human = 1
|
||||
genetic_damage = 10
|
||||
max_genetic_damage = 0
|
||||
|
||||
|
||||
/obj/effect/proc_holder/changeling/biodegrade/sting_action(mob/living/carbon/human/user)
|
||||
var/used = FALSE // only one form of shackles removed per use
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
dna_cost = 2
|
||||
chemical_cost = 25
|
||||
req_human = 1
|
||||
genetic_damage = 10
|
||||
max_genetic_damage = 50
|
||||
|
||||
|
||||
/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user)
|
||||
var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
dna_cost = 0
|
||||
req_dna = 1
|
||||
req_stat = DEAD
|
||||
max_genetic_damage = 100
|
||||
|
||||
|
||||
//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay.
|
||||
/obj/effect/proc_holder/changeling/fakedeath/sting_action(mob/living/user)
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
name = "Human Form"
|
||||
desc = "We change into a human."
|
||||
chemical_cost = 5
|
||||
genetic_damage = 3
|
||||
req_dna = 1
|
||||
max_genetic_damage = 3
|
||||
|
||||
|
||||
//Transform into a human.
|
||||
/obj/effect/proc_holder/changeling/humanform/sting_action(mob/living/carbon/user)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
desc = "We debase ourselves and become lesser. We become a monkey."
|
||||
chemical_cost = 5
|
||||
dna_cost = 1
|
||||
genetic_damage = 3
|
||||
req_human = 1
|
||||
|
||||
//Transform into a monkey.
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
chemical_cost = 0
|
||||
dna_cost = 0
|
||||
req_human = 1
|
||||
max_genetic_damage = 100
|
||||
|
||||
/obj/effect/proc_holder/changeling/linglink/can_sting(mob/living/carbon/user)
|
||||
if(!..())
|
||||
@@ -56,7 +55,7 @@
|
||||
to_chat(target, "<font color=#800040><span class='boldannounce'>You can now communicate in the changeling hivemind, say \":g message\" to communicate!</span>")
|
||||
target.reagents.add_reagent("salbutamol", 40) // So they don't choke to death while you interrogate them
|
||||
sleep(1800)
|
||||
feedback_add_details("changeling_powers","Hivemind Link|[i]")
|
||||
SSblackbox.add_details("changeling_powers","Hivemind Link|[i]")
|
||||
if(!do_mob(user, target, 20))
|
||||
to_chat(user, "<span class='warning'>Our link with [target] has ended!</span>")
|
||||
changeling.islinking = 0
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
helptext = "Yell at Miauw and/or Perakp"
|
||||
chemical_cost = 1000
|
||||
dna_cost = -1
|
||||
genetic_damage = 1000
|
||||
|
||||
var/silent = FALSE
|
||||
var/weapon_type
|
||||
@@ -67,7 +66,6 @@
|
||||
helptext = "Yell at Miauw and/or Perakp"
|
||||
chemical_cost = 1000
|
||||
dna_cost = -1
|
||||
genetic_damage = 1000
|
||||
|
||||
var/helmet_type = /obj/item
|
||||
var/suit_type = /obj/item
|
||||
@@ -89,7 +87,7 @@
|
||||
return 1
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(istype(H.wear_suit, suit_type) || istype(H.head, helmet_type))
|
||||
H.visible_message("<span class='warning'>[H] casts off their [suit_name_simple]!</span>", "<span class='warning'>We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]</span>", "<span class='italics'>You hear the organic matter ripping and tearing!</span>")
|
||||
H.visible_message("<span class='warning'>[H] casts off their [suit_name_simple]!</span>", "<span class='warning'>We cast off our [suit_name_simple].</span>", "<span class='italics'>You hear the organic matter ripping and tearing!</span>")
|
||||
H.temporarilyRemoveItemFromInventory(H.head, TRUE) //The qdel on dropped() takes care of it
|
||||
H.temporarilyRemoveItemFromInventory(H.wear_suit, TRUE)
|
||||
H.update_inv_wear_suit()
|
||||
@@ -100,7 +98,6 @@
|
||||
H.add_splatter_floor()
|
||||
playsound(H.loc, 'sound/effects/splat.ogg', 50, 1) //So real sounds
|
||||
|
||||
changeling.geneticdamage += genetic_damage //Casting off a space suit leaves you weak for a few seconds.
|
||||
changeling.chem_recharge_slowdown -= recharge_slowdown
|
||||
return 1
|
||||
|
||||
@@ -139,9 +136,7 @@
|
||||
helptext = "We may retract our armblade in the same manner as we form it. Cannot be used while in lesser form."
|
||||
chemical_cost = 20
|
||||
dna_cost = 2
|
||||
genetic_damage = 10
|
||||
req_human = 1
|
||||
max_genetic_damage = 20
|
||||
weapon_type = /obj/item/weapon/melee/arm_blade
|
||||
weapon_name_simple = "blade"
|
||||
|
||||
@@ -217,9 +212,7 @@
|
||||
and Harm will stun it, and stab it if we're also holding a sharp weapon. Cannot be used while in lesser form."
|
||||
chemical_cost = 10
|
||||
dna_cost = 2
|
||||
genetic_damage = 5
|
||||
req_human = 1
|
||||
max_genetic_damage = 10
|
||||
weapon_type = /obj/item/weapon/gun/magic/tentacle
|
||||
weapon_name_simple = "tentacle"
|
||||
silent = TRUE
|
||||
@@ -381,9 +374,7 @@
|
||||
helptext = "Organic tissue cannot resist damage forever; the shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form."
|
||||
chemical_cost = 20
|
||||
dna_cost = 1
|
||||
genetic_damage = 12
|
||||
req_human = 1
|
||||
max_genetic_damage = 20
|
||||
|
||||
weapon_type = /obj/item/weapon/shield/changeling
|
||||
weapon_name_simple = "shield"
|
||||
@@ -430,12 +421,10 @@
|
||||
/obj/effect/proc_holder/changeling/suit/organic_space_suit
|
||||
name = "Organic Space Suit"
|
||||
desc = "We grow an organic suit to protect ourselves from space exposure."
|
||||
helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Retreating the suit damages our genomes. Cannot be used in lesser form."
|
||||
helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Cannot be used in lesser form."
|
||||
chemical_cost = 20
|
||||
dna_cost = 2
|
||||
genetic_damage = 8
|
||||
req_human = 1
|
||||
max_genetic_damage = 20
|
||||
|
||||
suit_type = /obj/item/clothing/suit/space/changeling
|
||||
helmet_type = /obj/item/clothing/head/helmet/space/changeling
|
||||
@@ -477,12 +466,10 @@
|
||||
/obj/effect/proc_holder/changeling/suit/armor
|
||||
name = "Chitinous Armor"
|
||||
desc = "We turn our skin into tough chitin to protect us from damage."
|
||||
helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form."
|
||||
helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form."
|
||||
chemical_cost = 20
|
||||
dna_cost = 1
|
||||
genetic_damage = 11
|
||||
req_human = 1
|
||||
max_genetic_damage = 20
|
||||
recharge_slowdown = 0.25
|
||||
|
||||
suit_type = /obj/item/clothing/suit/armor/changeling
|
||||
|
||||
@@ -40,10 +40,9 @@
|
||||
return
|
||||
if(!AStar(user, target.loc, /turf/proc/Distance, user.mind.changeling.sting_range, simulated_only = 0))
|
||||
return
|
||||
if(target.mind && target.mind.changeling)
|
||||
sting_feedback(user,target)
|
||||
take_chemical_cost(user.mind.changeling)
|
||||
return
|
||||
if(target.mind && target.mind.changeling)
|
||||
sting_feedback(user, target)
|
||||
user.mind.changeling.chem_charges -= chemical_cost
|
||||
return 1
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/sting_feedback(mob/user, mob/target)
|
||||
@@ -62,7 +61,6 @@
|
||||
sting_icon = "sting_transform"
|
||||
chemical_cost = 40
|
||||
dna_cost = 3
|
||||
genetic_damage = 100
|
||||
var/datum/changelingprofile/selected_dna = null
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/transformation/Click()
|
||||
@@ -117,8 +115,6 @@
|
||||
sting_icon = "sting_armblade"
|
||||
chemical_cost = 20
|
||||
dna_cost = 1
|
||||
genetic_damage = 20
|
||||
max_genetic_damage = 10
|
||||
|
||||
/obj/item/weapon/melee/arm_blade/false
|
||||
desc = "A grotesque mass of flesh that used to be your arm. Although it looks dangerous at first, you can tell it's actually quite dull and useless."
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
dna_cost = 0
|
||||
req_dna = 1
|
||||
req_human = 1
|
||||
max_genetic_damage = 3
|
||||
|
||||
/obj/item/clothing/glasses/changeling
|
||||
name = "flesh"
|
||||
|
||||
@@ -198,7 +198,7 @@ Credit where due:
|
||||
var/datum/game_mode/clockwork_cult/C = SSticker.mode
|
||||
if(C.check_clockwork_victory())
|
||||
text += "<span class='large_brass'><b>Ratvar's servants have succeeded in fulfilling His goals!</b></span>"
|
||||
feedback_set_details("round_end_result", "win - servants completed their objective (summon ratvar)")
|
||||
SSblackbox.set_details("round_end_result", "win - servants completed their objective (summon ratvar)")
|
||||
else
|
||||
var/half_victory = FALSE
|
||||
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = locate() in GLOB.all_clockwork_objects
|
||||
@@ -207,10 +207,10 @@ Credit where due:
|
||||
if(half_victory)
|
||||
text += "<span class='large_brass'><b>The crew escaped before Ratvar could rise, but the gateway \
|
||||
was successfully constructed!</b></span>"
|
||||
feedback_set_details("round_end_result", "halfwin - servants constructed the gateway but their objective was not completed (summon ratvar)")
|
||||
SSblackbox.set_details("round_end_result", "halfwin - servants constructed the gateway but their objective was not completed (summon ratvar)")
|
||||
else
|
||||
text += "<span class='userdanger'>Ratvar's servants have failed!</span>"
|
||||
feedback_set_details("round_end_result", "loss - servants failed their objective (summon ratvar)")
|
||||
SSblackbox.set_details("round_end_result", "loss - servants failed their objective (summon ratvar)")
|
||||
text += "<br><b>The servants' objective was:</b> <br>[CLOCKCULT_OBJECTIVE]"
|
||||
text += "<br>Ratvar's servants had <b>[GLOB.clockwork_caches]</b> Tinkerer's Caches."
|
||||
text += "<br><b>Construction Value(CV)</b> was: <b>[GLOB.clockwork_construction_value]</b>"
|
||||
|
||||
@@ -54,8 +54,11 @@
|
||||
clockwork_desc = "A sigil that will stun the next non-Servant to cross it."
|
||||
icon_state = "sigildull"
|
||||
layer = HIGH_SIGIL_LAYER
|
||||
alpha = 60
|
||||
alpha = 75
|
||||
color = "#FAE48C"
|
||||
light_range = 1.4
|
||||
light_power = 1
|
||||
light_color = "#FAE48C"
|
||||
sigil_name = "Sigil of Transgression"
|
||||
|
||||
/obj/effect/clockwork/sigil/transgression/sigil_effects(mob/living/L)
|
||||
@@ -93,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)
|
||||
@@ -202,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))
|
||||
@@ -214,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))
|
||||
@@ -228,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)
|
||||
@@ -265,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
|
||||
@@ -299,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))
|
||||
@@ -369,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)
|
||||
|
||||
@@ -15,9 +15,8 @@
|
||||
var/obj/effect/clockwork/spatial_gateway/linked_gateway //The gateway linked to this one
|
||||
var/timerid
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/New()
|
||||
..()
|
||||
update_light()
|
||||
/obj/effect/clockwork/spatial_gateway/Initialize()
|
||||
. = ..()
|
||||
addtimer(CALLBACK(src, .proc/check_setup), 1)
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/Destroy()
|
||||
@@ -99,12 +98,12 @@
|
||||
if(severity == 1 && uses)
|
||||
uses = 0
|
||||
visible_message("<span class='warning'>[src] is disrupted!</span>")
|
||||
animate(src, alpha = 0, transform = matrix()*2, time = 10)
|
||||
animate(src, alpha = 0, transform = matrix()*2, time = 10, flags = ANIMATION_END_NOW)
|
||||
deltimer(timerid)
|
||||
timerid = QDEL_IN(src, 10)
|
||||
linked_gateway.uses = 0
|
||||
linked_gateway.visible_message("<span class='warning'>[linked_gateway] is disrupted!</span>")
|
||||
animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 10)
|
||||
animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 10, flags = ANIMATION_END_NOW)
|
||||
deltimer(linked_gateway.timerid)
|
||||
linked_gateway.timerid = QDEL_IN(linked_gateway, 10)
|
||||
return TRUE
|
||||
@@ -131,9 +130,9 @@
|
||||
playsound(src, 'sound/effects/EMPulse.ogg', 50, 1)
|
||||
playsound(linked_gateway, 'sound/effects/EMPulse.ogg', 50, 1)
|
||||
transform = matrix() * 1.5
|
||||
animate(src, transform = matrix() / 1.5, time = 10)
|
||||
animate(src, transform = matrix() / 1.5, time = 10, flags = ANIMATION_END_NOW)
|
||||
linked_gateway.transform = matrix() * 1.5
|
||||
animate(linked_gateway, transform = matrix() / 1.5, time = 10)
|
||||
animate(linked_gateway, transform = matrix() / 1.5, time = 10, flags = ANIMATION_END_NOW)
|
||||
A.forceMove(get_turf(linked_gateway))
|
||||
if(!no_cost)
|
||||
uses = max(0, uses - 1)
|
||||
@@ -181,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
|
||||
|
||||
@@ -326,13 +326,19 @@
|
||||
if(production_time != SLAB_PRODUCTION_TIME+SLAB_SLOWDOWN_MAXIMUM)
|
||||
production_text_addon = ", which increases for each human or silicon servant above <b>[SCRIPT_SERVANT_REQ]</b>"
|
||||
production_time = production_time/600
|
||||
var/production_text = "<b>[round(production_time)] minute\s"
|
||||
var/list/production_text
|
||||
if(round(production_time))
|
||||
production_text = list("<b>[round(production_time)] minute\s")
|
||||
if(production_time != round(production_time))
|
||||
production_time -= round(production_time)
|
||||
production_time *= 60
|
||||
production_text += " and [round(production_time, 1)] second\s"
|
||||
if(!LAZYLEN(production_text))
|
||||
production_text = list("<b>[round(production_time, 1)] second\s")
|
||||
else
|
||||
production_text += " and [round(production_time, 1)] second\s"
|
||||
production_text += "</b>"
|
||||
production_text += production_text_addon
|
||||
production_text = production_text.Join()
|
||||
|
||||
textlist = list("<font color=#BE8700 size=3><b><center>Chetr nyy hagehguf-naq-ubabe Ratvar.</center></b></font><br>\
|
||||
\
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -86,7 +86,7 @@ Judgement: 12 servants, 5 caches, 300 CV, and any existing AIs are converted or
|
||||
else
|
||||
successful = TRUE
|
||||
if(slab && !slab.no_cost && !GLOB.ratvar_awakens) //if the slab exists and isn't debug and ratvar isn't up, log the scripture as being used
|
||||
feedback_add_details("clockcult_scripture_recited", name)
|
||||
SSblackbox.add_details("clockcult_scripture_recited", name)
|
||||
if(slab)
|
||||
slab.busy = null
|
||||
qdel(src)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
It will penetrate mindshield implants once before disappearing."
|
||||
invocations = list("Divinity, enslave...", "...all who trespass here!")
|
||||
channel_time = 70
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 4, GEIS_CAPACITOR = 2, HIEROPHANT_ANSIBLE = 2)
|
||||
whispered = TRUE
|
||||
object_path = /obj/effect/clockwork/sigil/submission/accession
|
||||
prevent_path = /obj/effect/clockwork/sigil/submission
|
||||
@@ -32,7 +32,7 @@
|
||||
It grows faster to invoke with more adjacent Servants."
|
||||
invocations = list("Shield us...", "...with the...", "... fragments of Engine!")
|
||||
channel_time = 100
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 4, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
|
||||
usage_tip = "This scripture will replace all weaker armor worn by affected Servants."
|
||||
tier = SCRIPTURE_APPLICATION
|
||||
multiple_invokers_used = TRUE
|
||||
@@ -99,7 +99,7 @@
|
||||
If it remains close to you, you will gradually regain health up to a low amount, but it will die if it goes too far from you."
|
||||
invocations = list("Fright's will...", "...call forth...")
|
||||
channel_time = 100
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 2)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, GEIS_CAPACITOR = 4)
|
||||
usage_tip = "Marauders are useful as personal bodyguards and frontline warriors."
|
||||
tier = SCRIPTURE_APPLICATION
|
||||
primary_component = GEIS_CAPACITOR
|
||||
@@ -160,7 +160,7 @@
|
||||
and exceptional speed, though taking damage will temporarily slow it down."
|
||||
invocations = list("Call forth...", "...the soldiers of Armorer.")
|
||||
channel_time = 80
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, REPLICANT_ALLOY = 2)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 4)
|
||||
object_path = /obj/structure/destructible/clockwork/shell/fragment
|
||||
creator_message = "<span class='brass'>You form an anima fragment, a powerful soul vessel receptacle.</span>"
|
||||
observer_message = "<span class='warning'>The slab disgorges a puddle of black metal that expands and forms into a strange shell!</span>"
|
||||
@@ -179,7 +179,7 @@
|
||||
desc = "Places a sigil that stores energy to power clockwork structures."
|
||||
invocations = list("Divinity...", "...power our creations!")
|
||||
channel_time = 70
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 2)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 2, GEIS_CAPACITOR = 2, HIEROPHANT_ANSIBLE = 4)
|
||||
whispered = TRUE
|
||||
object_path = /obj/effect/clockwork/sigil/transmission
|
||||
creator_message = "<span class='brass'>A sigil silently appears below you. It will automatically power clockwork structures near it.</span>"
|
||||
@@ -199,7 +199,7 @@
|
||||
desc = "Creates a clockwork totem that sabotages nearby machinery and funnels drained power into nearby Sigils of Transmission or the area's APC."
|
||||
invocations = list("May this totem...", "...shroud the false suns!")
|
||||
channel_time = 80
|
||||
consumed_components = list(BELLIGERENT_EYE = 3, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 5, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
|
||||
object_path = /obj/structure/destructible/clockwork/powered/interdiction_lens
|
||||
creator_message = "<span class='brass'>You form an interdiction lens, which disrupts cameras and radios and drains power.</span>"
|
||||
observer_message = "<span class='warning'>A brass totem rises from the ground, a purple gem appearing in its center!</span>"
|
||||
@@ -221,7 +221,7 @@
|
||||
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."
|
||||
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
|
||||
channel_time = 80
|
||||
consumed_components = list(GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
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>"
|
||||
observer_message = "<span class='warning'>A two-pronged machine rises from the ground!</span>"
|
||||
@@ -244,7 +244,7 @@
|
||||
and there is at least one existing cache."
|
||||
invocations = list("May this generator...", "...collect Engine parts that yet hold greatness!")
|
||||
channel_time = 80
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 3)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 5)
|
||||
object_path = /obj/structure/destructible/clockwork/powered/tinkerers_daemon
|
||||
creator_message = "<span class='brass'>You form a tinkerer's daemon which can rapidly collect components at a power cost.</span>"
|
||||
invokers_required = 2
|
||||
@@ -278,7 +278,7 @@
|
||||
desc = "Creates a clockwork obelisk that can broadcast messages over the Hierophant Network or open a Spatial Gateway to any living Servant or clockwork obelisk."
|
||||
invocations = list("May this obelisk...", "...take us to all places!")
|
||||
channel_time = 80
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 3)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, HIEROPHANT_ANSIBLE = 5)
|
||||
object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
|
||||
creator_message = "<span class='brass'>You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways.</span>"
|
||||
observer_message = "<span class='warning'>A brass obelisk appears hanging in midair!</span>"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -272,7 +259,7 @@
|
||||
var/static/prev_cost = 0
|
||||
|
||||
/datum/clockwork_scripture/create_object/tinkerers_cache/creation_update()
|
||||
var/cache_cost_increase = min(round(GLOB.clockwork_caches*0.25), 5)
|
||||
var/cache_cost_increase = min(round(GLOB.clockwork_caches*0.4), 10)
|
||||
if(cache_cost_increase != prev_cost)
|
||||
prev_cost = cache_cost_increase
|
||||
consumed_components = list(BELLIGERENT_EYE = 0, VANGUARD_COGWHEEL = 0, GEIS_CAPACITOR = 0, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 0)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
desc = "Taps the limitless power of Inath-neq, one of Ratvar's four generals. The benevolence of Inath-Neq will grant complete invulnerability to all Servants in range for fifteen seconds."
|
||||
invocations = list("I call upon you, Vanguard!!", "Let the Resonant Cogs turn once more!!", "Grant me and my allies the strength to vanquish our foes!!")
|
||||
channel_time = 100
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 4, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 10, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 3)
|
||||
usage_tip = "Servants affected by this scripture are only weak to things that outright destroy bodies, such as bombs or the singularity."
|
||||
tier = SCRIPTURE_REVENANT
|
||||
primary_component = VANGUARD_COGWHEEL
|
||||
@@ -44,7 +44,7 @@
|
||||
for all non-servant humans on the same z-level as them. The power of this scripture falls off somewhat with distance, and certain things may reduce its effects."
|
||||
invocations = list("I call upon you, Fright!!", "Let your power shatter the sanity of the weak-minded!!", "Let your tendrils hold sway over all!!")
|
||||
channel_time = 150
|
||||
consumed_components = list(BELLIGERENT_EYE = 3, VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 6, HIEROPHANT_ANSIBLE = 3)
|
||||
consumed_components = list(BELLIGERENT_EYE = 6, VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 10, HIEROPHANT_ANSIBLE = 6)
|
||||
usage_tip = "Causes brain damage, hallucinations, confusion, and dizziness in massive amounts."
|
||||
tier = SCRIPTURE_REVENANT
|
||||
sort_priority = 3
|
||||
@@ -108,7 +108,7 @@
|
||||
clockwork proselytizers will charge very rapidly."
|
||||
invocations = list("I call upon you, Armorer!!", "Let your machinations reign on this miserable station!!", "Let your power flow through the tools of your master!!")
|
||||
channel_time = 150
|
||||
consumed_components = list(BELLIGERENT_EYE = 3, VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 6)
|
||||
consumed_components = list(BELLIGERENT_EYE = 6, VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 6, REPLICANT_ALLOY = 10)
|
||||
usage_tip = "Ocular wardens will become empowered, clockwork proselytizers will require no alloy, tinkerer's daemons will produce twice as quickly, \
|
||||
and interdiction lenses, mania motors, tinkerer's daemons, and clockwork obelisks will all require no power."
|
||||
tier = SCRIPTURE_REVENANT
|
||||
@@ -153,7 +153,7 @@
|
||||
will be struck by devastating lightning bolts."
|
||||
invocations = list("I call upon you, Amperage!!", "Let your energy flow through me!!", "Let your boundless power shatter stars!!")
|
||||
channel_time = 100
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 4)
|
||||
consumed_components = list(BELLIGERENT_EYE = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 10)
|
||||
usage_tip = "Struck targets will also be knocked down for about sixteen seconds."
|
||||
tier = SCRIPTURE_REVENANT
|
||||
primary_component = HIEROPHANT_ANSIBLE
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
desc = "Forms an automatic short-range turret which will automatically attack nearby unrestrained non-Servants that can see it."
|
||||
invocations = list("Guardians...", "...of the Engine...", "...defend us!")
|
||||
channel_time = 120
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, REPLICANT_ALLOY = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, REPLICANT_ALLOY = 1)
|
||||
object_path = /obj/structure/destructible/clockwork/ocular_warden
|
||||
creator_message = "<span class='brass'>You form an ocular warden, which will automatically attack nearby unrestrained non-Servants that can see it.</span>"
|
||||
observer_message = "<span class='warning'>A brass eye takes shape and slowly rises into the air, its red iris glaring!</span>"
|
||||
@@ -36,7 +36,7 @@
|
||||
desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt proselytizer."
|
||||
invocations = list("Call forth...", "...the workers of Armorer.")
|
||||
channel_time = 60
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, HIEROPHANT_ANSIBLE = 1)
|
||||
object_path = /obj/structure/destructible/clockwork/shell/cogscarab
|
||||
creator_message = "<span class='brass'>You form a cogscarab, a constructor soul vessel receptacle.</span>"
|
||||
observer_message = "<span class='warning'>The slab disgorges a puddle of black metal that contracts and forms into a strange shell!</span>"
|
||||
@@ -56,7 +56,7 @@
|
||||
Matrices have drained from non-Servants. Dead Servants can be revived by this sigil if there is vitality equal to the target Servant's non-oxygen damage."
|
||||
invocations = list("Divinity...", "...steal their life...", "...for these shells!")
|
||||
channel_time = 60
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 2)
|
||||
whispered = TRUE
|
||||
object_path = /obj/effect/clockwork/sigil/vitality
|
||||
creator_message = "<span class='brass'>A vitality matrix appears below you. It will drain life from non-Servants and heal Servants that cross it.</span>"
|
||||
@@ -77,7 +77,7 @@
|
||||
chant_invocations = list("Mend our dents!", "Heal our scratches!", "Repair our gears!")
|
||||
chant_amount = 10
|
||||
chant_interval = 20
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, REPLICANT_ALLOY = 1)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 1)
|
||||
usage_tip = "This is a very effective way to rapidly reinforce a base after an attack."
|
||||
tier = SCRIPTURE_SCRIPT
|
||||
primary_component = VANGUARD_COGWHEEL
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -187,7 +188,7 @@
|
||||
desc = "Places a luminous sigil that will enslave any valid beings standing on it after a time."
|
||||
invocations = list("Divinity, enlighten...", "...those who trespass here!")
|
||||
channel_time = 60
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 2)
|
||||
whispered = TRUE
|
||||
object_path = /obj/effect/clockwork/sigil/submission
|
||||
creator_message = "<span class='brass'>A luminous sigil appears below you. The next non-servant to cross it will be enslaved after a brief time if they do not move.</span>"
|
||||
@@ -207,7 +208,7 @@
|
||||
desc = "Forms an ancient positronic brain with an overriding directive to serve Ratvar."
|
||||
invocations = list("Herd the souls of...", "...the blasphemous damned!")
|
||||
channel_time = 30
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 1)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 2)
|
||||
whispered = TRUE
|
||||
object_path = /obj/item/device/mmi/posibrain/soul_vessel
|
||||
creator_message = "<span class='brass'>You form a soul vessel, which can be used in-hand to attract spirits, or used on an unconscious or dead human to extract their consciousness.</span>"
|
||||
@@ -227,7 +228,7 @@
|
||||
desc = "Forms a device that, when used on certain objects, converts them into their Ratvarian equivalents. It requires power to function."
|
||||
invocations = list("With this device...", "...his presence shall be made known.")
|
||||
channel_time = 20
|
||||
consumed_components = list(GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 1)
|
||||
consumed_components = list(GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 2)
|
||||
whispered = TRUE
|
||||
object_path = /obj/item/clockwork/clockwork_proselytizer/preloaded
|
||||
creator_message = "<span class='brass'>You form a clockwork proselytizer.</span>"
|
||||
@@ -248,7 +249,7 @@
|
||||
vanish three minutes after being summoned."
|
||||
invocations = list("Grant me...", "...the might of brass!")
|
||||
channel_time = 20
|
||||
consumed_components = list(REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 1)
|
||||
whispered = TRUE
|
||||
usage_tip = "You can impale human targets with the spear by pulling them, then attacking. Throwing the spear at a mob will do massive damage and stun them, but break the spear."
|
||||
tier = SCRIPTURE_SCRIPT
|
||||
@@ -307,7 +308,7 @@
|
||||
Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration."
|
||||
invocations = list("Spatial Gateway...", "...activate!")
|
||||
channel_time = 80
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 2)
|
||||
multiple_invokers_used = TRUE
|
||||
multiple_invokers_optional = TRUE
|
||||
usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal."
|
||||
@@ -356,7 +357,7 @@
|
||||
chant_invocations = list("Use charge to kill!", "Slay with power!", "Hunt with energy!")
|
||||
chant_amount = 4
|
||||
chant_interval = 5
|
||||
consumed_components = list(GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 2)
|
||||
usage_tip = "Though it requires you to stand still, this scripture can do massive damage."
|
||||
tier = SCRIPTURE_SCRIPT
|
||||
primary_component = HIEROPHANT_ANSIBLE
|
||||
|
||||
@@ -44,50 +44,57 @@
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/attack_hand(mob/living/user)
|
||||
if(!is_servant_of_ratvar(user) || total_accessable_power() < hierophant_cost || !anchored)
|
||||
to_chat(user, "<span class='warning'>You place your hand on the obelisk, but it doesn't react.</span>")
|
||||
to_chat(user, "<span class='warning'>You place your hand on [src], but it doesn't react.</span>")
|
||||
return
|
||||
var/choice = alert(user,"You place your hand on the obelisk...",,"Hierophant Broadcast","Spatial Gateway","Cancel")
|
||||
var/choice = alert(user,"You place your hand on [src]...",,"Hierophant Broadcast","Spatial Gateway","Cancel")
|
||||
switch(choice)
|
||||
if("Hierophant Broadcast")
|
||||
if(active)
|
||||
to_chat(user, "<span class='warning'>The obelisk is sustaining a gateway and cannot broadcast!</span>")
|
||||
to_chat(user, "<span class='warning'>[src] is sustaining a gateway and cannot broadcast!</span>")
|
||||
return
|
||||
if(!user.can_speak_vocal())
|
||||
to_chat(user, "<span class='warning'>You cannot speak through the obelisk!</span>")
|
||||
to_chat(user, "<span class='warning'>You cannot speak through [src]!</span>")
|
||||
return
|
||||
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)
|
||||
to_chat(user, "<span class='warning'>[src] is no longer secured!</span>")
|
||||
return FALSE
|
||||
if(active)
|
||||
to_chat(user, "<span class='warning'>The obelisk is sustaining a gateway and cannot broadcast!</span>")
|
||||
return
|
||||
if(!try_use_power(hierophant_cost))
|
||||
to_chat(user, "<span class='warning'>The obelisk lacks the power to broadcast!</span>")
|
||||
to_chat(user, "<span class='warning'>[src] is sustaining a gateway and cannot broadcast!</span>")
|
||||
return
|
||||
if(!user.can_speak_vocal())
|
||||
to_chat(user, "<span class='warning'>You cannot speak through the obelisk!</span>")
|
||||
to_chat(user, "<span class='warning'>You cannot speak through [src]!</span>")
|
||||
return
|
||||
if(!try_use_power(hierophant_cost))
|
||||
to_chat(user, "<span class='warning'>[src] lacks the power to broadcast!</span>")
|
||||
return
|
||||
clockwork_say(user, text2ratvar("Hierophant Broadcast, activate! [html_decode(input)]"))
|
||||
titled_hierophant_message(user, input, "big_brass", "large_brass")
|
||||
if("Spatial Gateway")
|
||||
if(active)
|
||||
to_chat(user, "<span class='warning'>The obelisk is already sustaining a gateway!</span>")
|
||||
return
|
||||
if(!try_use_power(gateway_cost))
|
||||
to_chat(user, "<span class='warning'>The obelisk lacks the power to open a gateway!</span>")
|
||||
to_chat(user, "<span class='warning'>[src] is already sustaining a gateway!</span>")
|
||||
return
|
||||
if(!user.can_speak_vocal())
|
||||
to_chat(user, "<span class='warning'>You need to be able to speak to open a gateway!</span>")
|
||||
return
|
||||
if(procure_gateway(user, round(100 * get_efficiency_mod(), 1), round(5 * get_efficiency_mod(), 1), 1) && !active)
|
||||
clockwork_say(user, text2ratvar("Spatial Gateway, activate!"))
|
||||
else
|
||||
return_power(gateway_cost)
|
||||
if(!try_use_power(gateway_cost))
|
||||
to_chat(user, "<span class='warning'>[src] lacks the power to open a gateway!</span>")
|
||||
return
|
||||
if(procure_gateway(user, round(100 * get_efficiency_mod(), 1), round(5 * get_efficiency_mod(), 1), 1))
|
||||
process()
|
||||
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
|
||||
|
||||
/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
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert")
|
||||
var/area/A = get_area(src)
|
||||
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [A.name] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
|
||||
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency..proc/request, null, 0)
|
||||
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency..proc/request, null, 0, 0)
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
|
||||
GLOB.ratvar_awakens--
|
||||
@@ -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))
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
var/static/mutable_appearance/component_glow = mutable_appearance('icons/obj/clockwork_objects.dmi', "t_random_component")
|
||||
var/component_id_to_produce
|
||||
var/production_time = 0 //last time we produced a component
|
||||
var/production_cooldown = 120
|
||||
var/production_cooldown = 60
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -218,12 +218,12 @@
|
||||
/datum/game_mode/cult/declare_completion()
|
||||
|
||||
if(!check_cult_victory())
|
||||
feedback_set_details("round_end_result","win - cult win")
|
||||
feedback_set("round_end_result",acolytes_survived)
|
||||
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
|
||||
feedback_set_details("round_end_result","loss - staff stopped the cult")
|
||||
feedback_set("round_end_result",acolytes_survived)
|
||||
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>")
|
||||
|
||||
var/text = ""
|
||||
@@ -236,31 +236,31 @@
|
||||
if("survive")
|
||||
if(!check_survive())
|
||||
explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) <span class='greenannounce'>Success!</span>"
|
||||
feedback_add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]")
|
||||
SSblackbox.add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]")
|
||||
SSticker.news_report = CULT_ESCAPE
|
||||
else
|
||||
explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) <span class='boldannounce'>Fail.</span>"
|
||||
feedback_add_details("cult_objective","cult_survive|FAIL|[acolytes_needed]")
|
||||
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>"
|
||||
feedback_add_details("cult_objective","cult_sacrifice|SUCCESS")
|
||||
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>"
|
||||
feedback_add_details("cult_objective","cult_sacrifice|FAIL")
|
||||
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>"
|
||||
feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED")
|
||||
SSblackbox.add_details("cult_objective","cult_sacrifice|FAIL|GIBBED")
|
||||
if("eldergod")
|
||||
if(!eldergod)
|
||||
explanation = "Summon Nar-Sie. <span class='greenannounce'>Success!</span>"
|
||||
feedback_add_details("cult_objective","cult_narsie|SUCCESS")
|
||||
SSblackbox.add_details("cult_objective","cult_narsie|SUCCESS")
|
||||
SSticker.news_report = CULT_SUMMON
|
||||
else
|
||||
explanation = "Summon Nar-Sie. <span class='boldannounce'>Fail.</span>"
|
||||
feedback_add_details("cult_objective","cult_narsie|FAIL")
|
||||
SSblackbox.add_details("cult_objective","cult_narsie|FAIL")
|
||||
SSticker.news_report = CULT_FAILURE
|
||||
|
||||
text += "<br><B>Objective #[obj_count]</B>: [explanation]"
|
||||
|
||||
@@ -133,7 +133,7 @@ This file contains the arcane tome files.
|
||||
text += "<font color='red'><b>Talisman of Armaments</b></font><br>The Talisman of Arming will equip the user with armored robes, a backpack, an eldritch longsword, an empowered bola, and a pair of boots. Any items that cannot \
|
||||
be equipped will not be summoned. Attacking a fellow cultist with it will instead equip them.<br><br>"
|
||||
|
||||
text += "<font color='red'><b>Talisman of Horrors</b></font><br>The Talisman of Horror must be applied directly to the victim, it will shatter your victim's mind with visions of the endtimes that may incapitate them.<br><br>"
|
||||
text += "<font color='red'><b>Talisman of Horrors</b></font><br>The Talisman of Horror, unlike other talismans, can be applied at range, without the victim noticing. It will cause the victim to have severe hallucinations after a short while.<br><br>"
|
||||
|
||||
text += "<font color='red'><b>Talisman of Shackling</b></font><br>The Talisman of Shackling must be applied directly to the victim, it has 4 uses and cuffs victims with magic shackles that disappear when removed.<br><br>"
|
||||
|
||||
@@ -247,7 +247,7 @@ This file contains the arcane tome files.
|
||||
var/obj/effect/rune/R = new rune_to_scribe(Turf, chosen_keyword)
|
||||
R.add_mob_blood(user)
|
||||
to_chat(user, "<span class='cult'>The [lowertext(R.cultist_name)] rune [R.cultist_desc]</span>")
|
||||
feedback_add_details("cult_runes_scribed", R.cultist_name)
|
||||
SSblackbox.add_details("cult_runes_scribed", R.cultist_name)
|
||||
|
||||
/obj/item/weapon/tome/proc/check_rune_turf(turf/T, mob/user)
|
||||
var/area/A = get_area(T)
|
||||
|
||||
@@ -211,7 +211,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
log_game("Talisman Creation rune failed - already in use")
|
||||
return
|
||||
|
||||
for(var/I in subtypesof(/obj/item/weapon/paper/talisman) - /obj/item/weapon/paper/talisman/malformed - /obj/item/weapon/paper/talisman/supply - /obj/item/weapon/paper/talisman/supply/weak)
|
||||
for(var/I in subtypesof(/obj/item/weapon/paper/talisman) - /obj/item/weapon/paper/talisman/malformed - /obj/item/weapon/paper/talisman/supply - /obj/item/weapon/paper/talisman/supply/weak - /obj/item/weapon/paper/talisman/summon_tome)
|
||||
var/obj/item/weapon/paper/talisman/J = I
|
||||
var/talisman_cult_name = initial(J.cultist_name)
|
||||
if(talisman_cult_name)
|
||||
@@ -633,9 +633,9 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
qdel(src) //delete before pulsing because it's a delay reee
|
||||
empulse(E, 9*invokers.len, 12*invokers.len) // Scales now, from a single room to most of the station depending on # of chanters
|
||||
|
||||
//Rite of Astral Communion: Separates one's spirit from their body. They will take damage while it is active.
|
||||
/obj/effect/rune/astral
|
||||
cultist_name = "Astral Communion"
|
||||
//Rite of Spirit Sight: Separates one's spirit from their body. They will take damage while it is active.
|
||||
/obj/effect/rune/spirit
|
||||
cultist_name = "Spirit Sight"
|
||||
cultist_desc = "severs the link between one's spirit and body. This effect is taxing and one's physical body will take damage while this is active."
|
||||
invocation = "Fwe'sh mah erl nyag r'ya!"
|
||||
icon_state = "7"
|
||||
@@ -644,24 +644,24 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
construct_invoke = 0
|
||||
var/mob/living/affecting = null
|
||||
|
||||
/obj/effect/rune/astral/examine(mob/user)
|
||||
/obj/effect/rune/spirit/examine(mob/user)
|
||||
..()
|
||||
if(affecting)
|
||||
to_chat(user, "<span class='cultitalic'>A translucent field encases [user] above the rune!</span>")
|
||||
|
||||
/obj/effect/rune/astral/can_invoke(mob/living/user)
|
||||
/obj/effect/rune/spirit/can_invoke(mob/living/user)
|
||||
if(rune_in_use)
|
||||
to_chat(user, "<span class='cultitalic'>[src] cannot support more than one body!</span>")
|
||||
log_game("Astral Communion rune failed - more than one user")
|
||||
log_game("Spirit Sight rune failed - more than one user")
|
||||
return list()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!(user in T))
|
||||
to_chat(user, "<span class='cultitalic'>You must be standing on top of [src]!</span>")
|
||||
log_game("Astral Communion rune failed - user not standing on rune")
|
||||
log_game("Spirit Sight rune failed - user not standing on rune")
|
||||
return list()
|
||||
return ..()
|
||||
|
||||
/obj/effect/rune/astral/invoke(var/list/invokers)
|
||||
/obj/effect/rune/spirit/invoke(var/list/invokers)
|
||||
var/mob/living/user = invokers[1]
|
||||
..()
|
||||
var/turf/T = get_turf(src)
|
||||
@@ -898,45 +898,6 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
if(is_servant_of_ratvar(L))
|
||||
L.adjustStaminaLoss(tick_damage*0.5)
|
||||
|
||||
|
||||
//Deals brute damage to all targets on the rune and heals the invoker for each target drained.
|
||||
/obj/effect/rune/leeching
|
||||
cultist_name = "Drain Life"
|
||||
cultist_desc = "drains the life of all targets on the rune, restoring life to the user."
|
||||
invocation = "Yu'gular faras desdae. Umathar uf'kal thenar!"
|
||||
icon_state = "3"
|
||||
color = "#9F1C34"
|
||||
|
||||
/obj/effect/rune/leeching/can_invoke(mob/living/user)
|
||||
if(world.time <= user.next_move)
|
||||
return list()
|
||||
var/turf/T = get_turf(src)
|
||||
var/list/potential_targets = list()
|
||||
for(var/mob/living/carbon/M in T.contents - user)
|
||||
if(M.stat != DEAD)
|
||||
potential_targets += M
|
||||
if(!potential_targets.len)
|
||||
to_chat(user, "<span class='cultitalic'>There must be at least one valid target on the rune!</span>")
|
||||
log_game("Leeching rune failed - no valid targets")
|
||||
return list()
|
||||
return ..()
|
||||
|
||||
/obj/effect/rune/leeching/invoke(var/list/invokers)
|
||||
var/mob/living/user = invokers[1]
|
||||
user.changeNext_move(CLICK_CD_CLICK_ABILITY)
|
||||
..()
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/living/carbon/M in T.contents - user)
|
||||
if(M.stat != DEAD)
|
||||
var/drained_amount = rand(10,20)
|
||||
M.apply_damage(drained_amount, BRUTE, "chest")
|
||||
user.adjustBruteLoss(-drained_amount)
|
||||
to_chat(M, "<span class='cultitalic'>You feel extremely weak.</span>")
|
||||
user.Beam(T,icon_state="drainbeam",time=5)
|
||||
user.visible_message("<span class='warning'>Blood flows from the rune into [user]!</span>", \
|
||||
"<span class='cult'>Blood flows into you, healing your wounds and revitalizing your spirit.</span>")
|
||||
|
||||
|
||||
//Rite of Spectral Manifestation: Summons a ghost on top of the rune as a cultist human with no items. User must stand on the rune at all times, and takes damage for each summoned ghost.
|
||||
/obj/effect/rune/manifest
|
||||
cultist_name = "Manifest Spirit"
|
||||
|
||||
@@ -176,7 +176,7 @@
|
||||
invocation = "Kla'atu barada nikt'o!"
|
||||
health_cost = 1
|
||||
creation_time = 30
|
||||
uses = 2
|
||||
uses = 6
|
||||
var/revealing = FALSE //if it reveals or not
|
||||
|
||||
/obj/item/weapon/paper/talisman/true_sight/invoke(mob/living/user, successfuluse = 1)
|
||||
@@ -186,7 +186,7 @@
|
||||
"<span class='cultitalic'>You speak the words of the talisman, hiding nearby runes.</span>")
|
||||
invocation = "Nikt'o barada kla'atu!"
|
||||
revealing = TRUE
|
||||
for(var/obj/effect/rune/R in range(3,user))
|
||||
for(var/obj/effect/rune/R in range(4,user))
|
||||
R.talismanhide()
|
||||
else
|
||||
user.visible_message("<span class='warning'>A flash of light shines from [user]'s hand!</span>", \
|
||||
@@ -194,22 +194,6 @@
|
||||
for(var/obj/effect/rune/R in range(3,user))
|
||||
R.talismanreveal()
|
||||
|
||||
//Rite of False Truths: Same as rune
|
||||
/obj/item/weapon/paper/talisman/make_runes_fake
|
||||
cultist_name = "Talisman of Disguising"
|
||||
cultist_desc = "A talisman that will make nearby runes appear fake."
|
||||
color = "#ff80d5" // honk
|
||||
invocation = "By'o nar'nar!"
|
||||
creation_time = 20
|
||||
|
||||
/obj/item/weapon/paper/talisman/make_runes_fake/invoke(mob/living/user, successfuluse = 1)
|
||||
. = ..()
|
||||
user.visible_message("<span class='warning'>Dust flows from [user]s hand.</span>", \
|
||||
"<span class='cultitalic'>You speak the words of the talisman, making nearby runes appear fake.</span>")
|
||||
for(var/obj/effect/rune/R in orange(6,user))
|
||||
R.desc = "A rune vandalizing the station."
|
||||
|
||||
|
||||
//Rite of Disruption: Weaker than rune
|
||||
/obj/item/weapon/paper/talisman/emp
|
||||
cultist_name = "Talisman of Electromagnetic Pulse"
|
||||
@@ -309,12 +293,12 @@
|
||||
invocation = "Lo'Nab Na'Dm!"
|
||||
creation_time = 80
|
||||
|
||||
/obj/item/weapon/paper/talisman/horror/attack(mob/living/target, mob/living/user)
|
||||
if(iscultist(user))
|
||||
to_chat(user, "<span class='cultitalic'>You disturb [target] with visons of the end!</span>")
|
||||
/obj/item/weapon/paper/talisman/horror/afterattack(mob/living/target, mob/living/user)
|
||||
if(iscultist(user) && (get_dist(user, target) < 7))
|
||||
to_chat(user, "<span class='cultitalic'>You disturb [target] with visions of madness!</span>")
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/H = target
|
||||
H.reagents.add_reagent("mindbreaker", 25)
|
||||
H.reagents.add_reagent("mindbreaker", 12)
|
||||
if(is_servant_of_ratvar(target))
|
||||
to_chat(target, "<span class='userdanger'>You see a brief but horrible vision of Ratvar, rusted and scrapped, being torn apart.</span>")
|
||||
target.emote("scream")
|
||||
@@ -379,7 +363,7 @@
|
||||
cultist_desc = "Use this talisman on a victim to handcuff them with dark bindings."
|
||||
invocation = "In'totum Lig'abis!"
|
||||
color = "#B27300" // burnt-orange
|
||||
uses = 4
|
||||
uses = 6
|
||||
|
||||
/obj/item/weapon/paper/talisman/shackle/invoke(mob/living/user, successfuluse = 0)
|
||||
if(successfuluse) //if we're forced to be successful(we normally aren't) then do the normal stuff
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -80,12 +80,11 @@
|
||||
report = config.intercept
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME)
|
||||
|
||||
feedback_set_details("round_start","[time2text(world.realtime)]")
|
||||
SSblackbox.set_details("round_start","[time2text(world.realtime)]")
|
||||
if(SSticker && SSticker.mode)
|
||||
feedback_set_details("game_mode","[SSticker.mode]")
|
||||
SSblackbox.set_details("game_mode","[SSticker.mode]")
|
||||
if(GLOB.revdata.commit)
|
||||
feedback_set_details("revision","[GLOB.revdata.commit]")
|
||||
feedback_set_details("server_ip","[world.internet_address]:[world.port]")
|
||||
SSblackbox.set_details("revision","[GLOB.revdata.commit]")
|
||||
if(report)
|
||||
addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h))
|
||||
generate_station_goals()
|
||||
@@ -246,17 +245,17 @@
|
||||
ghosts++
|
||||
|
||||
if(clients > 0)
|
||||
feedback_set("round_end_clients",clients)
|
||||
SSblackbox.set_val("round_end_clients",clients)
|
||||
if(ghosts > 0)
|
||||
feedback_set("round_end_ghosts",ghosts)
|
||||
SSblackbox.set_val("round_end_ghosts",ghosts)
|
||||
if(surviving_humans > 0)
|
||||
feedback_set("survived_human",surviving_humans)
|
||||
SSblackbox.set_val("survived_human",surviving_humans)
|
||||
if(surviving_total > 0)
|
||||
feedback_set("survived_total",surviving_total)
|
||||
SSblackbox.set_val("survived_total",surviving_total)
|
||||
if(escaped_humans > 0)
|
||||
feedback_set("escaped_human",escaped_humans)
|
||||
SSblackbox.set_val("escaped_human",escaped_humans)
|
||||
if(escaped_total > 0)
|
||||
feedback_set("escaped_total",escaped_total)
|
||||
SSblackbox.set_val("escaped_total",escaped_total)
|
||||
send2irc("Server", "Round just ended.")
|
||||
return 0
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define DOM_BLOCKED_SPAM_CAP 6
|
||||
|
||||
/obj/machinery/dominator
|
||||
name = "dominator"
|
||||
desc = "A visibly sinister device. Looks like you can break it if you hit it enough."
|
||||
@@ -13,9 +15,20 @@
|
||||
var/datum/gang/gang
|
||||
var/operating = 0 //0=standby or broken, 1=takeover
|
||||
var/warned = 0 //if this device has set off the warning at <3 minutes yet
|
||||
var/spam_prevention = DOM_BLOCKED_SPAM_CAP //first message is immediate
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
var/obj/effect/countdown/dominator/countdown
|
||||
|
||||
/proc/dominator_excessive_walls(atom/A)
|
||||
var/open = 0
|
||||
for(var/turf/T in circleviewturfs(center=A,radius=3))
|
||||
if(!istype(T, /turf/closed))
|
||||
open++
|
||||
if(open < 40)
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/dominator/tesla_act()
|
||||
qdel(src)
|
||||
|
||||
@@ -48,6 +61,16 @@
|
||||
if(gang && gang.is_dominating)
|
||||
var/time_remaining = gang.domination_time_remaining()
|
||||
if(time_remaining > 0)
|
||||
if(dominator_excessive_walls(src))
|
||||
gang.domination_timer += 2
|
||||
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
|
||||
if(spam_prevention < DOM_BLOCKED_SPAM_CAP)
|
||||
spam_prevention++
|
||||
else
|
||||
gang.message_gangtools("Warning: There are too many walls around your gang's dominator, its signal is being blocked!")
|
||||
say("Error: Takeover signal is currently blocked! There are too many walls within 3 standard units of this device.")
|
||||
spam_prevention = 0
|
||||
return
|
||||
. = TRUE
|
||||
playsound(loc, 'sound/items/timer.ogg', 10, 0)
|
||||
if(!warned && (time_remaining < 180))
|
||||
|
||||
@@ -249,7 +249,7 @@ GLOBAL_LIST_INIT(gang_colors_pool, list("red","orange","yellow","green","blue","
|
||||
return gang_bosses
|
||||
|
||||
/proc/determine_domination_time(var/datum/gang/G)
|
||||
return max(180,900 - (round((G.territory.len/GLOB.start_state.num_territories)*100, 1) * 12))
|
||||
return max(180,480 - (round((G.territory.len/GLOB.start_state.num_territories)*100, 1) * 9))
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//Announces the end of the game with all relavent information stated//
|
||||
@@ -260,12 +260,12 @@ GLOBAL_LIST_INIT(gang_colors_pool, list("red","orange","yellow","green","blue","
|
||||
return
|
||||
if(!winner)
|
||||
to_chat(world, "<span class='redtext'>The station was [station_was_nuked ? "destroyed!" : "evacuated before a gang could claim it! The station wins!"]</span><br>")
|
||||
feedback_set_details("round_end_result","loss - gangs failed takeover")
|
||||
SSblackbox.set_details("round_end_result","loss - gangs failed takeover")
|
||||
|
||||
SSticker.news_report = GANG_LOSS
|
||||
else
|
||||
to_chat(world, "<span class='redtext'>The [winner.name] Gang successfully performed a hostile takeover of the station!</span><br>")
|
||||
feedback_set_details("round_end_result","win - gang domination complete")
|
||||
SSblackbox.set_details("round_end_result","win - gang domination complete")
|
||||
|
||||
SSticker.news_report = GANG_TAKEOVER
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
var/list/territory = list()
|
||||
var/list/territory_new = list()
|
||||
var/list/territory_lost = list()
|
||||
var/recalls = 1
|
||||
var/dom_attempts = 2
|
||||
var/points = 15
|
||||
var/datum/atom_hud/antag/gang/ganghud
|
||||
@@ -262,4 +263,4 @@
|
||||
ganghud = new()
|
||||
|
||||
/datum/gang/multiverse/income()
|
||||
return
|
||||
return
|
||||
|
||||
@@ -108,10 +108,16 @@
|
||||
/datum/gang_item/weapon/ammo/get_cost_display(mob/living/carbon/user, datum/gang/gang, obj/item/device/gangtool/gangtool)
|
||||
return " ↳" + ..() //this is pretty hacky but it looks nice on the popup
|
||||
|
||||
/datum/gang_item/weapon/shuriken
|
||||
name = "Shuriken"
|
||||
id = "shuriken"
|
||||
cost = 3
|
||||
item_path = /obj/item/weapon/throwing_star
|
||||
|
||||
/datum/gang_item/weapon/switchblade
|
||||
name = "Switchblade"
|
||||
id = "switchblade"
|
||||
cost = 10
|
||||
cost = 5
|
||||
item_path = /obj/item/weapon/switchblade
|
||||
|
||||
/datum/gang_item/weapon/pistol
|
||||
@@ -125,6 +131,18 @@
|
||||
id = "pistol_ammo"
|
||||
cost = 10
|
||||
item_path = /obj/item/ammo_box/magazine/m10mm
|
||||
|
||||
/datum/gang_item/weapon/sniper
|
||||
name = ".50cal Sniper Rifle"
|
||||
id = "sniper"
|
||||
cost = 40
|
||||
item_path = /obj/item/weapon/gun/ballistic/automatic/sniper_rifle
|
||||
|
||||
/datum/gang_item/weapon/ammo/sniper_ammo
|
||||
name = "Standard .50cal Sniper Rounds"
|
||||
id = "sniper_ammo"
|
||||
cost = 15
|
||||
item_path = /obj/item/ammo_box/magazine/sniper_rounds
|
||||
|
||||
/datum/gang_item/weapon/uzi
|
||||
name = "Uzi SMG"
|
||||
@@ -138,30 +156,8 @@
|
||||
id = "uzi_ammo"
|
||||
cost = 40
|
||||
item_path = /obj/item/ammo_box/magazine/uzim9mm
|
||||
|
||||
//SLEEPING CARP
|
||||
|
||||
/datum/gang_item/weapon/bostaff
|
||||
name = "Bo Staff"
|
||||
id = "bostaff"
|
||||
cost = 10
|
||||
item_path = /obj/item/weapon/twohanded/bostaff
|
||||
|
||||
/datum/gang_item/weapon/sleeping_carp_scroll
|
||||
name = "Sleeping Carp Scroll (one-use)"
|
||||
id = "sleeping_carp_scroll"
|
||||
cost = 30
|
||||
item_path = /obj/item/weapon/sleeping_carp_scroll
|
||||
spawn_msg = "<span class='notice'>Anyone who reads the <b>sleeping carp scroll</b> will learn secrets of the sleeping carp martial arts style.</span>"
|
||||
|
||||
/datum/gang_item/weapon/wrestlingbelt
|
||||
name = "Wrestling Belt"
|
||||
id = "wrastling_belt"
|
||||
cost = 20
|
||||
item_path = /obj/item/weapon/storage/belt/champion/wrestling
|
||||
spawn_msg = "<span class='notice'>Anyone wearing the <b>wresting belt</b> will know how to be effective with wrestling.</span>"
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////
|
||||
//EQUIPMENT
|
||||
///////////////////
|
||||
@@ -175,6 +171,12 @@
|
||||
id = "spraycan"
|
||||
cost = 5
|
||||
item_path = /obj/item/toy/crayon/spraycan/gang
|
||||
|
||||
/datum/gang_item/equipment/sharpener
|
||||
name = "Sharpener"
|
||||
id = "whetstone"
|
||||
cost = 3
|
||||
item_path = /obj/item/weapon/sharpener
|
||||
|
||||
/datum/gang_item/equipment/necklace
|
||||
name = "Gold Necklace"
|
||||
@@ -182,12 +184,31 @@
|
||||
cost = 1
|
||||
item_path = /obj/item/clothing/neck/necklace/dope
|
||||
|
||||
|
||||
/datum/gang_item/equipment/emp
|
||||
name = "EMP Grenade"
|
||||
id = "EMP"
|
||||
cost = 5
|
||||
item_path = /obj/item/weapon/grenade/empgrenade
|
||||
|
||||
/datum/gang_item/equipment/c4
|
||||
name = "C4 Explosive"
|
||||
id = "c4"
|
||||
cost = 10
|
||||
cost = 7
|
||||
item_path = /obj/item/weapon/grenade/plastic/c4
|
||||
|
||||
/datum/gang_item/equipment/frag
|
||||
name = "Fragmentation Grenade"
|
||||
id = "frag nade"
|
||||
cost = 10
|
||||
item_path = /obj/item/weapon/grenade/syndieminibomb/concussion/frag
|
||||
|
||||
/datum/gang_item/equipment/stimpack
|
||||
name = "Black Market Stimulants"
|
||||
id = "stimpack"
|
||||
cost = 15
|
||||
item_path = /obj/item/weapon/reagent_containers/syringe/stimulants
|
||||
|
||||
/datum/gang_item/equipment/implant_breaker
|
||||
name = "Implant Breaker"
|
||||
id = "implant_breaker"
|
||||
@@ -284,7 +305,11 @@
|
||||
if(obj.density)
|
||||
to_chat(user, "<span class='warning'>There's not enough room here!</span>")
|
||||
return FALSE
|
||||
|
||||
|
||||
if(dominator_excessive_walls(user))
|
||||
to_chat(user, "span class='warning'>The <b>dominator</b> will not function here! The <b>dominator</b> requires an open space within three standard units so that walls do not interfere with the signal.</span>")
|
||||
return FALSE
|
||||
|
||||
if(!(usrarea.type in gang.territory|gang.territory_new))
|
||||
to_chat(user, "<span class='warning'>The <b>dominator</b> can be spawned only on territory controlled by your gang!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
..()
|
||||
last_used = world.time
|
||||
|
||||
/obj/item/weapon/pen/gang/attack(mob/living/M, mob/user)
|
||||
/obj/item/weapon/pen/gang/attack(mob/living/M, mob/user, stealth = TRUE)
|
||||
if(!istype(M))
|
||||
return
|
||||
if(ishuman(M) && ishuman(user) && M.stat != DEAD)
|
||||
|
||||
@@ -168,6 +168,9 @@
|
||||
if(recalling)
|
||||
to_chat(usr, "<span class='warning'>Error: Recall already in progress.</span>")
|
||||
return 0
|
||||
|
||||
if(!gang.recalls)
|
||||
to_chat(usr, "<span class='warning'>Error: Unable to access communication arrays. Firewall has logged our signature and is blocking all further attempts.</span>")
|
||||
|
||||
gang.message_gangtools("[usr] is attempting to recall the emergency shuttle.")
|
||||
recalling = 1
|
||||
@@ -209,6 +212,7 @@
|
||||
userturf = get_turf(user)
|
||||
if(userturf.z == 1) //Check one more time that they are on station.
|
||||
if(SSshuttle.cancelEvac(user))
|
||||
gang.recalls -= 1
|
||||
return 1
|
||||
|
||||
to_chat(loc, "<span class='info'>\icon[src]No response recieved. Emergency shuttle cannot be recalled at this time.</span>")
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
else
|
||||
to_chat(world, "<span class='boldnotice'>Nobody survived the meteor storm!</span>")
|
||||
|
||||
feedback_set_details("round_end_result","end - evacuation")
|
||||
feedback_set("round_end_result",survivors)
|
||||
SSblackbox.set_details("round_end_result","end - evacuation")
|
||||
SSblackbox.set_val("round_end_result",survivors)
|
||||
|
||||
..()
|
||||
return 1
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -107,10 +107,10 @@
|
||||
|
||||
/datum/game_mode/monkey/declare_completion()
|
||||
if(check_monkey_victory())
|
||||
feedback_set_details("round_end_result","win - monkey win")
|
||||
feedback_set("round_end_result",escaped_monkeys)
|
||||
SSblackbox.set_details("round_end_result","win - monkey win")
|
||||
SSblackbox.set_val("round_end_result",escaped_monkeys)
|
||||
to_chat(world, "<span class='userdanger'>The monkeys have overthrown their captors! Eeek eeeek!!</span>")
|
||||
else
|
||||
feedback_set_details("round_end_result","loss - staff stopped the monkeys")
|
||||
feedback_set("round_end_result",escaped_monkeys)
|
||||
SSblackbox.set_details("round_end_result","loss - staff stopped the monkeys")
|
||||
SSblackbox.set_val("round_end_result",escaped_monkeys)
|
||||
to_chat(world, "<span class='userdanger'>The staff managed to contain the monkey infestation!</span>")
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
var/icon_reveal = "revenant_revealed"
|
||||
var/icon_stun = "revenant_stun"
|
||||
var/icon_drain = "revenant_draining"
|
||||
var/stasis = 0
|
||||
incorporeal_move = 3
|
||||
invisibility = INVISIBILITY_REVENANT
|
||||
health = INFINITY //Revenants don't use health, they use essence instead
|
||||
@@ -94,6 +95,8 @@
|
||||
|
||||
//Life, Stat, Hud Updates, and Say
|
||||
/mob/living/simple_animal/revenant/Life()
|
||||
if(stasis)
|
||||
return
|
||||
if(revealed && essence <= 0)
|
||||
death()
|
||||
if(unreveal_time && world.time >= unreveal_time)
|
||||
@@ -200,9 +203,8 @@
|
||||
death()
|
||||
|
||||
/mob/living/simple_animal/revenant/death()
|
||||
if(!revealed || stat == DEAD) //Revenants cannot die if they aren't revealed //or are already dead
|
||||
if(!revealed || stasis) //Revenants cannot die if they aren't revealed //or are already dead
|
||||
return 0
|
||||
..(1)
|
||||
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
|
||||
@@ -217,9 +219,12 @@
|
||||
var/reforming_essence = essence_regen_cap //retain the gained essence capacity
|
||||
var/obj/item/weapon/ectoplasm/revenant/R = new(get_turf(src))
|
||||
R.essence = max(reforming_essence - 15 * perfectsouls, 75) //minus any perfect souls
|
||||
R.client_to_revive = src.client //If the essence reforms, the old revenant is put back in the body
|
||||
ghostize()
|
||||
qdel(src)
|
||||
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
|
||||
ghostize(0)//Don't re-enter invisible corpse
|
||||
return
|
||||
|
||||
|
||||
@@ -302,6 +307,18 @@
|
||||
to_chat(src, "<span class='revenminor'>Lost [essence_amt]E[source ? " from [source]":""].</span>")
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/revenant/proc/death_reset()
|
||||
revealed = FALSE
|
||||
unreveal_time = 0
|
||||
notransform = 0
|
||||
unstun_time = 0
|
||||
inhibited = FALSE
|
||||
draining = FALSE
|
||||
incorporeal_move = 3
|
||||
invisibility = INVISIBILITY_REVENANT
|
||||
alpha=255
|
||||
stasis = 0
|
||||
|
||||
|
||||
//reforming
|
||||
/obj/item/weapon/ectoplasm/revenant
|
||||
@@ -314,11 +331,15 @@
|
||||
var/reforming = TRUE
|
||||
var/inert = FALSE
|
||||
var/client/client_to_revive
|
||||
var/mob/living/simple_animal/revenant/revenant
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/New()
|
||||
..()
|
||||
addtimer(CALLBACK(src, .proc/try_reform), 600)
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/proc/scatter()
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/proc/try_reform()
|
||||
if(reforming)
|
||||
reforming = FALSE
|
||||
@@ -333,14 +354,14 @@
|
||||
user.visible_message("<span class='notice'>[user] scatters [src] in all directions.</span>", \
|
||||
"<span class='notice'>You scatter [src] across the area. The particles slowly fade away.</span>")
|
||||
user.drop_item()
|
||||
qdel(src)
|
||||
scatter()
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/throw_impact(atom/hit_atom)
|
||||
..()
|
||||
if(inert)
|
||||
return
|
||||
visible_message("<span class='notice'>[src] breaks into particles upon impact, which fade away to nothingness.</span>")
|
||||
qdel(src)
|
||||
scatter()
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/examine(mob/user)
|
||||
..()
|
||||
@@ -350,47 +371,51 @@
|
||||
to_chat(user, "<span class='revenwarning'>It is shifting and distorted. It would be wise to destroy this.</span>")
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/proc/reform()
|
||||
if(QDELETED(src) || inert)
|
||||
if(QDELETED(src) || QDELETED(revenant) || inert)
|
||||
return
|
||||
var/key_of_revenant
|
||||
message_admins("Revenant ectoplasm was left undestroyed for 1 minute and is reforming into a new revenant.")
|
||||
loc = get_turf(src) //In case it's in a backpack or someone's hand
|
||||
var/mob/living/simple_animal/revenant/R = new(get_turf(src))
|
||||
revenant.forceMove(loc)
|
||||
if(client_to_revive)
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
if(M.client == client_to_revive) //Only recreates the mob if the mob the client is in is dead
|
||||
R.client = client_to_revive
|
||||
revenant.client = client_to_revive
|
||||
key_of_revenant = client_to_revive.key
|
||||
if(!key_of_revenant)
|
||||
message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...")
|
||||
var/list/candidates = get_candidates(ROLE_REVENANT)
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to be [revenant.name] (reforming)?", "revenant", null, ROLE_REVENANT, 50, revenant)
|
||||
if(!candidates.len)
|
||||
qdel(R)
|
||||
qdel(revenant)
|
||||
message_admins("No candidates were found for the new revenant. Oh well!")
|
||||
inert = TRUE
|
||||
visible_message("<span class='revenwarning'>[src] settles down and seems lifeless.</span>")
|
||||
return
|
||||
var/client/C = pick(candidates)
|
||||
revenant.client = C
|
||||
key_of_revenant = C.key
|
||||
if(!key_of_revenant)
|
||||
qdel(R)
|
||||
qdel(revenant)
|
||||
message_admins("No ckey was found for the new revenant. Oh well!")
|
||||
inert = TRUE
|
||||
visible_message("<span class='revenwarning'>[src] settles down and seems lifeless.</span>")
|
||||
return
|
||||
var/datum/mind/player_mind = new /datum/mind(key_of_revenant)
|
||||
R.essence_regen_cap = essence
|
||||
R.essence = R.essence_regen_cap
|
||||
player_mind.active = 1
|
||||
player_mind.transfer_to(R)
|
||||
player_mind.assigned_role = "revenant"
|
||||
player_mind.special_role = "Revenant"
|
||||
SSticker.mode.traitors |= player_mind
|
||||
|
||||
message_admins("[key_of_revenant] has been [client_to_revive ? "re":""]made into a revenant by reforming ectoplasm.")
|
||||
log_game("[key_of_revenant] was [client_to_revive ? "re":""]made as a revenant by reforming ectoplasm.")
|
||||
visible_message("<span class='revenboldnotice'>[src] suddenly rises into the air before fading away.</span>")
|
||||
|
||||
revenant.essence = essence
|
||||
revenant.essence_regen_cap = essence
|
||||
revenant.death_reset()
|
||||
revenant.key = key_of_revenant
|
||||
revenant = null
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/Destroy()
|
||||
if(!QDELETED(revenant))
|
||||
qdel(revenant)
|
||||
..()
|
||||
|
||||
//objectives
|
||||
/datum/objective/revenant
|
||||
|
||||
@@ -199,70 +199,70 @@
|
||||
|
||||
|
||||
if(nuke_off_station == NUKE_SYNDICATE_BASE)
|
||||
feedback_set_details("round_end_result","loss - syndicate nuked - disk secured")
|
||||
SSblackbox.set_details("round_end_result","loss - syndicate nuked - disk secured")
|
||||
to_chat(world, "<FONT size = 3><B>Humiliating Syndicate Defeat</B></FONT>")
|
||||
to_chat(world, "<B>The crew of [station_name()] gave [syndicate_name()] operatives back their bomb! The syndicate base was destroyed!</B> Next time, don't lose the nuke!")
|
||||
|
||||
SSticker.news_report = NUKE_SYNDICATE_BASE
|
||||
|
||||
else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape)
|
||||
feedback_set_details("round_end_result","win - syndicate nuke")
|
||||
SSblackbox.set_details("round_end_result","win - syndicate nuke")
|
||||
to_chat(world, "<FONT size = 3><B>Syndicate Major Victory!</B></FONT>")
|
||||
to_chat(world, "<B>[syndicate_name()] operatives have destroyed [station_name()]!</B>")
|
||||
|
||||
SSticker.news_report = STATION_NUKED
|
||||
|
||||
else if (!disk_rescued && station_was_nuked && syndies_didnt_escape)
|
||||
feedback_set_details("round_end_result","halfwin - syndicate nuke - did not evacuate in time")
|
||||
SSblackbox.set_details("round_end_result","halfwin - syndicate nuke - did not evacuate in time")
|
||||
to_chat(world, "<FONT size = 3><B>Total Annihilation</B></FONT>")
|
||||
to_chat(world, "<B>[syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion.</B> Next time, don't lose the disk!")
|
||||
|
||||
SSticker.news_report = STATION_NUKED
|
||||
|
||||
else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape)
|
||||
feedback_set_details("round_end_result","halfwin - blew wrong station")
|
||||
SSblackbox.set_details("round_end_result","halfwin - blew wrong station")
|
||||
to_chat(world, "<FONT size = 3><B>Crew Minor Victory</B></FONT>")
|
||||
to_chat(world, "<B>[syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()].</B> Next time, don't do that!")
|
||||
|
||||
SSticker.news_report = NUKE_MISS
|
||||
|
||||
else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape)
|
||||
feedback_set_details("round_end_result","halfwin - blew wrong station - did not evacuate in time")
|
||||
SSblackbox.set_details("round_end_result","halfwin - blew wrong station - did not evacuate in time")
|
||||
to_chat(world, "<FONT size = 3><B>[syndicate_name()] operatives have earned Darwin Award!</B></FONT>")
|
||||
to_chat(world, "<B>[syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion.</B> Next time, don't do that!")
|
||||
|
||||
SSticker.news_report = NUKE_MISS
|
||||
|
||||
else if ((disk_rescued || SSshuttle.emergency.mode != SHUTTLE_ENDGAME) && are_operatives_dead())
|
||||
feedback_set_details("round_end_result","loss - evacuation - disk secured - syndi team dead")
|
||||
SSblackbox.set_details("round_end_result","loss - evacuation - disk secured - syndi team dead")
|
||||
to_chat(world, "<FONT size = 3><B>Crew Major Victory!</B></FONT>")
|
||||
to_chat(world, "<B>The Research Staff has saved the disk and killed the [syndicate_name()] Operatives</B>")
|
||||
|
||||
SSticker.news_report = OPERATIVES_KILLED
|
||||
|
||||
else if (disk_rescued)
|
||||
feedback_set_details("round_end_result","loss - evacuation - disk secured")
|
||||
SSblackbox.set_details("round_end_result","loss - evacuation - disk secured")
|
||||
to_chat(world, "<FONT size = 3><B>Crew Major Victory</B></FONT>")
|
||||
to_chat(world, "<B>The Research Staff has saved the disk and stopped the [syndicate_name()] Operatives!</B>")
|
||||
|
||||
SSticker.news_report = OPERATIVES_KILLED
|
||||
|
||||
else if (!disk_rescued && are_operatives_dead())
|
||||
feedback_set_details("round_end_result","halfwin - evacuation - disk not secured")
|
||||
SSblackbox.set_details("round_end_result","halfwin - evacuation - disk not secured")
|
||||
to_chat(world, "<FONT size = 3><B>Neutral Victory!</B></FONT>")
|
||||
to_chat(world, "<B>The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name()] Operatives!</B>")
|
||||
|
||||
SSticker.news_report = OPERATIVE_SKIRMISH
|
||||
|
||||
else if (!disk_rescued && crew_evacuated)
|
||||
feedback_set_details("round_end_result","halfwin - detonation averted")
|
||||
SSblackbox.set_details("round_end_result","halfwin - detonation averted")
|
||||
to_chat(world, "<FONT size = 3><B>Syndicate Minor Victory!</B></FONT>")
|
||||
to_chat(world, "<B>[syndicate_name()] operatives survived the assault but did not achieve the destruction of [station_name()].</B> Next time, don't lose the disk!")
|
||||
|
||||
SSticker.news_report = OPERATIVE_SKIRMISH
|
||||
|
||||
else if (!disk_rescued && !crew_evacuated)
|
||||
feedback_set_details("round_end_result","halfwin - interrupted")
|
||||
SSblackbox.set_details("round_end_result","halfwin - interrupted")
|
||||
to_chat(world, "<FONT size = 3><B>Neutral Victory</B></FONT>")
|
||||
to_chat(world, "<B>Round was mysteriously interrupted!</B>")
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
U.hidden_uplink.telecrystals = CHALLENGE_TELECRYSTALS
|
||||
U.hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
|
||||
config.shuttle_refuel_delay = max(config.shuttle_refuel_delay, CHALLENGE_SHUTTLE_DELAY)
|
||||
feedback_set("nuclear_challenge_mode",1)
|
||||
SSblackbox.set_val("nuclear_challenge_mode",1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/device/nuclear_challenge/proc/check_allowed(mob/living/user)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
var/atom/movable/constant_target = null //The thing we're always focused on, if we're in the right mode
|
||||
var/target_x = 0 //The target coordinates if we're tracking those
|
||||
var/target_y = 0
|
||||
var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
|
||||
var/nuke_warning = FALSE // If we've set off a miniature alarm about an armed nuke
|
||||
var/mode = TRACK_NUKE_DISK //What are we looking for?
|
||||
|
||||
@@ -111,7 +112,7 @@
|
||||
var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here)
|
||||
if(closest_operative)
|
||||
target = closest_operative
|
||||
if(TRACK_ATOM)
|
||||
if(TRACK_ATOM)
|
||||
if(constant_target)
|
||||
target = constant_target
|
||||
if(TRACK_COORDINATES)
|
||||
@@ -129,7 +130,7 @@
|
||||
if(here.z != there.z)
|
||||
icon_state = "pinon[nuke_warning ? "alert" : ""]null"
|
||||
return
|
||||
if(here == there)
|
||||
if(get_dist_euclidian(here,there)<=minimum_range)
|
||||
icon_state = "pinon[nuke_warning ? "alert" : ""]direct"
|
||||
else
|
||||
setDir(get_dir(here, there))
|
||||
@@ -171,3 +172,6 @@
|
||||
desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives."
|
||||
mode = TRACK_OPERATIVES
|
||||
flags = NODROP
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -67,7 +67,14 @@
|
||||
/datum/objective/proc/update_explanation_text()
|
||||
//Default does nothing, override where needed
|
||||
|
||||
/datum/objective/proc/give_special_equipment()
|
||||
/datum/objective/proc/give_special_equipment(special_equipment)
|
||||
if(owner && owner.current)
|
||||
if(ishuman(owner.current))
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/list/slots = list ("backpack" = slot_in_backpack)
|
||||
for(var/eq_path in special_equipment)
|
||||
var/obj/O = new eq_path
|
||||
H.equip_in_one_of_slots(O, slots)
|
||||
|
||||
/datum/objective/assassinate
|
||||
var/target_role_type=0
|
||||
@@ -94,6 +101,14 @@
|
||||
else
|
||||
explanation_text = "Free Objective"
|
||||
|
||||
/datum/objective/assassinate/internal
|
||||
var/stolen = 0 //Have we already eliminated this target?
|
||||
|
||||
/datum/objective/assassinate/internal/update_explanation_text()
|
||||
..()
|
||||
if(target && !target.current)
|
||||
explanation_text = "Assassinate [target.name], who was obliterated"
|
||||
|
||||
|
||||
/datum/objective/mutiny
|
||||
var/target_role_type=0
|
||||
@@ -468,7 +483,7 @@ GLOBAL_LIST_EMPTY(possible_items)
|
||||
steal_target = targetinfo.targetitem
|
||||
explanation_text = "Steal [targetinfo.name]."
|
||||
dangerrating = targetinfo.difficulty
|
||||
give_special_equipment()
|
||||
give_special_equipment(targetinfo.special_equipment)
|
||||
return steal_target
|
||||
else
|
||||
explanation_text = "Free objective"
|
||||
@@ -511,15 +526,6 @@ GLOBAL_LIST_EMPTY(possible_items)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/objective/steal/give_special_equipment()
|
||||
if(owner && owner.current && targetinfo)
|
||||
if(ishuman(owner.current))
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/list/slots = list ("backpack" = slot_in_backpack)
|
||||
for(var/eq_path in targetinfo.special_equipment)
|
||||
var/obj/O = new eq_path
|
||||
H.equip_in_one_of_slots(O, slots)
|
||||
|
||||
|
||||
GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
/datum/objective/steal/special //ninjas are so special they get their own subtype good for them
|
||||
@@ -654,7 +660,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
for(var/mob/dead/new_player/P in GLOB.player_list)
|
||||
if(P.client && P.ready && P.mind!=owner)
|
||||
n_p ++
|
||||
else if (SSticker.current_state == GAME_STATE_PLAYING)
|
||||
else if (SSticker.IsRoundInProgress())
|
||||
for(var/mob/living/carbon/human/P in GLOB.player_list)
|
||||
if(P.client && !(P.mind in SSticker.mode.changelings) && P.mind!=owner)
|
||||
n_p ++
|
||||
@@ -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!"
|
||||
|
||||
@@ -345,13 +345,13 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/datum/game_mode/revolution/declare_completion()
|
||||
if(finished == 1)
|
||||
feedback_set_details("round_end_result","win - heads killed")
|
||||
SSblackbox.set_details("round_end_result","win - heads killed")
|
||||
to_chat(world, "<span class='redtext'>The heads of staff were killed or exiled! The revolutionaries win!</span>")
|
||||
|
||||
SSticker.news_report = REVS_WIN
|
||||
|
||||
else if(finished == 2)
|
||||
feedback_set_details("round_end_result","loss - rev heads killed")
|
||||
SSblackbox.set_details("round_end_result","loss - rev heads killed")
|
||||
to_chat(world, "<span class='redtext'>The heads of staff managed to stop the revolution!</span>")
|
||||
|
||||
SSticker.news_report = REVS_LOSE
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#define PINPOINTER_MINIMUM_RANGE 15
|
||||
#define PINPOINTER_EXTRA_RANDOM_RANGE 10
|
||||
#define PINPOINTER_PING_TIME 40
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs
|
||||
name = "Internal Affairs"
|
||||
config_tag = "internal_affairs"
|
||||
employer = "Internal Affairs"
|
||||
required_players = 25
|
||||
required_enemies = 5
|
||||
required_players = 25
|
||||
required_enemies = 5
|
||||
recommended_enemies = 8
|
||||
reroll_friendly = 0
|
||||
traitor_name = "Nanotrasen Internal Affairs Agent"
|
||||
@@ -18,15 +22,189 @@
|
||||
var/list/target_list = list()
|
||||
var/list/late_joining_list = list()
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/post_setup()
|
||||
var/i = 0
|
||||
for(var/datum/mind/traitor in traitors)
|
||||
i++
|
||||
if(i + 1 > traitors.len)
|
||||
i = 0
|
||||
target_list[traitor] = traitors[i + 1]
|
||||
target_list[traitor] = traitors[i+1]
|
||||
..()
|
||||
|
||||
|
||||
/datum/status_effect/agent_pinpointer
|
||||
id = "agent_pinpointer"
|
||||
duration = -1
|
||||
tick_interval = PINPOINTER_PING_TIME
|
||||
alert_type = /obj/screen/alert/status_effect/agent_pinpointer
|
||||
var/minimum_range = PINPOINTER_MINIMUM_RANGE
|
||||
var/mob/scan_target = null
|
||||
|
||||
/obj/screen/alert/status_effect/agent_pinpointer
|
||||
name = "Internal Affairs Integrated Pinpointer"
|
||||
desc = "Even stealthier than a normal implant."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "pinon"
|
||||
|
||||
/datum/status_effect/agent_pinpointer/proc/point_to_target() //If we found what we're looking for, show the distance and direction
|
||||
if(!scan_target)
|
||||
linked_alert.icon_state = "pinonnull"
|
||||
return
|
||||
var/turf/here = get_turf(owner)
|
||||
var/turf/there = get_turf(scan_target)
|
||||
if(here.z != there.z)
|
||||
linked_alert.icon_state = "pinonnull"
|
||||
return
|
||||
if(get_dist_euclidian(here,there)<=minimum_range + rand(0, PINPOINTER_EXTRA_RANDOM_RANGE))
|
||||
linked_alert.icon_state = "pinondirect"
|
||||
else
|
||||
linked_alert.setDir(get_dir(here, there))
|
||||
switch(get_dist(here, there))
|
||||
if(1 to 8)
|
||||
linked_alert.icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
linked_alert.icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
linked_alert.icon_state = "pinonfar"
|
||||
|
||||
|
||||
/datum/status_effect/agent_pinpointer/proc/scan_for_target()
|
||||
scan_target = null
|
||||
if(owner)
|
||||
if(owner.mind)
|
||||
if(owner.mind.objectives)
|
||||
for(var/datum/objective/objective_ in owner.mind.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
var/mob/current = objective.target.current
|
||||
if(current&¤t.stat!=DEAD)
|
||||
scan_target = current
|
||||
break
|
||||
|
||||
|
||||
/datum/status_effect/agent_pinpointer/tick()
|
||||
if(!owner)
|
||||
qdel(src)
|
||||
return
|
||||
scan_for_target()
|
||||
point_to_target()
|
||||
|
||||
/proc/give_pinpointer(datum/mind/owner)
|
||||
if(owner && owner.current)
|
||||
owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer)
|
||||
|
||||
|
||||
/datum/internal_agent_state
|
||||
var/traitored = FALSE
|
||||
var/datum/mind/owner = null
|
||||
var/list/datum/mind/targets_stolen = list()
|
||||
|
||||
/proc/is_internal_objective(datum/objective/O)
|
||||
return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal))
|
||||
|
||||
/proc/replace_escape_objective(datum/mind/owner)
|
||||
if(!owner||!owner.objectives)
|
||||
return
|
||||
for (var/objective_ in owner.objectives)
|
||||
if(!(istype(objective_, /datum/objective/escape)||istype(objective_,/datum/objective/survive)))
|
||||
continue
|
||||
owner.objectives -= objective_
|
||||
var/datum/objective/martyr/martyr_objective = new
|
||||
martyr_objective.owner = owner
|
||||
owner.objectives += martyr_objective
|
||||
|
||||
/proc/reinstate_escape_objective(datum/mind/owner)
|
||||
if(!owner||!owner.objectives)
|
||||
return
|
||||
for (var/objective_ in owner.objectives)
|
||||
if(!istype(objective_, /datum/objective/martyr))
|
||||
continue
|
||||
owner.objectives -= objective_
|
||||
if(issilicon(owner))
|
||||
var/datum/objective/survive/survive_objective = new
|
||||
survive_objective.owner = owner
|
||||
owner.objectives += survive_objective
|
||||
else
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
owner.objectives += escape_objective
|
||||
|
||||
/datum/internal_agent_state/proc/steal_targets(datum/mind/victim)
|
||||
if(!owner.current||owner.current.stat==DEAD) //Should already be guaranteed if this is only called from steal_targets_timer_func, but better to be safe code than sorry code
|
||||
return
|
||||
var/already_traitored = traitored
|
||||
to_chat(owner.current, "<span class='userdanger'> Target eliminated: [victim.name]</span>")
|
||||
for(var/objective_ in victim.objectives)
|
||||
if(istype(objective_, /datum/objective/assassinate/internal))
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(objective.target==owner)
|
||||
traitored = TRUE
|
||||
else if(targets_stolen.Find(objective.target) == 0)
|
||||
var/datum/objective/assassinate/internal/new_objective = new
|
||||
new_objective.owner = owner
|
||||
new_objective.target = objective.target
|
||||
new_objective.update_explanation_text()
|
||||
owner.objectives += new_objective
|
||||
targets_stolen += objective.target
|
||||
var/status_text = objective.check_completion() ? "neutralised" : "active"
|
||||
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
|
||||
else if(istype(objective_, /datum/objective/destroy/internal))
|
||||
var/datum/objective/destroy/internal/objective = objective_
|
||||
var/datum/objective/destroy/internal/new_objective = new
|
||||
if(objective.target==owner)
|
||||
traitored = TRUE
|
||||
else if(targets_stolen.Find(objective.target) == 0)
|
||||
new_objective.owner = owner
|
||||
new_objective.target = objective.target
|
||||
new_objective.update_explanation_text()
|
||||
owner.objectives += new_objective
|
||||
targets_stolen += objective.target
|
||||
var/status_text = objective.check_completion() ? "neutralised" : "active"
|
||||
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
|
||||
if(traitored&&!already_traitored)
|
||||
for(var/objective_ in owner.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(!objective.check_completion())
|
||||
traitored = FALSE
|
||||
return
|
||||
to_chat(owner.current,"<span class='userdanger'> All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.</span>")
|
||||
replace_escape_objective(owner)
|
||||
|
||||
|
||||
|
||||
/datum/internal_agent_state/proc/steal_targets_timer_func()
|
||||
if(owner&&owner.current&&owner.current.stat!=DEAD)
|
||||
for(var/objective_ in owner.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(!objective.target)
|
||||
continue
|
||||
if(objective.check_completion())
|
||||
if(objective.stolen)
|
||||
continue
|
||||
else
|
||||
steal_targets(objective.target)
|
||||
objective.stolen = TRUE
|
||||
else
|
||||
if(objective.stolen)
|
||||
var/fail_msg = "<span class='userdanger'>Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! </span>"
|
||||
if(traitored)
|
||||
fail_msg += "<span class='userdanger'> The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated.</span>"
|
||||
reinstate_escape_objective(owner)
|
||||
traitored = FALSE
|
||||
to_chat(owner.current, fail_msg)
|
||||
objective.stolen = FALSE
|
||||
add_steal_targets_timer(owner)
|
||||
|
||||
/datum/internal_agent_state/proc/add_steal_targets_timer()
|
||||
var/datum/callback/C = new(src, .steal_targets_timer_func)
|
||||
addtimer(C, 30)
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/forge_traitor_objectives(datum/mind/traitor)
|
||||
|
||||
if(target_list.len && target_list[traitor]) // Is a double agent
|
||||
@@ -34,13 +212,13 @@
|
||||
// Assassinate
|
||||
var/datum/mind/target_mind = target_list[traitor]
|
||||
if(issilicon(target_mind.current))
|
||||
var/datum/objective/destroy/destroy_objective = new
|
||||
var/datum/objective/destroy/internal/destroy_objective = new
|
||||
destroy_objective.owner = traitor
|
||||
destroy_objective.target = target_mind
|
||||
destroy_objective.update_explanation_text()
|
||||
traitor.objectives += destroy_objective
|
||||
else
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
var/datum/objective/assassinate/internal/kill_objective = new
|
||||
kill_objective.owner = traitor
|
||||
kill_objective.target = target_mind
|
||||
kill_objective.update_explanation_text()
|
||||
@@ -55,6 +233,11 @@
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = traitor
|
||||
traitor.objectives += escape_objective
|
||||
var/datum/internal_agent_state/state = new
|
||||
state.owner=traitor
|
||||
state.add_steal_targets_timer()
|
||||
if(!issilicon(traitor.current))
|
||||
give_pinpointer(traitor)
|
||||
|
||||
else
|
||||
..() // Give them standard objectives.
|
||||
@@ -106,14 +289,18 @@
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/greet_traitor(datum/mind/traitor)
|
||||
var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>You are the [traitor_name].</font></B>")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.</font></B>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>You are the [traitor_name].</span>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.</span>")
|
||||
to_chat(traitor.current, "<B><font size=5 color=red>While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.</font></B>")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.</font></B>")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</font></B>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.</span>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
|
||||
traitor.announce_objectives()
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/give_codewords(mob/living/traitor_mob)
|
||||
return
|
||||
return
|
||||
|
||||
#undef PINPOINTER_EXTRA_RANDOM_RANGE
|
||||
#undef PINPOINTER_MINIMUM_RANGE
|
||||
#undef PINPOINTER_PING_TIME
|
||||
|
||||
@@ -261,10 +261,10 @@
|
||||
for(var/datum/objective/objective in traitor.objectives)
|
||||
if(objective.check_completion())
|
||||
objectives += "<br><B>Objective #[count]</B>: [objective.explanation_text] <font color='green'><B>Success!</B></font>"
|
||||
feedback_add_details("traitor_objective","[objective.type]|SUCCESS")
|
||||
SSblackbox.add_details("traitor_objective","[objective.type]|SUCCESS")
|
||||
else
|
||||
objectives += "<br><B>Objective #[count]</B>: [objective.explanation_text] <font color='red'>Fail.</font>"
|
||||
feedback_add_details("traitor_objective","[objective.type]|FAIL")
|
||||
SSblackbox.add_details("traitor_objective","[objective.type]|FAIL")
|
||||
traitorwin = 0
|
||||
count++
|
||||
|
||||
@@ -284,10 +284,10 @@
|
||||
|
||||
if(traitorwin)
|
||||
text += "<br><font color='green'><B>The [special_role_text] was successful!</B></font>"
|
||||
feedback_add_details("traitor_success","SUCCESS")
|
||||
SSblackbox.add_details("traitor_success","SUCCESS")
|
||||
else
|
||||
text += "<br><font color='red'><B>The [special_role_text] has failed!</B></font>"
|
||||
feedback_add_details("traitor_success","FAIL")
|
||||
SSblackbox.add_details("traitor_success","FAIL")
|
||||
|
||||
text += "<br>"
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
/datum/game_mode/wizard/raginmages/declare_completion()
|
||||
if(finished)
|
||||
feedback_set_details("round_end_result","loss - wizard killed")
|
||||
SSblackbox.set_details("round_end_result","loss - wizard killed")
|
||||
to_chat(world, "<FONT size=3><B>The crew has managed to hold off the wizard attack! The Space Wizards Federation has been taught a lesson they will not soon forget!</B></FONT>")
|
||||
..(1)
|
||||
|
||||
|
||||
@@ -57,10 +57,10 @@
|
||||
aspell.name = "Instant [aspell.name]"
|
||||
if(aspell.spell_level >= aspell.level_max)
|
||||
to_chat(user, "<span class='notice'>This spell cannot be strengthened any further.</span>")
|
||||
feedback_add_details("wizard_spell_improved", "[name]|[aspell.level]")
|
||||
SSblackbox.add_details("wizard_spell_improved", "[name]|[aspell.level]")
|
||||
return 1
|
||||
//No same spell found - just learn it
|
||||
feedback_add_details("wizard_spell_learned", name)
|
||||
SSblackbox.add_details("wizard_spell_learned", name)
|
||||
user.mind.AddSpell(S)
|
||||
to_chat(user, "<span class='notice'>You have learned [S.name].</span>")
|
||||
return 1
|
||||
@@ -266,7 +266,7 @@
|
||||
|
||||
/datum/spellbook_entry/item/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book)
|
||||
new item_path(get_turf(user))
|
||||
feedback_add_details("wizard_spell_learned", name)
|
||||
SSblackbox.add_details("wizard_spell_learned", name)
|
||||
return 1
|
||||
|
||||
/datum/spellbook_entry/item/GetInfo()
|
||||
@@ -465,7 +465,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book)
|
||||
feedback_add_details("wizard_spell_learned", name)
|
||||
SSblackbox.add_details("wizard_spell_learned", name)
|
||||
new /datum/round_event/wizard/ghost()
|
||||
active = TRUE
|
||||
to_chat(user, "<span class='notice'>You have cast summon ghosts!</span>")
|
||||
@@ -482,7 +482,7 @@
|
||||
return (SSticker.mode.name != "ragin' mages" && !config.no_summon_guns)
|
||||
|
||||
/datum/spellbook_entry/summon/guns/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book)
|
||||
feedback_add_details("wizard_spell_learned", name)
|
||||
SSblackbox.add_details("wizard_spell_learned", name)
|
||||
rightandwrong(0, user, 25)
|
||||
active = 1
|
||||
playsound(get_turf(user), 'sound/magic/CastSummon.ogg', 50, 1)
|
||||
@@ -499,7 +499,7 @@
|
||||
return (SSticker.mode.name != "ragin' mages" && !config.no_summon_magic)
|
||||
|
||||
/datum/spellbook_entry/summon/magic/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book)
|
||||
feedback_add_details("wizard_spell_learned", name)
|
||||
SSblackbox.add_details("wizard_spell_learned", name)
|
||||
rightandwrong(1, user, 25)
|
||||
active = 1
|
||||
playsound(get_turf(user), 'sound/magic/CastSummon.ogg', 50, 1)
|
||||
@@ -517,7 +517,7 @@
|
||||
return (SSticker.mode.name != "ragin' mages" && !config.no_summon_events)
|
||||
|
||||
/datum/spellbook_entry/summon/events/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book)
|
||||
feedback_add_details("wizard_spell_learned", name)
|
||||
SSblackbox.add_details("wizard_spell_learned", name)
|
||||
summonevents()
|
||||
times++
|
||||
playsound(get_turf(user), 'sound/magic/CastSummon.ogg', 50, 1)
|
||||
@@ -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"
|
||||
|
||||
@@ -176,7 +176,7 @@
|
||||
|
||||
/datum/game_mode/wizard/declare_completion()
|
||||
if(finished)
|
||||
feedback_set_details("round_end_result","loss - wizard killed")
|
||||
SSblackbox.set_details("round_end_result","loss - wizard killed")
|
||||
to_chat(world, "<span class='userdanger'>The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!</span>")
|
||||
|
||||
SSticker.news_report = WIZARD_KILLED
|
||||
@@ -208,19 +208,19 @@
|
||||
for(var/datum/objective/objective in wizard.objectives)
|
||||
if(objective.check_completion())
|
||||
text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <font color='green'><B>Success!</B></font>"
|
||||
feedback_add_details("wizard_objective","[objective.type]|SUCCESS")
|
||||
SSblackbox.add_details("wizard_objective","[objective.type]|SUCCESS")
|
||||
else
|
||||
text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <font color='red'>Fail.</font>"
|
||||
feedback_add_details("wizard_objective","[objective.type]|FAIL")
|
||||
SSblackbox.add_details("wizard_objective","[objective.type]|FAIL")
|
||||
wizardwin = 0
|
||||
count++
|
||||
|
||||
if(wizard.current && wizard.current.stat!=2 && wizardwin)
|
||||
text += "<br><font color='green'><B>The wizard was successful!</B></font>"
|
||||
feedback_add_details("wizard_success","SUCCESS")
|
||||
SSblackbox.add_details("wizard_success","SUCCESS")
|
||||
else
|
||||
text += "<br><font color='red'><B>The wizard has failed!</B></font>"
|
||||
feedback_add_details("wizard_success","FAIL")
|
||||
SSblackbox.add_details("wizard_success","FAIL")
|
||||
if(wizard.spell_list.len>0)
|
||||
text += "<br><B>[wizard.name] used the following spells: </B>"
|
||||
var/i = 1
|
||||
|
||||
@@ -321,7 +321,9 @@
|
||||
return
|
||||
else
|
||||
connected_message("Authorized Ejection")
|
||||
|
||||
SPEAK("An authorized ejection of [clonemind.name] has occurred.")
|
||||
|
||||
to_chat(user, "<span class='notice'>You force an emergency ejection. </span>")
|
||||
go_out()
|
||||
else
|
||||
@@ -378,8 +380,10 @@
|
||||
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)
|
||||
|
||||
icon_state = "pod_g"
|
||||
if(mob_occupant.mind != clonemind)
|
||||
clonemind.transfer_to(mob_occupant)
|
||||
@@ -395,10 +399,12 @@
|
||||
go_out()
|
||||
|
||||
/obj/machinery/clonepod/emp_act(severity)
|
||||
|
||||
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 [mob_occupant.real_name] prematurely." ,0))
|
||||
|
||||
go_out()
|
||||
..()
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
playsound(loc, 'sound/arcade/Win.ogg', 50, 1, extrarange = -3, falloff = 10)
|
||||
|
||||
if(emagged)
|
||||
feedback_inc("arcade_win_emagged")
|
||||
SSblackbox.inc("arcade_win_emagged")
|
||||
new /obj/effect/spawner/newbomb/timer/syndicate(loc)
|
||||
new /obj/item/clothing/head/collectable/petehat(loc)
|
||||
message_admins("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded a bomb.")
|
||||
@@ -242,7 +242,7 @@
|
||||
Reset()
|
||||
emagged = 0
|
||||
else
|
||||
feedback_inc("arcade_win_normal")
|
||||
SSblackbox.inc("arcade_win_normal")
|
||||
prizevend()
|
||||
|
||||
else if (emagged && (turtle >= 4))
|
||||
@@ -264,10 +264,10 @@
|
||||
temp = "You have been drained! GAME OVER"
|
||||
playsound(loc, 'sound/arcade/Lose.ogg', 50, 1, extrarange = -3, falloff = 10)
|
||||
if(emagged)
|
||||
feedback_inc("arcade_loss_mana_emagged")
|
||||
SSblackbox.inc("arcade_loss_mana_emagged")
|
||||
usr.gib()
|
||||
else
|
||||
feedback_inc("arcade_loss_mana_normal")
|
||||
SSblackbox.inc("arcade_loss_mana_normal")
|
||||
|
||||
else if ((enemy_hp <= 10) && (enemy_mp > 4))
|
||||
temp = "[enemy_name] heals for 4 health!"
|
||||
@@ -286,10 +286,10 @@
|
||||
temp = "You have been crushed! GAME OVER"
|
||||
playsound(loc, 'sound/arcade/Lose.ogg', 50, 1, extrarange = -3, falloff = 10)
|
||||
if(emagged)
|
||||
feedback_inc("arcade_loss_hp_emagged")
|
||||
SSblackbox.inc("arcade_loss_hp_emagged")
|
||||
usr.gib()
|
||||
else
|
||||
feedback_inc("arcade_loss_hp_normal")
|
||||
SSblackbox.inc("arcade_loss_hp_normal")
|
||||
|
||||
blocked = FALSE
|
||||
return
|
||||
|
||||
@@ -115,9 +115,9 @@
|
||||
message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].")
|
||||
switch(GLOB.security_level)
|
||||
if(SEC_LEVEL_GREEN)
|
||||
feedback_inc("alert_comms_green",1)
|
||||
SSblackbox.inc("alert_comms_green",1)
|
||||
if(SEC_LEVEL_BLUE)
|
||||
feedback_inc("alert_comms_blue",1)
|
||||
SSblackbox.inc("alert_comms_blue",1)
|
||||
tmp_alertlevel = 0
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You are not authorized to do this!</span>")
|
||||
@@ -176,7 +176,7 @@
|
||||
SSshuttle.points -= S.credit_cost
|
||||
minor_announce("[usr.name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase")
|
||||
message_admins("[key_name_admin(usr)] purchased [S.name].")
|
||||
feedback_add_details("shuttle_purchase", S.name)
|
||||
SSblackbox.add_details("shuttle_purchase", S.name)
|
||||
else
|
||||
to_chat(usr, "Something went wrong! The shuttle exchange system seems to be down.")
|
||||
else
|
||||
@@ -368,9 +368,9 @@
|
||||
message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].")
|
||||
switch(GLOB.security_level)
|
||||
if(SEC_LEVEL_GREEN)
|
||||
feedback_inc("alert_comms_green",1)
|
||||
SSblackbox.inc("alert_comms_green",1)
|
||||
if(SEC_LEVEL_BLUE)
|
||||
feedback_inc("alert_comms_blue",1)
|
||||
SSblackbox.inc("alert_comms_blue",1)
|
||||
tmp_alertlevel = 0
|
||||
src.aistate = STATE_DEFAULT
|
||||
if("ai-changeseclevel")
|
||||
|
||||
@@ -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
|
||||
@@ -153,8 +153,8 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
U = H.w_uniform
|
||||
|
||||
// Are the suit sensors on?
|
||||
if (U.has_sensor && U.sensor_mode)
|
||||
pos = H.z == 0 || U.sensor_mode == 3 ? get_turf(H) : null
|
||||
if ((U.has_sensor > 0) && U.sensor_mode)
|
||||
pos = H.z == 0 || U.sensor_mode == SENSOR_COORDS ? get_turf(H) : null
|
||||
|
||||
// Special case: If the mob is inside an object confirm the z-level on turf level.
|
||||
if (H.z == 0 && (!pos || pos.z != z)) continue
|
||||
@@ -170,10 +170,10 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
assignment = ""
|
||||
ijob = 80
|
||||
|
||||
if (U.sensor_mode >= 1) life_status = (!H.stat ? "true" : "false")
|
||||
if (U.sensor_mode >= SENSOR_LIVING) life_status = (!H.stat ? "true" : "false")
|
||||
else life_status = null
|
||||
|
||||
if (U.sensor_mode >= 2)
|
||||
if (U.sensor_mode >= SENSOR_VITALS)
|
||||
dam1 = round(H.getOxyLoss(),1)
|
||||
dam2 = round(H.getToxLoss(),1)
|
||||
dam3 = round(H.getFireLoss(),1)
|
||||
@@ -184,7 +184,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
dam3 = null
|
||||
dam4 = null
|
||||
|
||||
if (U.sensor_mode >= 3)
|
||||
if (U.sensor_mode >= SENSOR_COORDS)
|
||||
if (!pos) pos = get_turf(H)
|
||||
var/area/player_area = get_area(H)
|
||||
|
||||
|
||||
@@ -58,7 +58,12 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1)
|
||||
if(uplinkholder && linkedboss)
|
||||
if(amt <= uplinkholder.hidden_uplink.telecrystals)
|
||||
if(amt < 0)
|
||||
linkedboss.storedcrystals += uplinkholder.hidden_uplink.telecrystals
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] donated [uplinkholder.hidden_uplink.telecrystals] telecrystals to [linkedboss].")
|
||||
uplinkholder.hidden_uplink.telecrystals = 0
|
||||
else if(amt <= uplinkholder.hidden_uplink.telecrystals)
|
||||
uplinkholder.hidden_uplink.telecrystals -= amt
|
||||
linkedboss.storedcrystals += amt
|
||||
if(addLog)
|
||||
@@ -66,7 +71,12 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
|
||||
if(uplinkholder && linkedboss)
|
||||
if(amt <= linkedboss.storedcrystals)
|
||||
if(amt < 0)
|
||||
uplinkholder.hidden_uplink.telecrystals += linkedboss.storedcrystals
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].")
|
||||
linkedboss.storedcrystals = 0
|
||||
else if(amt <= linkedboss.storedcrystals)
|
||||
uplinkholder.hidden_uplink.telecrystals += amt
|
||||
linkedboss.storedcrystals -= amt
|
||||
if(addLog)
|
||||
@@ -89,7 +99,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
if(uplinkholder)
|
||||
dat += "[uplinkholder.hidden_uplink.telecrystals] telecrystals remain in this uplink.<BR>"
|
||||
if(linkedboss)
|
||||
dat += "Donate TC: <a href='byond://?src=\ref[src];donate1=1'>1</a> | <a href='byond://?src=\ref[src];donate5=1'>5</a>"
|
||||
dat += "Donate TC: <a href='byond://?src=\ref[src];donate=1'>1</a> | <a href='byond://?src=\ref[src];donate=5'>5</a> | <a href='byond://?src=\ref[src];donate=-1'>All</a>"
|
||||
dat += "<br><a href='byond://?src=\ref[src];eject=1'>Eject Uplink</a>"
|
||||
|
||||
|
||||
@@ -103,11 +113,9 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["donate1"])
|
||||
donateTC(1)
|
||||
|
||||
if(href_list["donate5"])
|
||||
donateTC(5)
|
||||
if(href_list["donate"])
|
||||
var/tcamt = text2num(href_list["donate"])
|
||||
donateTC(tcamt)
|
||||
|
||||
if(href_list["eject"])
|
||||
ejectuplink()
|
||||
@@ -162,7 +170,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
|
||||
var/dat = ""
|
||||
dat += "<a href='byond://?src=\ref[src];scan=1'>Scan for TC stations.</a><BR>"
|
||||
dat += "This [src] has [storedcrystals] telecrystals available for distribution. <BR>"
|
||||
dat += "[storedcrystals] telecrystals are available for distribution. <BR>"
|
||||
dat += "<BR><BR>"
|
||||
|
||||
|
||||
@@ -171,10 +179,10 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
if(A.uplinkholder)
|
||||
dat += "[A.uplinkholder.hidden_uplink.telecrystals] telecrystals."
|
||||
if(storedcrystals)
|
||||
dat+= "<BR>Add TC: <a href ='?src=\ref[src];give1=\ref[A]'>1</a> | <a href ='?src=\ref[src];give5=\ref[A]'>5</a>"
|
||||
dat+= "<BR>Add TC: <a href ='?src=\ref[src];target=\ref[A];give=1'>1</a> | <a href ='?src=\ref[src];target=\ref[A];give=5'>5</a> | <a href ='?src=\ref[src];target=\ref[A];give=10'>10</a> | <a href ='?src=\ref[src];target=\ref[A];give=-1'>All</a>"
|
||||
dat += "<BR>"
|
||||
|
||||
if(TCstations.len)
|
||||
if(TCstations.len && storedcrystals)
|
||||
dat += "<BR><BR><a href='byond://?src=\ref[src];distrib=1'>Evenly distribute remaining TC.</a><BR><BR>"
|
||||
|
||||
|
||||
@@ -195,13 +203,11 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
if(href_list["scan"])
|
||||
scanUplinkers()
|
||||
|
||||
if(href_list["give1"])
|
||||
var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give1"])
|
||||
A.giveTC(1)
|
||||
|
||||
if(href_list["give5"])
|
||||
var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give5"])
|
||||
A.giveTC(5)
|
||||
if(href_list["give"])
|
||||
var/tcamt = text2num(href_list["give"])
|
||||
if(TCstations.len) // sanity
|
||||
var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations
|
||||
A.giveTC(tcamt)
|
||||
|
||||
if(href_list["distrib"])
|
||||
var/sanity = 0
|
||||
|
||||
@@ -1283,8 +1283,6 @@
|
||||
|
||||
if(!density)
|
||||
return 1
|
||||
if(!SSticker || !SSticker.mode)
|
||||
return 0
|
||||
operating = 1
|
||||
update_icon(AIRLOCK_OPENING, 1)
|
||||
src.set_opacity(0)
|
||||
|
||||
@@ -229,8 +229,6 @@
|
||||
return 1
|
||||
if(operating)
|
||||
return
|
||||
if(!SSticker || !SSticker.mode)
|
||||
return 0
|
||||
operating = 1
|
||||
do_animate("opening")
|
||||
set_opacity(0)
|
||||
|
||||
@@ -129,8 +129,6 @@
|
||||
/obj/machinery/door/window/open(forced=0)
|
||||
if (src.operating == 1) //doors can still open when emag-disabled
|
||||
return 0
|
||||
if(!SSticker || !SSticker.mode)
|
||||
return 0
|
||||
if(!forced)
|
||||
if(!hasPower())
|
||||
return 0
|
||||
|
||||
+221
-74
@@ -26,14 +26,13 @@ Possible to do for anyone motivated enough:
|
||||
|
||||
#define HOLOPAD_PASSIVE_POWER_USAGE 1
|
||||
#define HOLOGRAM_POWER_USAGE 2
|
||||
#define RANGE_BASED 4
|
||||
#define AREA_BASED 6
|
||||
|
||||
GLOBAL_LIST_EMPTY(holopads)
|
||||
#define HOLOPAD_MODE RANGE_BASED
|
||||
|
||||
/obj/machinery/holopad
|
||||
name = "\improper AI holopad"
|
||||
desc = "It's a floor-mounted device for projecting holographic images. It is activated remotely."
|
||||
name = "Holopad"
|
||||
desc = "It's a floor-mounted device for projecting holographic images."
|
||||
icon_state = "holopad0"
|
||||
layer = LOW_OBJ_LAYER
|
||||
flags = HEAR
|
||||
@@ -44,21 +43,33 @@ Possible to do for anyone motivated enough:
|
||||
obj_integrity = 300
|
||||
max_integrity = 300
|
||||
armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 0)
|
||||
var/list/masters = list()//List of AIs that use the holopad
|
||||
var/list/masters = list()//List of living mobs that use the holopad
|
||||
var/last_request = 0 //to prevent request spam. ~Carn
|
||||
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
|
||||
var/temp = ""
|
||||
var/list/holo_calls //array of /datum/holocalls
|
||||
var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs
|
||||
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
|
||||
var/static/list/holopads = list()
|
||||
|
||||
/obj/machinery/holopad/New()
|
||||
/obj/machinery/holopad/Initialize()
|
||||
..()
|
||||
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/holopad(null)
|
||||
B.apply_default_parts(src)
|
||||
holopads += src
|
||||
|
||||
/obj/machinery/holopad/Destroy()
|
||||
for (var/mob/living/silicon/ai/master in masters)
|
||||
clear_holo(master)
|
||||
if(outgoing_call)
|
||||
LAZYADD(holo_calls, outgoing_call)
|
||||
outgoing_call = null
|
||||
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
HC.ConnectionFailure(src)
|
||||
LAZYCLEARLIST(holo_calls)
|
||||
|
||||
for (var/I in masters)
|
||||
clear_holo(I)
|
||||
holopads -= src
|
||||
return ..()
|
||||
|
||||
@@ -91,20 +102,58 @@ Possible to do for anyone motivated enough:
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/holopad/proc/CheckCallClose()
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(usr == HC.eye)
|
||||
HC.Disconnect(HC.calling_holopad) //disconnect via clicking the called holopad
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/holopad/Click(location,control,params)
|
||||
if(!CheckCallClose())
|
||||
return ..()
|
||||
|
||||
/obj/machinery/holopad/AltClick(mob/living/carbon/human/user)
|
||||
interact(user)
|
||||
if(!CheckCallClose())
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/holopad/interact(mob/living/carbon/human/user) //Carn: Hologram requests.
|
||||
if(!istype(user))
|
||||
return
|
||||
if(user.stat || !is_operational())
|
||||
|
||||
if(outgoing_call || user.incapacitated() || !is_operational())
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
if(temp)
|
||||
dat = temp
|
||||
else
|
||||
dat = "<A href='?src=\ref[src];AIrequest=1'>request an AI's presence.</A>"
|
||||
dat = "<a href='?src=\ref[src];AIrequest=1'>Request an AI's presence.</a><br>"
|
||||
dat += "<a href='?src=\ref[src];Holocall=1'>Call another holopad.</a><br>"
|
||||
|
||||
if(LAZYLEN(holo_calls))
|
||||
dat += "=====================================================<br>"
|
||||
|
||||
var/one_answered_call = FALSE
|
||||
var/one_unanswered_call = FALSE
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad != src)
|
||||
dat += "<a href='?src=\ref[src];connectcall=\ref[HC]'>Answer call from [get_area(HC.calling_holopad)].</a><br>"
|
||||
one_unanswered_call = TRUE
|
||||
else
|
||||
one_answered_call = TRUE
|
||||
|
||||
if(one_answered_call && one_unanswered_call)
|
||||
dat += "=====================================================<br>"
|
||||
//we loop twice for formatting
|
||||
for(var/I in holo_calls)
|
||||
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)
|
||||
@@ -112,7 +161,10 @@ Possible to do for anyone motivated enough:
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/holopad/Topic(href, href_list)
|
||||
if(..() || !is_operational())
|
||||
if(..() || isAI(usr))
|
||||
return
|
||||
add_fingerprint(usr)
|
||||
if(!is_operational())
|
||||
return
|
||||
if (href_list["AIrequest"])
|
||||
if(last_request + 200 < world.time)
|
||||
@@ -120,7 +172,7 @@ Possible to do for anyone motivated enough:
|
||||
temp = "You requested an AI's presence.<BR>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
var/area/area = get_area(src)
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.living_mob_list)
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs)
|
||||
if(!AI.client)
|
||||
continue
|
||||
to_chat(AI, "<span class='info'>Your presence is requested at <a href='?src=\ref[AI];jumptoholopad=\ref[src]'>\the [area]</a>.</span>")
|
||||
@@ -128,12 +180,49 @@ Possible to do for anyone motivated enough:
|
||||
temp = "A request for AI presence was already sent recently.<BR>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
|
||||
else if(href_list["mainmenu"])
|
||||
else if(href_list["Holocall"])
|
||||
if(outgoing_call)
|
||||
return
|
||||
|
||||
temp = "You must stand on the holopad to make a call!<br>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
if(usr.loc == loc)
|
||||
var/list/callnames = list()
|
||||
for(var/I in holopads)
|
||||
var/area/A = get_area(I)
|
||||
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
|
||||
|
||||
if(usr.loc == loc)
|
||||
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))
|
||||
call_to_connect.Answer(src)
|
||||
temp = ""
|
||||
|
||||
updateDialog()
|
||||
add_fingerprint(usr)
|
||||
else if(href_list["disconnectcall"])
|
||||
var/datum/holocall/call_to_disconnect = locate(href_list["disconnectcall"])
|
||||
if(!QDELETED(call_to_disconnect))
|
||||
call_to_disconnect.Disconnect(src)
|
||||
temp = ""
|
||||
|
||||
else if(href_list["mainmenu"])
|
||||
temp = ""
|
||||
if(outgoing_call)
|
||||
outgoing_call.Disconnect()
|
||||
|
||||
updateDialog()
|
||||
|
||||
//do not allow AIs to answer calls or people will use it to meta the AI sattelite
|
||||
/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user)
|
||||
if (!istype(user))
|
||||
return
|
||||
@@ -148,39 +237,75 @@ Possible to do for anyone motivated enough:
|
||||
clear_holo(user)
|
||||
|
||||
/obj/machinery/holopad/process()
|
||||
if(masters.len)//If there is a hologram.
|
||||
for (var/mob/living/silicon/ai/master in masters)
|
||||
if(master && !master.stat && master.client && master.eyeobj)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
|
||||
if(!(stat & NOPOWER))//If the machine has power.
|
||||
if(HOLOPAD_MODE == RANGE_BASED)
|
||||
if(get_dist(master.eyeobj, src) <= holo_range)
|
||||
return TRUE
|
||||
else
|
||||
var/obj/machinery/holopad/pad_close = get_closest_atom(/obj/machinery/holopad, holopads, master.eyeobj)
|
||||
if(get_dist(pad_close, master.eyeobj) <= holo_range)
|
||||
var/obj/effect/overlay/holo_pad_hologram/h = masters[master]
|
||||
unset_holo(master)
|
||||
pad_close.set_holo(master, h)
|
||||
return TRUE
|
||||
for(var/I in masters)
|
||||
var/mob/living/master = I
|
||||
var/mob/living/silicon/ai/AI = master
|
||||
if(!istype(AI))
|
||||
AI = null
|
||||
|
||||
else if (HOLOPAD_MODE == AREA_BASED)
|
||||
if(!QDELETED(master) && !master.incapacitated() && master.client && (!AI || AI.eyeobj))//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
|
||||
if(is_operational())//If the machine has power.
|
||||
if(AI) //ais are range based
|
||||
if(get_dist(AI.eyeobj, src) <= holo_range)
|
||||
continue
|
||||
else
|
||||
var/obj/machinery/holopad/pad_close = get_closest_atom(/obj/machinery/holopad, holopads, AI.eyeobj)
|
||||
if(get_dist(pad_close, AI.eyeobj) <= holo_range)
|
||||
var/obj/effect/overlay/holo_pad_hologram/h = masters[master]
|
||||
unset_holo(master)
|
||||
pad_close.set_holo(master, h)
|
||||
continue
|
||||
else
|
||||
continue
|
||||
clear_holo(master)//If not, we want to get rid of the hologram.
|
||||
|
||||
var/area/holo_area = get_area(src)
|
||||
var/area/eye_area = get_area(master.eyeobj)
|
||||
if(outgoing_call)
|
||||
outgoing_call.Check()
|
||||
|
||||
if(eye_area in holo_area.related)
|
||||
return TRUE
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad != src)
|
||||
if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2)))
|
||||
HC.Answer(src)
|
||||
break
|
||||
if(outgoing_call)
|
||||
HC.Disconnect(src)//can't answer calls while calling
|
||||
else
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 100) //bring, bring!
|
||||
|
||||
clear_holo(master)//If not, we want to get rid of the hologram.
|
||||
return TRUE
|
||||
/obj/machinery/holopad/proc/activate_holo(mob/living/user)
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
if(!istype(AI))
|
||||
AI = null
|
||||
|
||||
/obj/machinery/holopad/proc/activate_holo(mob/living/silicon/ai/user)
|
||||
if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it
|
||||
if (istype(user.current, /obj/machinery/holopad))
|
||||
if(is_operational() && (!AI || AI.eyeobj.loc == loc))//If the projector has power and client eye is on it
|
||||
if (AI && istype(AI.current, /obj/machinery/holopad))
|
||||
to_chat(user, "<span class='danger'>ERROR:</span> \black Image feed in progress.")
|
||||
return
|
||||
create_holo(user)//Create one.
|
||||
src.visible_message("A holographic image of [user] flicks to life right before your eyes!")
|
||||
|
||||
var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location.
|
||||
if(AI)
|
||||
Hologram.icon = AI.holo_icon
|
||||
else //make it like real life
|
||||
Hologram.icon = user.icon
|
||||
Hologram.icon_state = user.icon_state
|
||||
Hologram.copy_overlays(user, TRUE)
|
||||
//codersprite some holo effects here
|
||||
Hologram.alpha = 100
|
||||
Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
|
||||
Hologram.Impersonation = user
|
||||
|
||||
Hologram.languages = user.languages
|
||||
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.
|
||||
Hologram.name = "[user.name] (Hologram)"//If someone decides to right click.
|
||||
Hologram.set_light(2) //hologram lighting
|
||||
|
||||
set_holo(user, Hologram)
|
||||
visible_message("A holographic image of [user] flicks to life right before your eyes!")
|
||||
|
||||
return Hologram
|
||||
else
|
||||
to_chat(user, "<span class='danger'>ERROR:</span> \black Unable to project hologram.")
|
||||
|
||||
@@ -192,58 +317,80 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
if(masters[master] && speaker != master)
|
||||
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
|
||||
/obj/machinery/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc)
|
||||
var/obj/effect/overlay/holo_pad_hologram/h = new(T)//Spawn a blank effect at the location.
|
||||
h.icon = A.holo_icon
|
||||
h.mouse_opacity = 0//So you can't click on it.
|
||||
h.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
|
||||
h.anchored = 1//So space wind cannot drag it.
|
||||
h.name = "[A.name] (Hologram)"//If someone decides to right click.
|
||||
h.set_light(2) //hologram lighting
|
||||
set_holo(A, h)
|
||||
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)
|
||||
|
||||
if(outgoing_call && speaker == outgoing_call.user)
|
||||
outgoing_call.hologram.say(raw_message)
|
||||
|
||||
/obj/machinery/holopad/proc/SetLightsAndPower()
|
||||
var/total_users = masters.len + LAZYLEN(holo_calls)
|
||||
use_power = HOLOPAD_PASSIVE_POWER_USAGE + HOLOGRAM_POWER_USAGE * total_users
|
||||
if(total_users)
|
||||
set_light(2)
|
||||
icon_state = "holopad1"
|
||||
else
|
||||
set_light(0)
|
||||
icon_state = "holopad0"
|
||||
|
||||
/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h)
|
||||
masters[user] = h
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
if(istype(AI))
|
||||
AI.current = src
|
||||
SetLightsAndPower()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/holopad/proc/set_holo(mob/living/silicon/ai/A, var/obj/effect/overlay/holo_pad_hologram/h)
|
||||
masters[A] = h
|
||||
set_light(2) // pad lighting
|
||||
icon_state = "holopad1"
|
||||
A.current = src
|
||||
use_power += HOLOGRAM_POWER_USAGE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/holopad/proc/clear_holo(mob/living/silicon/ai/user)
|
||||
/obj/machinery/holopad/proc/clear_holo(mob/living/user)
|
||||
qdel(masters[user]) // Get rid of user's hologram
|
||||
unset_holo(user)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/holopad/proc/unset_holo(mob/living/silicon/ai/user)
|
||||
if(user.current == src)
|
||||
user.current = null
|
||||
/obj/machinery/holopad/proc/unset_holo(mob/living/user)
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
if(istype(AI) && AI.current == src)
|
||||
AI.current = null
|
||||
masters -= user // Discard AI from the list of those who use holopad
|
||||
use_power = max(HOLOPAD_PASSIVE_POWER_USAGE, use_power - HOLOGRAM_POWER_USAGE)//Reduce power usage
|
||||
if (!masters.len) // If no users left
|
||||
set_light(0) // pad lighting (hologram lighting will be handled automatically since its owner was deleted)
|
||||
icon_state = "holopad0"
|
||||
use_power = HOLOPAD_PASSIVE_POWER_USAGE
|
||||
SetLightsAndPower()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/holopad/proc/move_hologram(mob/living/silicon/ai/user)
|
||||
/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf)
|
||||
if(masters[user])
|
||||
step_to(masters[user], user.eyeobj)
|
||||
var/obj/effect/overlay/holo_pad_hologram/H = masters[user]
|
||||
H.loc = get_turf(user.eyeobj)
|
||||
step_to(H, new_turf)
|
||||
H.loc = new_turf
|
||||
var/area/holo_area = get_area(src)
|
||||
var/area/eye_area = new_turf.loc
|
||||
|
||||
if(!(eye_area in holo_area.related))
|
||||
clear_holo(user)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/overlay/holo_pad_hologram
|
||||
var/mob/living/Impersonation
|
||||
var/datum/holocall/HC
|
||||
|
||||
/obj/effect/overlay/holo_pad_hologram/Destroy()
|
||||
Impersonation = null
|
||||
if(HC)
|
||||
HC.Disconnect(HC.calling_holopad)
|
||||
return ..()
|
||||
|
||||
/obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0)
|
||||
return 1
|
||||
|
||||
/obj/effect/overlay/holo_pad_hologram/examine(mob/user)
|
||||
if(Impersonation)
|
||||
return Impersonation.examine(user)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/circuitboard/machine/holopad
|
||||
name = "AI Holopad (Machine Board)"
|
||||
build_path = /obj/machinery/holopad
|
||||
origin_tech = "programming=1"
|
||||
req_components = list(/obj/item/weapon/stock_parts/capacitor = 1)
|
||||
|
||||
#undef RANGE_BASED
|
||||
#undef AREA_BASED
|
||||
#undef HOLOPAD_PASSIVE_POWER_USAGE
|
||||
#undef HOLOGRAM_POWER_USAGE
|
||||
#undef HOLOGRAM_POWER_USAGE
|
||||
@@ -535,7 +535,7 @@ GLOBAL_LIST_EMPTY(allCasters)
|
||||
if(choice=="Confirm")
|
||||
scan_user(usr)
|
||||
GLOB.news_network.CreateFeedChannel(channel_name, scanned_user, c_locked)
|
||||
feedback_inc("newscaster_channels",1)
|
||||
SSblackbox.inc("newscaster_channels",1)
|
||||
screen=5
|
||||
updateUsrDialog()
|
||||
else if(href_list["set_channel_receiving"])
|
||||
@@ -558,7 +558,7 @@ GLOBAL_LIST_EMPTY(allCasters)
|
||||
screen=6
|
||||
else
|
||||
GLOB.news_network.SubmitArticle("<font face=\"[PEN_FONT]\">[parsepencode(msg, usr, SIGNFONT)]</font>", scanned_user, channel_name, photo, 0, allow_comments)
|
||||
feedback_inc("newscaster_stories",1)
|
||||
SSblackbox.inc("newscaster_stories",1)
|
||||
screen=4
|
||||
msg = ""
|
||||
updateUsrDialog()
|
||||
@@ -850,7 +850,7 @@ GLOBAL_LIST_EMPTY(allCasters)
|
||||
return
|
||||
|
||||
/obj/machinery/newscaster/proc/print_paper()
|
||||
feedback_inc("newscaster_newspapers_printed",1)
|
||||
SSblackbox.inc("newscaster_newspapers_printed",1)
|
||||
var/obj/item/weapon/newspaper/NEWSPAPER = new /obj/item/weapon/newspaper
|
||||
for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels)
|
||||
NEWSPAPER.news_content += FC
|
||||
|
||||
@@ -251,6 +251,8 @@ GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
var/mob/living/carbon/C = user
|
||||
for(var/i=1 to 20)
|
||||
C.vomit(0,1,0,4,0)
|
||||
if(prob(20))
|
||||
C.spew_organ()
|
||||
sleep(5)
|
||||
C.blood_volume = 0
|
||||
return(OXYLOSS|BRUTELOSS)
|
||||
|
||||
@@ -364,6 +364,10 @@
|
||||
var/list/targets = list()
|
||||
var/turretview = view(scan_range, base)
|
||||
for(var/A in turretview)
|
||||
var/atom/AA = A
|
||||
if(AA.invisibility>SEE_INVISIBLE_LIVING)
|
||||
continue
|
||||
|
||||
if(check_anomalies)//if it's set to check for simple animals
|
||||
if(istype(A, /mob/living/simple_animal))
|
||||
var/mob/living/simple_animal/SA = A
|
||||
|
||||
@@ -144,30 +144,7 @@
|
||||
// --- This following recording is intended for research and feedback in the use of department radio channels ---
|
||||
|
||||
var/blackbox_msg = "[AM] [AM.say_quote(message, spans)]"
|
||||
if(istype(GLOB.blackbox))
|
||||
switch(freq)
|
||||
if(1459)
|
||||
GLOB.blackbox.msg_common += blackbox_msg
|
||||
if(1351)
|
||||
GLOB.blackbox.msg_science += blackbox_msg
|
||||
if(1353)
|
||||
GLOB.blackbox.msg_command += blackbox_msg
|
||||
if(1355)
|
||||
GLOB.blackbox.msg_medical += blackbox_msg
|
||||
if(1357)
|
||||
GLOB.blackbox.msg_engineering += blackbox_msg
|
||||
if(1359)
|
||||
GLOB.blackbox.msg_security += blackbox_msg
|
||||
if(1441)
|
||||
GLOB.blackbox.msg_deathsquad += blackbox_msg
|
||||
if(1213)
|
||||
GLOB.blackbox.msg_syndicate += blackbox_msg
|
||||
if(1349)
|
||||
GLOB.blackbox.msg_service += blackbox_msg
|
||||
if(1347)
|
||||
GLOB.blackbox.msg_cargo += blackbox_msg
|
||||
else
|
||||
GLOB.blackbox.messages += blackbox_msg
|
||||
SSblackbox.LogBroadcast(blackbox_msg, freq)
|
||||
|
||||
sleep(50)
|
||||
if(!QDELETED(virt)) //It could happen to YOU
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
var/dish_quants = list() //used by the snack machine's custom compartment to count dishes.
|
||||
|
||||
var/obj/item/weapon/vending_refill/refill_canister = null //The type of refill canisters used by this machine.
|
||||
var/refill_count = 3 //The number of canisters the vending machine uses
|
||||
|
||||
/obj/machinery/vending/Initialize()
|
||||
..()
|
||||
@@ -88,7 +89,9 @@
|
||||
/obj/machinery/vending/cola = "Robust Softdrinks",
|
||||
/obj/machinery/vending/cigarette = "ShadyCigs Deluxe",
|
||||
/obj/machinery/vending/autodrobe = "AutoDrobe",
|
||||
/obj/machinery/vending/clothing = "ClothesMate")
|
||||
/obj/machinery/vending/clothing = "ClothesMate",
|
||||
/obj/machinery/vending/medical = "NanoMed Plus",
|
||||
/obj/machinery/vending/wallmed = "NanoMed")
|
||||
|
||||
/obj/item/weapon/circuitboard/machine/vendor/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/weapon/screwdriver))
|
||||
@@ -104,7 +107,7 @@
|
||||
/obj/item/weapon/circuitboard/machine/vendor/proc/set_type(var/obj/machinery/vending/typepath)
|
||||
build_path = typepath
|
||||
name = "[names_paths[build_path]] Vendor (Machine Board)"
|
||||
req_components = list(initial(typepath.refill_canister) = 3)
|
||||
req_components = list(initial(typepath.refill_canister) = initial(typepath.refill_count))
|
||||
|
||||
/obj/item/weapon/circuitboard/machine/vendor/apply_default_parts(obj/machinery/M)
|
||||
for(var/typepath in names_paths)
|
||||
@@ -113,7 +116,6 @@
|
||||
break
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/vending/Destroy()
|
||||
qdel(wires)
|
||||
wires = null
|
||||
@@ -297,7 +299,7 @@
|
||||
to_chat(user, "<span class='notice'>You [panel_open ? "open" : "close"] the maintenance panel.</span>")
|
||||
cut_overlays()
|
||||
if(panel_open)
|
||||
add_overlay("[initial(icon_state)]-panel")
|
||||
add_overlay("[initial(icon_state)]-panel")
|
||||
playsound(src.loc, W.usesound, 50, 1)
|
||||
updateUsrDialog()
|
||||
else
|
||||
@@ -307,7 +309,10 @@
|
||||
if(panel_open)
|
||||
attack_hand(user)
|
||||
return
|
||||
else if(istype(W, /obj/item/weapon/coin) && premium.len > 0)
|
||||
else if(istype(W, /obj/item/weapon/coin))
|
||||
if(!premium.len)
|
||||
to_chat(user, "<span class='warning'>[src] doesn't have a coin slot.</span>")
|
||||
return
|
||||
if(!user.drop_item())
|
||||
return
|
||||
W.loc = src
|
||||
@@ -528,7 +533,7 @@
|
||||
if(icon_vend) //Show the vending animation if needed
|
||||
flick(icon_vend,src)
|
||||
new R.product_path(get_turf(src))
|
||||
feedback_add_details("vending_machine_usage","[src.type]|[R.product_path]")
|
||||
SSblackbox.add_details("vending_machine_usage","[src.type]|[R.product_path]")
|
||||
vend_ready = 1
|
||||
return
|
||||
|
||||
@@ -732,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,
|
||||
@@ -750,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
|
||||
@@ -874,6 +879,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
|
||||
premium = list(/obj/item/weapon/storage/box/hug/medical = 1,/obj/item/weapon/reagent_containers/hypospray/medipen = 3, /obj/item/weapon/storage/belt/medical = 3, /obj/item/weapon/wrench/medical = 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
|
||||
refill_canister = /obj/item/weapon/vending_refill/medical
|
||||
|
||||
//This one's from bay12
|
||||
/obj/machinery/vending/plasmaresearch
|
||||
@@ -896,6 +902,8 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
|
||||
contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 2,/obj/item/weapon/reagent_containers/pill/morphine = 2)
|
||||
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
refill_canister = /obj/item/weapon/vending_refill/medical
|
||||
refill_count = 1
|
||||
|
||||
/obj/machinery/vending/security
|
||||
name = "\improper SecTech"
|
||||
@@ -1120,7 +1128,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
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
icon_state = "mecha_ion"
|
||||
origin_tech = "materials=4;engineering=4;combat=6;magnets=6"
|
||||
energy_drain = 500
|
||||
projectile = /obj/item/projectile/energy/tesla_cannon
|
||||
projectile = /obj/item/projectile/energy/tesla/cannon
|
||||
fire_sound = 'sound/magic/lightningbolt.ogg'
|
||||
|
||||
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
|
||||
/datum/construction/reversible/mecha/ripley/spawn_result()
|
||||
..()
|
||||
feedback_inc("mecha_ripley_created",1)
|
||||
SSblackbox.inc("mecha_ripley_created",1)
|
||||
return
|
||||
|
||||
|
||||
@@ -564,7 +564,7 @@
|
||||
var/obj/mecha/combat/gygax/M = new result(get_turf(holder))
|
||||
M.CheckParts(holder.contents)
|
||||
qdel(holder)
|
||||
feedback_inc("mecha_gygax_created",1)
|
||||
SSblackbox.inc("mecha_gygax_created",1)
|
||||
return
|
||||
|
||||
/datum/construction/mecha/firefighter_chassis
|
||||
@@ -786,7 +786,7 @@
|
||||
|
||||
/datum/construction/reversible/mecha/firefighter/spawn_result()
|
||||
..()
|
||||
feedback_inc("mecha_firefighter_created",1)
|
||||
SSblackbox.inc("mecha_firefighter_created",1)
|
||||
return
|
||||
|
||||
|
||||
@@ -864,7 +864,7 @@
|
||||
|
||||
/datum/construction/mecha/honker/spawn_result()
|
||||
..()
|
||||
feedback_inc("mecha_honker_created",1)
|
||||
SSblackbox.inc("mecha_honker_created",1)
|
||||
return
|
||||
|
||||
/datum/construction/mecha/durand_chassis
|
||||
@@ -1149,7 +1149,7 @@
|
||||
var/obj/mecha/combat/gygax/M = new result(get_turf(holder))
|
||||
M.CheckParts(holder.contents)
|
||||
qdel(holder)
|
||||
feedback_inc("mecha_durand_created",1)
|
||||
SSblackbox.inc("mecha_durand_created",1)
|
||||
return
|
||||
|
||||
//PHAZON
|
||||
@@ -1481,7 +1481,7 @@
|
||||
var/obj/mecha/combat/gygax/M = new result(get_turf(holder))
|
||||
M.CheckParts(holder.contents)
|
||||
qdel(holder)
|
||||
feedback_inc("mecha_phazon_created",1)
|
||||
SSblackbox.inc("mecha_phazon_created",1)
|
||||
return
|
||||
|
||||
//ODYSSEUS
|
||||
@@ -1692,5 +1692,5 @@
|
||||
|
||||
/datum/construction/reversible/mecha/odysseus/spawn_result()
|
||||
..()
|
||||
feedback_inc("mecha_odysseus_created",1)
|
||||
SSblackbox.inc("mecha_odysseus_created",1)
|
||||
return
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
name = "Head of Personnel"
|
||||
|
||||
/obj/effect/landmark/start/librarian
|
||||
name = "Librarian"
|
||||
name = "Curator"
|
||||
|
||||
/obj/effect/landmark/start/lawyer
|
||||
name = "Lawyer"
|
||||
|
||||
@@ -323,11 +323,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 +355,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)
|
||||
. = ..()
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
diff a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm (rejected hunks)
|
||||
@@ -31,8 +31,8 @@
|
||||
. = ..()
|
||||
deltimer(timerid)
|
||||
|
||||
-/obj/effect/overlay/temp/New()
|
||||
- ..()
|
||||
+/obj/effect/overlay/temp/Initialize()
|
||||
+ . = ..()
|
||||
if(randomdir)
|
||||
setDir(pick(GLOB.cardinal))
|
||||
flick("[icon_state]", src) //Because we might be pulling it from a pool, flick whatever icon it uses so it starts at the start of the icon's animation.
|
||||
@@ -214,7 +221,7 @@
|
||||
icon = 'icons/effects/fire.dmi'
|
||||
icon_state = "3"
|
||||
duration = 20
|
||||
-
|
||||
+
|
||||
/obj/effect/overlay/temp/cult
|
||||
randomdir = 0
|
||||
duration = 10
|
||||
@@ -9,10 +9,12 @@
|
||||
host = _host
|
||||
last_host_loc = _host.loc
|
||||
ignore_if_not_on_turf = _ignore_if_not_on_turf
|
||||
checkers = list()
|
||||
SetRange(range)
|
||||
|
||||
/datum/proximity_monitor/Destroy()
|
||||
host = null
|
||||
last_host_loc = null
|
||||
QDEL_LIST(checkers)
|
||||
return ..()
|
||||
|
||||
@@ -34,46 +36,47 @@
|
||||
|
||||
current_range = range
|
||||
|
||||
var/list/old_checkers = checkers
|
||||
var/old_checkers_len = LAZYLEN(old_checkers)
|
||||
var/list/checkers_local = checkers
|
||||
var/old_checkers_len = checkers_local.len
|
||||
|
||||
var/atom/host_loc = host.loc
|
||||
var/atom/_host = host
|
||||
|
||||
var/atom/loc_to_use = ignore_if_not_on_turf ? host_loc : get_turf(host)
|
||||
var/atom/loc_to_use = ignore_if_not_on_turf ? _host.loc : get_turf(_host)
|
||||
if(!isturf(loc_to_use)) //only check the host's loc
|
||||
if(range)
|
||||
var/obj/effect/abstract/proximity_checker/pc
|
||||
if(old_checkers_len)
|
||||
pc = old_checkers[old_checkers_len]
|
||||
--old_checkers.len
|
||||
pc = checkers_local[old_checkers_len]
|
||||
--checkers_local.len
|
||||
QDEL_LIST(checkers_local)
|
||||
else
|
||||
pc = new(host_loc, src)
|
||||
pc = new(loc_to_use, src)
|
||||
|
||||
checkers = list(pc) //only check the host's loc
|
||||
checkers_local += pc //only check the host's loc
|
||||
return
|
||||
|
||||
var/list/turfs = RANGE_TURFS(range, loc_to_use)
|
||||
var/old_checkers_used = min(turfs.len, old_checkers_len)
|
||||
var/turfs_len = turfs.len
|
||||
var/old_checkers_used = min(turfs_len, old_checkers_len)
|
||||
|
||||
//reuse what we can
|
||||
for(var/I in 1 to old_checkers_len)
|
||||
if(I <= old_checkers_used)
|
||||
var/obj/effect/abstract/proximity_checker/pc = old_checkers[I]
|
||||
var/obj/effect/abstract/proximity_checker/pc = checkers_local[I]
|
||||
pc.loc = turfs[I]
|
||||
else
|
||||
qdel(old_checkers[I]) //delete the leftovers
|
||||
qdel(checkers_local[I]) //delete the leftovers
|
||||
|
||||
LAZYCLEARLIST(old_checkers)
|
||||
|
||||
//create what we lack
|
||||
var/list/checkers_local = list()
|
||||
for(var/I in (old_checkers_used + 1) to turfs.len)
|
||||
checkers_local += new /obj/effect/abstract/proximity_checker(turfs[I], src)
|
||||
|
||||
checkers = checkers_local
|
||||
if(old_checkers_len < turfs_len)
|
||||
//create what we lack
|
||||
for(var/I in (old_checkers_used + 1) to turfs_len)
|
||||
checkers_local += new /obj/effect/abstract/proximity_checker(turfs[I], src)
|
||||
else
|
||||
checkers_local.Cut(old_checkers_used + 1, old_checkers_len)
|
||||
|
||||
/obj/effect/abstract/proximity_checker
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
anchored = TRUE
|
||||
var/datum/proximity_monitor/monitor
|
||||
|
||||
/obj/effect/abstract/proximity_checker/Initialize(mapload, datum/proximity_monitor/_monitor)
|
||||
@@ -81,8 +84,8 @@
|
||||
if(_monitor)
|
||||
monitor = _monitor
|
||||
else
|
||||
stack_trace("proximity_checker created without proximity_monitor")
|
||||
qdel(src)
|
||||
stack_trace("proximity_checker created without host")
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/abstract/proximity_checker/Destroy()
|
||||
monitor = null
|
||||
@@ -90,9 +93,6 @@
|
||||
|
||||
/obj/effect/abstract/proximity_checker/Crossed(atom/movable/AM)
|
||||
set waitfor = FALSE
|
||||
var/datum/proximity_monitor/M = monitor
|
||||
if(!M.current_range)
|
||||
return
|
||||
var/atom/H = M.host
|
||||
var/atom/H = monitor.host
|
||||
testing("HasProx: [H] -> [AM]")
|
||||
H.HasProximity(AM)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
diff a/code/game/objects/items.dm b/code/game/objects/items.dm (rejected hunks)
|
||||
@@ -102,7 +102,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
|
||||
/obj/item/Initialize()
|
||||
if (!materials)
|
||||
materials = list()
|
||||
- ..()
|
||||
+ . = ..()
|
||||
for(var/path in actions_types)
|
||||
new path(src)
|
||||
actions_types = null
|
||||
@@ -86,7 +86,7 @@
|
||||
name = "station charter for [station_name()]"
|
||||
desc = "An official document entrusting the governance of \
|
||||
[station_name()] and surrounding space to Captain [uname]."
|
||||
feedback_set_details("station_renames","[station_name()]")
|
||||
SSblackbox.set_details("station_renames","[station_name()]")
|
||||
if(!unlimited_uses)
|
||||
used = TRUE
|
||||
|
||||
|
||||
@@ -161,11 +161,11 @@
|
||||
icon_state = "pda-roboticist"
|
||||
default_cartridge = /obj/item/weapon/cartridge/roboticist
|
||||
|
||||
/obj/item/device/pda/librarian
|
||||
name = "librarian PDA"
|
||||
/obj/item/device/pda/curator
|
||||
name = "curator PDA"
|
||||
icon_state = "pda-library"
|
||||
icon_alert = "pda-r-library"
|
||||
default_cartridge = /obj/item/weapon/cartridge/librarian
|
||||
default_cartridge = /obj/item/weapon/cartridge/curator
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a WGW-11 series e-reader."
|
||||
note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!"
|
||||
silent = 1 //Quiet in the library!
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
access_mime = 1
|
||||
var/mime_charges = 5
|
||||
|
||||
/obj/item/weapon/cartridge/librarian
|
||||
/obj/item/weapon/cartridge/curator
|
||||
name = "\improper Lib-Tweet cartridge"
|
||||
icon_state = "cart-s"
|
||||
access_newscaster = 1
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
return 1
|
||||
|
||||
|
||||
/obj/item/device/flashlight/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
|
||||
/obj/item/device/flashlight/attack(mob/living/carbon/M, mob/living/carbon/human/user)
|
||||
add_fingerprint(user)
|
||||
if(on && user.zone_selected == "eyes")
|
||||
if(istype(M) && on && user.zone_selected in list("eyes", "mouth"))
|
||||
|
||||
if((user.disabilities & CLUMSY || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly
|
||||
return ..() //just hit them in the head
|
||||
@@ -48,28 +48,101 @@
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/H = M //mob has protective eyewear
|
||||
if(ishuman(M) && ((H.head && H.head.flags_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES)))
|
||||
to_chat(user, "<span class='notice'>You're going to need to remove that [(H.head && H.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first.</span>")
|
||||
if(!M.get_bodypart("head"))
|
||||
to_chat(user, "<span class='warning'>[M] doesn't have a head!</span>")
|
||||
return
|
||||
|
||||
if(M == user) //they're using it on themselves
|
||||
if(M.flash_act(visual = 1))
|
||||
M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "<span class='notice'>You wave the light in front of your eyes! Trippy!</span>")
|
||||
else
|
||||
M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "<span class='notice'>You wave the light in front of your eyes.</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] directs [src] to [M]'s eyes.</span>", \
|
||||
"<span class='danger'>You direct [src] to [M]'s eyes.</span>")
|
||||
var/mob/living/carbon/C = M
|
||||
if(istype(C))
|
||||
if(C.stat == DEAD || (C.disabilities & BLIND)) //mob is dead or fully blind
|
||||
to_chat(user, "<span class='warning'>[C] pupils don't react to the light!</span>")
|
||||
else if(C.dna.check_mutation(XRAY)) //mob has X-RAY vision
|
||||
to_chat(user, "<span class='danger'>[C] pupils give an eerie glow!</span>")
|
||||
else //they're okay!
|
||||
if(C.flash_act(visual = 1))
|
||||
to_chat(user, "<span class='notice'>[C]'s pupils narrow.</span>")
|
||||
switch(user.zone_selected)
|
||||
if("eyes")
|
||||
if((M.head && M.head.flags_cover & HEADCOVERSEYES) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) || (M.glasses && M.glasses.flags_cover & GLASSESCOVERSEYES))
|
||||
to_chat(user, "<span class='notice'>You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first.</span>")
|
||||
return
|
||||
|
||||
var/obj/item/organ/eyes/E = M.getorganslot("eye_sight")
|
||||
if(!E)
|
||||
to_chat(user, "<span class='danger'>[M] doesn't have any eyes!</span>")
|
||||
return
|
||||
|
||||
if(M == user) //they're using it on themselves
|
||||
if(M.flash_act(visual = 1))
|
||||
M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "<span class='notice'>You wave the light in front of your eyes! Trippy!</span>")
|
||||
else
|
||||
M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "<span class='notice'>You wave the light in front of your eyes.</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] directs [src] to [M]'s eyes.</span>", \
|
||||
"<span class='danger'>You direct [src] to [M]'s eyes.</span>")
|
||||
if(M.stat == DEAD || (M.disabilities & BLIND) || !M.flash_act(visual = 1)) //mob is dead or fully blind
|
||||
to_chat(user, "<span class='warning'>[M]'s pupils don't react to the light!</span>")
|
||||
else if(M.dna && M.dna.check_mutation(XRAY)) //mob has X-RAY vision
|
||||
to_chat(user, "<span class='danger'>[M]'s pupils give an eerie glow!</span>")
|
||||
else //they're okay!
|
||||
to_chat(user, "<span class='notice'>[M]'s pupils narrow.</span>")
|
||||
|
||||
if("mouth")
|
||||
|
||||
if((M.head && M.head.flags_cover & HEADCOVERSMOUTH) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
|
||||
to_chat(user, "<span class='notice'>You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first.</span>")
|
||||
return
|
||||
|
||||
var/their = M.p_their()
|
||||
|
||||
var/list/mouth_organs = new
|
||||
for(var/obj/item/organ/O in M.internal_organs)
|
||||
if(O.zone == "mouth")
|
||||
mouth_organs.Add(O)
|
||||
var/organ_list = ""
|
||||
var/organ_count = LAZYLEN(mouth_organs)
|
||||
if(organ_count)
|
||||
for(var/I in 1 to organ_count)
|
||||
if(I > 1)
|
||||
if(I == mouth_organs.len)
|
||||
organ_list += ", and "
|
||||
else
|
||||
organ_list += ", "
|
||||
var/obj/item/organ/O = mouth_organs[I]
|
||||
organ_list += (O.gender == "plural" ? O.name : "\an [O.name]")
|
||||
|
||||
var/pill_count = 0
|
||||
for(var/datum/action/item_action/hands_free/activate_pill/AP in M.actions)
|
||||
pill_count++
|
||||
|
||||
if(M == user)
|
||||
var/can_use_mirror = FALSE
|
||||
if(isturf(user.loc))
|
||||
var/obj/structure/mirror/mirror = locate(/obj/structure/mirror, user.loc)
|
||||
if(mirror)
|
||||
switch(user.dir)
|
||||
if(NORTH)
|
||||
can_use_mirror = mirror.pixel_y > 0
|
||||
if(SOUTH)
|
||||
can_use_mirror = mirror.pixel_y < 0
|
||||
if(EAST)
|
||||
can_use_mirror = mirror.pixel_x > 0
|
||||
if(WEST)
|
||||
can_use_mirror = mirror.pixel_x < 0
|
||||
|
||||
M.visible_message("[M] directs [src] to [their] mouth.", \
|
||||
"<span class='notice'>You point [src] into your mouth.</span>")
|
||||
if(!can_use_mirror)
|
||||
to_chat(user, "<span class='notice'>You can't see anything without a mirror.</span>")
|
||||
return
|
||||
if(organ_count)
|
||||
to_chat(user, "<span class='notice'>Inside your mouth [organ_count > 1 ? "are" : "is"] [organ_list].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There's nothing inside your mouth.</span>")
|
||||
if(pill_count)
|
||||
to_chat(user, "<span class='notice'>You have [pill_count] implanted pill[pill_count > 1 ? "s" : ""].</span>")
|
||||
|
||||
else
|
||||
user.visible_message("<span class='notice'>[user] directs [src] to [M]'s mouth.</span>",\
|
||||
"<span class='notice'>You direct [src] to [M]'s mouth.</span>")
|
||||
if(organ_count)
|
||||
to_chat(user, "<span class='notice'>Inside [their] mouth [organ_count > 1 ? "are" : "is"] [organ_list].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[M] doesn't have any organs in [their] mouth.</span>")
|
||||
if(pill_count)
|
||||
to_chat(user, "<span class='notice'>[M] has [pill_count] pill[pill_count > 1 ? "s" : ""] implanted in [their] teeth.")
|
||||
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -280,7 +353,7 @@
|
||||
return TRUE
|
||||
|
||||
/obj/item/device/flashlight/emp/attack(mob/living/M, mob/living/user)
|
||||
if(on && user.zone_selected == "eyes") // call original attack proc only if aiming at the eyes
|
||||
if(on && user.zone_selected in list("eyes", "mouth")) // call original attack when examining organs
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
. = ..()
|
||||
@@ -296,6 +296,7 @@
|
||||
// --- Cold, emotionless machines. ---
|
||||
else if(isobj(M))
|
||||
jobname = "Machine"
|
||||
voice = capitalize(voice)
|
||||
|
||||
// --- Unidentifiable mob ---
|
||||
else
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
if(src.l_arm && src.r_arm)
|
||||
if(src.l_leg && src.r_leg)
|
||||
if(src.chest && src.head)
|
||||
feedback_inc("cyborg_frames_built",1)
|
||||
SSblackbox.inc("cyborg_frames_built",1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -235,7 +235,7 @@
|
||||
O.mmi = W //and give the real mmi to the borg.
|
||||
O.updatename()
|
||||
|
||||
feedback_inc("cyborg_birth",1)
|
||||
SSblackbox.inc("cyborg_birth",1)
|
||||
|
||||
forceMove(O)
|
||||
O.robot_suit = src
|
||||
|
||||
@@ -237,6 +237,7 @@
|
||||
/obj/item/borg/upgrade/selfrepair/proc/check_dropped()
|
||||
if(loc != cyborg)
|
||||
toggle_action.Remove(cyborg)
|
||||
QDEL_NULL(toggle_action)
|
||||
cyborg = null
|
||||
deactivate()
|
||||
|
||||
@@ -399,4 +400,4 @@
|
||||
return
|
||||
|
||||
R.make_shell(src)
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -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", ???), \
|
||||
@@ -334,12 +335,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
|
||||
*/
|
||||
|
||||
@@ -328,7 +328,7 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \
|
||||
|
||||
/obj/item/stack/tile/brass/Initialize(mapload, new_amount, merge = TRUE)
|
||||
recipes = GLOB.brass_recipes
|
||||
..()
|
||||
. = ..()
|
||||
pixel_x = 0
|
||||
pixel_y = 0
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
var/turf_type = null
|
||||
var/mineralType = null
|
||||
|
||||
/obj/item/stack/tile/New(loc, amount)
|
||||
..()
|
||||
/obj/item/stack/tile/Initialize(mapload, amount)
|
||||
. = ..()
|
||||
pixel_x = rand(-3, 3)
|
||||
pixel_y = rand(-3, 3) //randomize a little
|
||||
|
||||
@@ -88,6 +88,14 @@
|
||||
turf_type = /turf/open/floor/wood
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
//Basalt
|
||||
/obj/item/stack/tile/basalt
|
||||
name = "basalt tile"
|
||||
singular_name = "basalt floor tile"
|
||||
desc = "Artificially made ashy soil themed on a hostile enviroment."
|
||||
icon_state = "tile_basalt"
|
||||
origin_tech = "materials=1"
|
||||
turf_type = /turf/open/floor/grass/fakebasalt
|
||||
|
||||
//Carpets
|
||||
/obj/item/stack/tile/carpet
|
||||
|
||||
@@ -1218,9 +1218,9 @@
|
||||
icon_state = "lawyer"
|
||||
toysay = "My client is a dirty traitor!"
|
||||
|
||||
/obj/item/toy/figure/librarian
|
||||
name = "Librarian action figure"
|
||||
icon_state = "librarian"
|
||||
/obj/item/toy/figure/curator
|
||||
name = "Curator action figure"
|
||||
icon_state = "curator"
|
||||
toysay = "One day while..."
|
||||
|
||||
/obj/item/toy/figure/md
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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,5 +1,5 @@
|
||||
/obj/item/weapon/grenade/spawnergrenade
|
||||
desc = "It will unleash unleash an unspecified anomaly into the vicinity."
|
||||
desc = "It will unleash an unspecified anomaly into the vicinity."
|
||||
name = "delivery grenade"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "delivery"
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
if(do_mob(user, C, 30) && (C.get_num_arms() >= 2 || C.get_arm_ignore()))
|
||||
apply_cuffs(C,user)
|
||||
to_chat(user, "<span class='notice'>You handcuff [C].</span>")
|
||||
feedback_add_details("handcuffs","[type]")
|
||||
SSblackbox.add_details("handcuffs","[type]")
|
||||
|
||||
add_logs(user, C, "handcuffed")
|
||||
else
|
||||
@@ -275,7 +275,7 @@
|
||||
C.legcuffed = src
|
||||
src.loc = C
|
||||
C.update_inv_legcuffed()
|
||||
feedback_add_details("handcuffs","[type]")
|
||||
SSblackbox.add_details("handcuffs","[type]")
|
||||
else if(isanimal(L))
|
||||
var/mob/living/simple_animal/SA = L
|
||||
if(SA.mob_size > MOB_SIZE_TINY)
|
||||
@@ -336,7 +336,7 @@
|
||||
C.legcuffed = src
|
||||
src.loc = C
|
||||
C.update_inv_legcuffed()
|
||||
feedback_add_details("handcuffs","[type]")
|
||||
SSblackbox.add_details("handcuffs","[type]")
|
||||
to_chat(C, "<span class='userdanger'>\The [src] ensnares you!</span>")
|
||||
C.Weaken(weaken)
|
||||
|
||||
|
||||
@@ -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)
|
||||
..()
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
SSreligion.holy_weapon_type = holy_weapon.type
|
||||
|
||||
feedback_set_details("chaplain_weapon","[choice]")
|
||||
SSblackbox.set_details("chaplain_weapon","[choice]")
|
||||
|
||||
if(holy_weapon)
|
||||
holy_weapon.reskinned = TRUE
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
|
||||
SSreligion.bible_icon_state = B.icon_state
|
||||
SSreligion.bible_item_state = B.item_state
|
||||
|
||||
feedback_set_details("religion_book","[biblename]")
|
||||
SSblackbox.set_details("religion_book","[biblename]")
|
||||
usr << browse(null, "window=editicon")
|
||||
|
||||
/obj/item/weapon/storage/book/bible/proc/bless(mob/living/carbon/human/H, mob/living/user)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user