Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into disablesnolegs
This commit is contained in:
@@ -15,7 +15,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
var/antag_memory = ""//These will be removed with antag datum
|
||||
var/antag_moodlet //typepath of moodlet that the mob will gain with their status
|
||||
var/can_hijack = HIJACK_NEUTRAL //If these antags are alone on shuttle hijack happens.
|
||||
|
||||
|
||||
//Antag panel properties
|
||||
var/show_in_antagpanel = TRUE //This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind
|
||||
var/antagpanel_category = "Uncategorized" //Antagpanel will display these together, REQUIRED
|
||||
@@ -87,7 +87,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
|
||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
|
||||
owner.current.ghostize(0)
|
||||
owner.current.key = C.key
|
||||
C.transfer_ckey(owner.current, FALSE)
|
||||
|
||||
/datum/antagonist/proc/on_removal()
|
||||
remove_innate_effects()
|
||||
@@ -96,7 +96,6 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
LAZYREMOVE(owner.antag_datums, src)
|
||||
if(!silent && owner.current)
|
||||
farewell()
|
||||
owner.objectives -= objectives
|
||||
var/datum/team/team = get_team()
|
||||
if(team)
|
||||
team.remove_member(owner)
|
||||
@@ -132,14 +131,14 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
report += printplayer(owner)
|
||||
|
||||
var/objectives_complete = TRUE
|
||||
if(owner.objectives.len)
|
||||
report += printobjectives(owner)
|
||||
for(var/datum/objective/objective in owner.objectives)
|
||||
if(objectives.len)
|
||||
report += printobjectives(objectives)
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(!objective.check_completion())
|
||||
objectives_complete = FALSE
|
||||
break
|
||||
|
||||
if(owner.objectives.len == 0 || objectives_complete)
|
||||
if(objectives.len == 0 || objectives_complete)
|
||||
report += "<span class='greentext big'>The [name] was successful!</span>"
|
||||
else
|
||||
report += "<span class='redtext big'>The [name] has failed!</span>"
|
||||
@@ -216,25 +215,6 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
return
|
||||
antag_memory = new_memo
|
||||
|
||||
//This datum will autofill the name with special_role
|
||||
//Used as placeholder for minor antagonists, please create proper datums for these
|
||||
/datum/antagonist/auto_custom
|
||||
show_in_antagpanel = FALSE
|
||||
antagpanel_category = "Other"
|
||||
show_name_in_check_antagonists = TRUE
|
||||
|
||||
/datum/antagonist/auto_custom/on_gain()
|
||||
..()
|
||||
name = owner.special_role
|
||||
//Add all objectives not already owned by other datums to this one.
|
||||
var/list/already_registered_objectives = list()
|
||||
for(var/datum/antagonist/A in owner.antag_datums)
|
||||
if(A == src)
|
||||
continue
|
||||
else
|
||||
already_registered_objectives |= A.objectives
|
||||
objectives = owner.objectives - already_registered_objectives
|
||||
|
||||
//This one is created by admin tools for custom objectives
|
||||
/datum/antagonist/custom
|
||||
antagpanel_category = "Custom"
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
if(used)
|
||||
to_chat(H, "You already used this contract!")
|
||||
return
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, null, ROLE_WIZARD, 150, src)
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, null, ROLE_WIZARD, 150, src, ignore_category = POLL_IGNORE_WIZARD)
|
||||
if(LAZYLEN(candidates))
|
||||
if(QDELETED(src))
|
||||
return
|
||||
@@ -182,6 +182,10 @@
|
||||
name = "syndicate medical teleporter"
|
||||
borg_to_spawn = "Medical"
|
||||
|
||||
/obj/item/antag_spawner/nuke_ops/borg_tele/saboteur
|
||||
name = "syndicate saboteur teleporter"
|
||||
borg_to_spawn = "Saboteur"
|
||||
|
||||
/obj/item/antag_spawner/nuke_ops/borg_tele/spawn_antag(client/C, turf/T, kind, datum/mind/user)
|
||||
var/mob/living/silicon/robot/R
|
||||
var/datum/antagonist/nukeop/creator_op = user.has_antag_datum(/datum/antagonist/nukeop,TRUE)
|
||||
@@ -191,6 +195,8 @@
|
||||
switch(borg_to_spawn)
|
||||
if("Medical")
|
||||
R = new /mob/living/silicon/robot/modules/syndicate/medical(T)
|
||||
if("Saboteur")
|
||||
R = new /mob/living/silicon/robot/modules/syndicate/saboteur(T)
|
||||
else
|
||||
R = new /mob/living/silicon/robot/modules/syndicate(T) //Assault borg by default
|
||||
|
||||
@@ -235,7 +241,7 @@
|
||||
return
|
||||
if(used)
|
||||
return
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, src)
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, src, ignore_category = POLL_IGNORE_DEMON)
|
||||
if(LAZYLEN(candidates))
|
||||
if(used || QDELETED(src))
|
||||
return
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
sub_role = "Scientist"
|
||||
outfit = /datum/outfit/abductor/scientist
|
||||
landmark_type = /obj/effect/landmark/abductor/scientist
|
||||
greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve."
|
||||
greet_text = "Use your experimental console and surgical equipment to monitor your agent and experiment upon abducted humans."
|
||||
show_in_antagpanel = TRUE
|
||||
|
||||
/datum/antagonist/abductor/create_team(datum/team/abductor_team/new_team)
|
||||
@@ -40,17 +40,18 @@
|
||||
return team
|
||||
|
||||
/datum/antagonist/abductor/on_gain()
|
||||
owner.special_role = "[name] [sub_role]"
|
||||
owner.assigned_role = "[name] [sub_role]"
|
||||
owner.objectives += team.objectives
|
||||
owner.special_role = "[name]"
|
||||
owner.assigned_role = "[name]"
|
||||
objectives += team.objectives
|
||||
finalize_abductor()
|
||||
ADD_TRAIT(owner, TRAIT_ABDUCTOR_TRAINING, ABDUCTOR_ANTAGONIST)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/abductor/on_removal()
|
||||
owner.objectives -= team.objectives
|
||||
if(owner.current)
|
||||
to_chat(owner.current,"<span class='userdanger'>You are no longer the [owner.special_role]!</span>")
|
||||
owner.special_role = null
|
||||
REMOVE_TRAIT(owner, TRAIT_ABDUCTOR_TRAINING, ABDUCTOR_ANTAGONIST)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/abductor/greet()
|
||||
@@ -64,6 +65,7 @@
|
||||
//Equip
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
H.set_species(/datum/species/abductor)
|
||||
|
||||
H.real_name = "[team.name] [sub_role]"
|
||||
H.equipOutfit(outfit)
|
||||
|
||||
@@ -75,11 +77,15 @@
|
||||
|
||||
update_abductor_icons_added(owner,"abductor")
|
||||
|
||||
/datum/antagonist/abductor/scientist/finalize_abductor()
|
||||
..()
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/datum/species/abductor/A = H.dna.species
|
||||
A.scientist = TRUE
|
||||
/datum/antagonist/abductor/scientist/on_gain()
|
||||
ADD_TRAIT(owner, TRAIT_ABDUCTOR_SCIENTIST_TRAINING, ABDUCTOR_ANTAGONIST)
|
||||
ADD_TRAIT(owner, TRAIT_SURGEON, ABDUCTOR_ANTAGONIST)
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/abductor/scientist/on_removal()
|
||||
REMOVE_TRAIT(owner, TRAIT_ABDUCTOR_SCIENTIST_TRAINING, ABDUCTOR_ANTAGONIST)
|
||||
REMOVE_TRAIT(owner, TRAIT_SURGEON, ABDUCTOR_ANTAGONIST)
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin)
|
||||
var/list/current_teams = list()
|
||||
@@ -93,8 +99,8 @@
|
||||
else
|
||||
return
|
||||
new_owner.add_antag_datum(src)
|
||||
log_admin("[key_name(usr)] made [key_name(new_owner.current)] [name] on [choice]!")
|
||||
message_admins("[key_name_admin(usr)] made [key_name_admin(new_owner.current)] [name] on [choice] !")
|
||||
log_admin("[key_name(usr)] made [key_name(new_owner)] [name] on [choice]!")
|
||||
message_admins("[key_name_admin(usr)] made [key_name_admin(new_owner)] [name] on [choice] !")
|
||||
|
||||
/datum/antagonist/abductor/get_admin_commands()
|
||||
. = ..()
|
||||
@@ -147,7 +153,7 @@
|
||||
result += "<span class='header'>The abductors of [name] were:</span>"
|
||||
for(var/datum/mind/abductor_mind in members)
|
||||
result += printplayer(abductor_mind)
|
||||
result += printobjectives(abductor_mind)
|
||||
result += printobjectives(objectives)
|
||||
|
||||
return "<div class='panel redborder'>[result.Join("<br>")]</div>"
|
||||
|
||||
@@ -172,7 +178,6 @@
|
||||
var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random))
|
||||
var/datum/objective/abductee/O = new objtype()
|
||||
objectives += O
|
||||
owner.objectives += objectives
|
||||
|
||||
/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override)
|
||||
update_abductor_icons_added(mob_override ? mob_override.mind : owner,"abductee")
|
||||
@@ -214,4 +219,4 @@
|
||||
/datum/antagonist/proc/update_abductor_icons_removed(datum/mind/alien_mind)
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR]
|
||||
hud.leave_hud(alien_mind.current)
|
||||
set_antag_hud(alien_mind.current, null)
|
||||
set_antag_hud(alien_mind.current, null)
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
|
||||
/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user)
|
||||
/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user, datum/action/A)
|
||||
if(slot == SLOT_WEAR_SUIT) //we only give the mob the ability to activate the vest if he's actually wearing it.
|
||||
return 1
|
||||
|
||||
@@ -132,22 +132,26 @@
|
||||
/obj/item/abductor
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
|
||||
/obj/item/abductor/proc/AbductorCheck(user)
|
||||
if(isabductor(user))
|
||||
/obj/item/abductor/proc/AbductorCheck(mob/user)
|
||||
if(HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING))
|
||||
return TRUE
|
||||
if (istype(user) && user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
|
||||
return TRUE
|
||||
to_chat(user, "<span class='warning'>You can't figure how this works!</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/item/abductor/proc/ScientistCheck(user)
|
||||
if(!AbductorCheck(user))
|
||||
return FALSE
|
||||
/obj/item/abductor/proc/ScientistCheck(mob/user)
|
||||
var/training = HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) || (user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
|
||||
var/sci_training = HAS_TRAIT(user, TRAIT_ABDUCTOR_SCIENTIST_TRAINING) || (user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_SCIENTIST_TRAINING))
|
||||
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/datum/species/abductor/S = H.dna.species
|
||||
if(S.scientist)
|
||||
return TRUE
|
||||
to_chat(user, "<span class='warning'>You're not trained to use this!</span>")
|
||||
return FALSE
|
||||
if(training && !sci_training)
|
||||
to_chat(user, "<span class='warning'>You're not trained to use this!</span>")
|
||||
. = FALSE
|
||||
else if(!training && !sci_training)
|
||||
to_chat(user, "<span class='warning'>You can't figure how this works!</span>")
|
||||
. = FALSE
|
||||
else
|
||||
. = TRUE
|
||||
|
||||
/obj/item/abductor/gizmo
|
||||
name = "science tool"
|
||||
@@ -341,8 +345,8 @@
|
||||
if(QDELETED(G))
|
||||
return
|
||||
|
||||
if(istype(C.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
|
||||
to_chat(user, "<span class='warning'>Your target seems to have some sort of protective headgear on, blocking the message from being sent!</span>")
|
||||
if(C.anti_magic_check(FALSE, FALSE, TRUE, 0))
|
||||
to_chat(user, "<span class='warning'>Your target seems to have some sort of tinfoil protection on, blocking the message from being sent!</span>")
|
||||
return
|
||||
|
||||
G.mind_control(command, user)
|
||||
@@ -389,23 +393,22 @@
|
||||
name = "Dissection Guide"
|
||||
icon_state = "alienpaper_words"
|
||||
info = {"<b>Dissection for Dummies</b><br>
|
||||
|
||||
<br>
|
||||
1.Acquire fresh specimen.<br>
|
||||
2.Put the specimen on operating table.<br>
|
||||
3.Apply surgical drapes, preparing for experimental dissection.<br>
|
||||
4.Apply scalpel to specimen's torso.<br>
|
||||
5.Clamp bleeders on specimen's torso with a hemostat.<br>
|
||||
6.Retract skin of specimen's torso with a retractor.<br>
|
||||
7.Apply scalpel again to specimen's torso.<br>
|
||||
8.Search through the specimen's torso with your hands to remove any superfluous organs.<br>
|
||||
9.Insert replacement gland (Retrieve one from gland storage).<br>
|
||||
10.Consider dressing the specimen back to not disturb the habitat. <br>
|
||||
11.Put the specimen in the experiment machinery.<br>
|
||||
12.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.<br>
|
||||
13.You will receive one supply credit, and the subject will be counted towards your quota.<br>
|
||||
<br>
|
||||
Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
<br>
|
||||
1.Acquire fresh specimen.<br>
|
||||
2.Put the specimen on operating table.<br>
|
||||
3.Apply surgical drapes, preparing for experimental dissection.<br>
|
||||
4.Apply scalpel to specimen's torso.<br>
|
||||
5.Clamp bleeders on specimen's torso with a hemostat.<br>
|
||||
6.Retract skin of specimen's torso with a retractor.<br>
|
||||
7.Apply scalpel again to specimen's torso.<br>
|
||||
8.Search through the specimen's torso with your hands to remove any superfluous organs.<br>
|
||||
9.Insert replacement gland (Retrieve one from gland storage).<br>
|
||||
10.Consider dressing the specimen back to not disturb the habitat. <br>
|
||||
11.Put the specimen in the experiment machinery.<br>
|
||||
12.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.<br>
|
||||
13.You will receive one supply credit, and the subject will be counted towards your quota.<br>
|
||||
<br>
|
||||
Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
|
||||
/obj/item/paper/guides/antag/abductor/update_icon()
|
||||
return
|
||||
@@ -520,10 +523,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
|
||||
/obj/item/abductor_baton/proc/SleepAttack(mob/living/L,mob/living/user)
|
||||
if(L.incapacitated(TRUE, TRUE))
|
||||
if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
|
||||
to_chat(user, "<span class='warning'>The specimen's protective headgear is interfering with the sleep inducement!</span>")
|
||||
L.visible_message("<span class='danger'>[user] tried to induced sleep in [L] with [src], but [L.p_their()] headgear protected [L.p_them()]!</span>", \
|
||||
"<span class='userdanger'>You feel a strange wave of heavy drowsiness wash over you, but your headgear deflects most of it!</span>")
|
||||
if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
|
||||
to_chat(user, "<span class='warning'>The specimen's tinfoil protection is interfering with the sleep inducement!</span>")
|
||||
L.visible_message("<span class='danger'>[user] tried to induced sleep in [L] with [src], but [L.p_their()] tinfoil protected [L.p_them()]!</span>", \
|
||||
"<span class='userdanger'>You feel a strange wave of heavy drowsiness wash over you, but your tinfoil protection deflects most of it!</span>")
|
||||
L.drowsyness += 2
|
||||
return
|
||||
L.visible_message("<span class='danger'>[user] has induced sleep in [L] with [src]!</span>", \
|
||||
@@ -532,10 +535,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
L.Sleeping(1200)
|
||||
log_combat(user, L, "put to sleep")
|
||||
else
|
||||
if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
|
||||
to_chat(user, "<span class='warning'>The specimen's protective headgear is completely blocking our sleep inducement methods!</span>")
|
||||
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src], but [L.p_their()] headgear completely protected [L.p_them()]!</span>", \
|
||||
"<span class='userdanger'>Any sense of drowsiness is quickly diminished as your headgear deflects the effects!</span>")
|
||||
if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
|
||||
to_chat(user, "<span class='warning'>The specimen's tinfoil protection is completely blocking our sleep inducement methods!</span>")
|
||||
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src], but [L.p_their()] tinfoil completely protected [L.p_them()]!</span>", \
|
||||
"<span class='userdanger'>Any sense of drowsiness is quickly diminished as your tinfoil protection deflects the effects!</span>")
|
||||
return
|
||||
L.drowsyness += 1
|
||||
to_chat(user, "<span class='warning'>Sleep inducement works fully only on stunned specimens! </span>")
|
||||
@@ -683,7 +686,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
desc = "Abduct with style - spiky style. Prevents digital tracking."
|
||||
icon_state = "alienhelmet"
|
||||
item_state = "alienhelmet"
|
||||
blockTracking = 1
|
||||
blockTracking = TRUE
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
|
||||
// Operating Table / Beds / Lockers
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
for(var/obj/item/abductor/gizmo/G in B.contents)
|
||||
console.AddGizmo(G)
|
||||
|
||||
/datum/outfit/abductor/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
/datum/outfit/abductor/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
|
||||
..()
|
||||
if(!visualsOnly)
|
||||
link_to_console(H)
|
||||
@@ -49,8 +49,8 @@
|
||||
/obj/item/abductor/gizmo = 1
|
||||
)
|
||||
|
||||
/datum/outfit/abductor/scientist/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
/datum/outfit/abductor/scientist/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
|
||||
..()
|
||||
if(!visualsOnly)
|
||||
var/obj/item/implant/abductor/beamplant = new /obj/item/implant/abductor(H)
|
||||
var/obj/item/implant/abductor/beamplant = new
|
||||
beamplant.implant(H)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
icon_state = "gland"
|
||||
status = ORGAN_ROBOTIC
|
||||
beating = TRUE
|
||||
var/true_name = "baseline placebo referencer"
|
||||
var/cooldown_low = 300
|
||||
var/cooldown_high = 300
|
||||
var/next_activation = 0
|
||||
@@ -16,6 +17,11 @@
|
||||
var/mind_control_duration = 1800
|
||||
var/active_mind_control = FALSE
|
||||
|
||||
/obj/item/organ/heart/gland/examine(mob/user)
|
||||
. = ..()
|
||||
if((user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_SCIENTIST_TRAINING)) || isobserver(user))
|
||||
to_chat(user, "<span class='notice'>It is \a [true_name].</span>")
|
||||
|
||||
/obj/item/organ/heart/gland/proc/ownerCheck()
|
||||
if(ishuman(owner))
|
||||
return TRUE
|
||||
@@ -42,19 +48,19 @@
|
||||
|
||||
/obj/item/organ/heart/gland/proc/mind_control(command, mob/living/user)
|
||||
if(!ownerCheck() || !mind_control_uses || active_mind_control)
|
||||
return
|
||||
return FALSE
|
||||
mind_control_uses--
|
||||
to_chat(owner, "<span class='userdanger'>You suddenly feel an irresistible compulsion to follow an order...</span>")
|
||||
to_chat(owner, "<span class='mind_control'>[command]</span>")
|
||||
active_mind_control = TRUE
|
||||
log_admin("[key_name(user)] sent an abductor mind control message to [key_name(owner)]: [command]")
|
||||
message_admins("[key_name(user)] sent an abductor mind control message to [key_name(owner)]: [command]")
|
||||
update_gland_hud()
|
||||
|
||||
addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration)
|
||||
|
||||
/obj/item/organ/heart/gland/proc/clear_mind_control()
|
||||
if(!ownerCheck() || !active_mind_control)
|
||||
return
|
||||
return FALSE
|
||||
to_chat(owner, "<span class='userdanger'>You feel the compulsion fade, and you completely forget about your previous orders.</span>")
|
||||
active_mind_control = FALSE
|
||||
|
||||
@@ -67,7 +73,7 @@
|
||||
clear_mind_control()
|
||||
..()
|
||||
|
||||
/obj/item/organ/heart/gland/Insert(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/heart/gland/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
|
||||
..()
|
||||
if(special != 2 && uses) // Special 2 means abductor surgery
|
||||
Start()
|
||||
@@ -95,6 +101,7 @@
|
||||
return
|
||||
|
||||
/obj/item/organ/heart/gland/heals
|
||||
true_name = "coherency harmonizer"
|
||||
cooldown_low = 200
|
||||
cooldown_high = 400
|
||||
uses = -1
|
||||
@@ -109,6 +116,7 @@
|
||||
owner.adjustOxyLoss(-20)
|
||||
|
||||
/obj/item/organ/heart/gland/slime
|
||||
true_name = "gastric animation galvanizer"
|
||||
cooldown_low = 600
|
||||
cooldown_high = 1200
|
||||
uses = -1
|
||||
@@ -116,7 +124,7 @@
|
||||
mind_control_uses = 1
|
||||
mind_control_duration = 2400
|
||||
|
||||
/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
|
||||
..()
|
||||
owner.faction |= "slime"
|
||||
owner.grant_language(/datum/language/slime)
|
||||
@@ -130,6 +138,7 @@
|
||||
Slime.Leader = owner
|
||||
|
||||
/obj/item/organ/heart/gland/mindshock
|
||||
true_name = "neural crosstalk uninhibitor"
|
||||
cooldown_low = 400
|
||||
cooldown_high = 700
|
||||
uses = -1
|
||||
@@ -151,11 +160,12 @@
|
||||
if(2)
|
||||
to_chat(H, "<span class='warning'>You hear an annoying buzz in your head.</span>")
|
||||
H.confused += 15
|
||||
H.adjustBrainLoss(10, 160)
|
||||
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 160)
|
||||
if(3)
|
||||
H.hallucination += 60
|
||||
|
||||
/obj/item/organ/heart/gland/pop
|
||||
true_name = "anthropmorphic translocator"
|
||||
cooldown_low = 900
|
||||
cooldown_high = 1800
|
||||
uses = -1
|
||||
@@ -171,6 +181,7 @@
|
||||
owner.set_species(species)
|
||||
|
||||
/obj/item/organ/heart/gland/ventcrawling
|
||||
true_name = "pliant cartilage enabler"
|
||||
cooldown_low = 1800
|
||||
cooldown_high = 2400
|
||||
uses = 1
|
||||
@@ -183,6 +194,7 @@
|
||||
owner.ventcrawler = VENTCRAWLER_ALWAYS
|
||||
|
||||
/obj/item/organ/heart/gland/viral
|
||||
true_name = "contamination incubator"
|
||||
cooldown_low = 1800
|
||||
cooldown_high = 2400
|
||||
uses = 1
|
||||
@@ -217,6 +229,7 @@
|
||||
return A
|
||||
|
||||
/obj/item/organ/heart/gland/trauma
|
||||
true_name = "white matter randomiser"
|
||||
cooldown_low = 800
|
||||
cooldown_high = 1200
|
||||
uses = 5
|
||||
@@ -235,6 +248,7 @@
|
||||
owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
|
||||
|
||||
/obj/item/organ/heart/gland/spiderman
|
||||
true_name = "araneae cloister accelerator"
|
||||
cooldown_low = 450
|
||||
cooldown_high = 900
|
||||
uses = -1
|
||||
@@ -249,6 +263,7 @@
|
||||
S.directive = "Protect your nest inside [owner.real_name]."
|
||||
|
||||
/obj/item/organ/heart/gland/egg
|
||||
true_name = "roe/enzymatic synthesizer"
|
||||
cooldown_low = 300
|
||||
cooldown_high = 400
|
||||
uses = -1
|
||||
@@ -264,13 +279,14 @@
|
||||
new /obj/item/reagent_containers/food/snacks/egg/gland(T)
|
||||
|
||||
/obj/item/organ/heart/gland/electric
|
||||
true_name = "electron accumulator/discharger"
|
||||
cooldown_low = 800
|
||||
cooldown_high = 1200
|
||||
uses = -1
|
||||
mind_control_uses = 2
|
||||
mind_control_duration = 900
|
||||
|
||||
/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
|
||||
..()
|
||||
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
|
||||
|
||||
@@ -289,6 +305,7 @@
|
||||
playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, 1)
|
||||
|
||||
/obj/item/organ/heart/gland/chem
|
||||
true_name = "intrinsic pharma-provider"
|
||||
cooldown_low = 50
|
||||
cooldown_high = 50
|
||||
uses = -1
|
||||
@@ -315,6 +332,7 @@
|
||||
..()
|
||||
|
||||
/obj/item/organ/heart/gland/plasma
|
||||
true_name = "effluvium sanguine-synonym emitter"
|
||||
cooldown_low = 1200
|
||||
cooldown_high = 1800
|
||||
uses = -1
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
/obj/machinery/computer/camera_advanced/abductor/CreateEye()
|
||||
..()
|
||||
eyeobj.visible_icon = 1
|
||||
eyeobj.icon = 'icons/obj/abductor.dmi'
|
||||
eyeobj.icon_state = "camera_target"
|
||||
eyeobj.visible_icon = TRUE
|
||||
eyeobj.icon = 'icons/mob/cameramob.dmi'
|
||||
eyeobj.icon_state = "generic_camera"
|
||||
|
||||
/obj/machinery/computer/camera_advanced/abductor/GrantActions(mob/living/carbon/user)
|
||||
..()
|
||||
@@ -55,8 +55,7 @@
|
||||
actions += set_droppoint_action
|
||||
|
||||
/obj/machinery/computer/camera_advanced/abductor/proc/IsScientist(mob/living/carbon/human/H)
|
||||
var/datum/species/abductor/S = H.dna.species
|
||||
return S.scientist
|
||||
return HAS_TRAIT(H, TRAIT_ABDUCTOR_SCIENTIST_TRAINING)
|
||||
|
||||
/datum/action/innate/teleport_in
|
||||
name = "Send To"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!isabductor(user))
|
||||
if(!HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) && !HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
|
||||
to_chat(user, "<span class='warning'>You start mashing alien buttons at random!</span>")
|
||||
if(do_after(user,100, target = src))
|
||||
TeleporterSend()
|
||||
@@ -178,8 +178,8 @@
|
||||
c.console = src
|
||||
|
||||
/obj/machinery/abductor/console/proc/AddSnapshot(mob/living/carbon/human/target)
|
||||
if(istype(target.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
|
||||
say("Subject wearing specialized protective headgear, unable to get a proper scan!")
|
||||
if(target.anti_magic_check(FALSE, FALSE, TRUE, 0))
|
||||
say("Subject wearing specialized protective tinfoil gear, unable to get a proper scan!")
|
||||
return
|
||||
var/datum/icon_snapshot/entry = new
|
||||
entry.name = target.name
|
||||
|
||||
@@ -53,4 +53,4 @@
|
||||
. = ..()
|
||||
var/datum/effect_system/spark_spread/S = new
|
||||
S.set_up(10,0,loc)
|
||||
S.start()
|
||||
S.start()
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
var/datum/objective/blob_takeover/main = new
|
||||
main.owner = owner
|
||||
objectives += main
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/blob/apply_innate_effects(mob/living/mob_override)
|
||||
if(!isovermind(owner.current))
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
. = ..()
|
||||
|
||||
/obj/structure/blob/core/proc/generate_announcement()
|
||||
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg')
|
||||
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", "outbreak5")
|
||||
|
||||
/obj/structure/blob/core/scannerreport()
|
||||
return "Directs the blob's expansion, gradually expands, and sustains nearby blob spores and blobbernauts."
|
||||
|
||||
@@ -9,7 +9,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
name = "Blob Overmind"
|
||||
real_name = "Blob Overmind"
|
||||
desc = "The overmind. It controls the blob."
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
icon = 'icons/mob/cameramob.dmi'
|
||||
icon_state = "marker"
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
move_on_shuttle = 1
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
blobber.adjustHealth(blobber.maxHealth * 0.5)
|
||||
blob_mobs += blobber
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
blobber.key = C.key
|
||||
C.transfer_ckey(blobber)
|
||||
SEND_SOUND(blobber, sound('sound/effects/blobattack.ogg'))
|
||||
SEND_SOUND(blobber, sound('sound/effects/attackblob.ogg'))
|
||||
to_chat(blobber, "<b>You are a blobbernaut!</b>")
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
/datum/antagonist/blood_contract
|
||||
name = "Blood Contract Target"
|
||||
show_in_roundend = FALSE
|
||||
show_in_antagpanel = FALSE
|
||||
|
||||
/datum/antagonist/blood_contract/on_gain()
|
||||
. = ..()
|
||||
give_objective()
|
||||
start_the_hunt()
|
||||
|
||||
/datum/antagonist/blood_contract/proc/give_objective()
|
||||
var/datum/objective/survive/survive = new
|
||||
survive.owner = owner
|
||||
objectives += survive
|
||||
|
||||
/datum/antagonist/blood_contract/greet()
|
||||
. = ..()
|
||||
to_chat(owner, "<span class='userdanger'>You've been marked for death! Don't let the demons get you! KILL THEM ALL!</span>")
|
||||
|
||||
/datum/antagonist/blood_contract/proc/start_the_hunt()
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(!istype(H))
|
||||
return
|
||||
H.add_atom_colour("#FF0000", ADMIN_COLOUR_PRIORITY)
|
||||
var/obj/effect/mine/pickup/bloodbath/B = new(H)
|
||||
INVOKE_ASYNC(B, /obj/effect/mine/pickup/bloodbath/.proc/mineEffect, H) //could use moving out from the mine
|
||||
|
||||
for(var/mob/living/carbon/human/P in GLOB.player_list)
|
||||
if(P == H)
|
||||
continue
|
||||
to_chat(P, "<span class='userdanger'>You have an overwhelming desire to kill [H]. [H.p_theyve(TRUE)] been marked red! Whoever [H.p_they()] [H.p_were()], friend or foe, go kill [H.p_them()]!</span>")
|
||||
P.put_in_hands(new /obj/item/kitchen/knife/butcher(P), TRUE)
|
||||
@@ -9,7 +9,6 @@
|
||||
for(var/O in directives)
|
||||
var/datum/objective/brainwashing/objective = new(O)
|
||||
B.objectives += objective
|
||||
M.objectives += objective
|
||||
B.greet()
|
||||
else
|
||||
B = new()
|
||||
@@ -32,10 +31,6 @@
|
||||
antagpanel_category = "Other"
|
||||
show_name_in_check_antagonists = TRUE
|
||||
|
||||
/datum/antagonist/brainwashed/on_gain()
|
||||
owner.objectives |= objectives
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/brainwashed/greet()
|
||||
to_chat(owner, "<span class='warning'>Your mind reels as it begins focusing on a single purpose...</span>")
|
||||
to_chat(owner, "<big><span class='warning'><b>Follow the Directives, at any cost!</b></span></big>")
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
/datum/antagonist/brother/on_gain()
|
||||
SSticker.mode.brothers += owner
|
||||
objectives += team.objectives
|
||||
owner.objectives += objectives
|
||||
owner.special_role = special_role
|
||||
finalize_brother()
|
||||
return ..()
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
if(istype(C))
|
||||
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
if(B && (B.decoy_override != initial(B.decoy_override)))
|
||||
B.vital = TRUE
|
||||
B.organ_flags |= ORGAN_VITAL
|
||||
B.decoy_override = FALSE
|
||||
remove_changeling_powers()
|
||||
. = ..()
|
||||
@@ -340,7 +340,7 @@
|
||||
if(istype(C))
|
||||
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
if(B)
|
||||
B.vital = FALSE
|
||||
B.organ_flags &= ~ORGAN_VITAL
|
||||
B.decoy_override = TRUE
|
||||
update_changeling_icons_added()
|
||||
return
|
||||
@@ -459,8 +459,6 @@
|
||||
objectives += identity_theft
|
||||
escape_objective_possible = FALSE
|
||||
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/changeling/proc/update_changeling_icons_added()
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
|
||||
hud.join_hud(owner.current)
|
||||
|
||||
@@ -334,7 +334,7 @@
|
||||
/obj/item/projectile/tentacle/proc/tentacle_stab(mob/living/carbon/human/H, mob/living/carbon/C)
|
||||
if(H.Adjacent(C))
|
||||
for(var/obj/item/I in H.held_items)
|
||||
if(I.is_sharp())
|
||||
if(I.get_sharpness())
|
||||
C.visible_message("<span class='danger'>[H] impales [C] with [H.p_their()] [I.name]!</span>", "<span class='userdanger'>[H] impales you with [H.p_their()] [I.name]!</span>")
|
||||
C.apply_damage(I.force, BRUTE, BODY_ZONE_CHEST)
|
||||
H.do_item_attack_animation(C, used_item = I)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
B = new C.dna.species.mutant_brain()
|
||||
else
|
||||
B = new()
|
||||
B.vital = FALSE
|
||||
B.organ_flags &= ~ORGAN_VITAL
|
||||
B.decoy_override = TRUE
|
||||
B.Insert(C)
|
||||
if(ishuman(user))
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
to_chat(user, "<span class='notice'>Our muscles tense and strengthen.</span>")
|
||||
changeling.chem_recharge_slowdown += 0.5
|
||||
else
|
||||
REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
|
||||
user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES)
|
||||
to_chat(user, "<span class='notice'>Our muscles relax.</span>")
|
||||
changeling.chem_recharge_slowdown -= 0.5
|
||||
if(stacks >= 20)
|
||||
@@ -36,12 +36,12 @@
|
||||
/obj/effect/proc_holder/changeling/strained_muscles/proc/muscle_loop(mob/living/carbon/user)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
while(active)
|
||||
ADD_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
|
||||
user.add_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
if(user.stat != CONSCIOUS || user.staminaloss >= 90)
|
||||
active = !active
|
||||
to_chat(user, "<span class='notice'>Our muscles relax without the energy to strengthen them.</span>")
|
||||
user.Knockdown(40)
|
||||
REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
|
||||
user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES)
|
||||
changeling.chem_recharge_slowdown -= 0.5
|
||||
break
|
||||
|
||||
|
||||
@@ -147,6 +147,11 @@
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/M = L
|
||||
M.uncuff()
|
||||
var/brutedamage = L.getBruteLoss()
|
||||
var/burndamage = L.getFireLoss()
|
||||
if(brutedamage || burndamage)
|
||||
L.adjustBruteLoss(-(brutedamage * 0.25))
|
||||
L.adjustFireLoss(-(burndamage * 0.25))
|
||||
L.Knockdown(50) //Completely defenseless for five seconds - mainly to give them time to read over the information they've just been presented with
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
@@ -262,7 +267,7 @@
|
||||
clockwork_desc = "A sigil that will drain non-Servants that remain on it. Servants that remain on it will be healed if it has any vitality drained."
|
||||
icon_state = "sigilvitality"
|
||||
layer = SIGIL_LAYER
|
||||
alpha = 75
|
||||
alpha = 125
|
||||
color = "#123456"
|
||||
affects_servants = TRUE
|
||||
stat_affected = DEAD
|
||||
@@ -349,7 +354,7 @@
|
||||
to_chat(L, "<span class='userdanger'>Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form!</span>")
|
||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(L)]) to replace an inactive clock cultist.")
|
||||
L.ghostize(0)
|
||||
L.key = C.key
|
||||
C.transfer_ckey(L, FALSE)
|
||||
var/obj/effect/temp_visual/ratvar/sigil/vitality/V = new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
|
||||
animate(V, alpha = 0, transform = matrix()*2, time = 8)
|
||||
playsound(L, 'sound/magic/staff_healing.ogg', 50, 1)
|
||||
@@ -366,6 +371,8 @@
|
||||
break
|
||||
|
||||
if(!GLOB.ratvar_awakens)
|
||||
if(GLOB.clockwork_vitality <= 0)
|
||||
break
|
||||
GLOB.clockwork_vitality -= vitality_used
|
||||
|
||||
sleep(2)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
/obj/item/clockwork/weapon/ratvarian_spear/attack(mob/living/target, mob/living/carbon/human/user)
|
||||
. = ..()
|
||||
if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check() && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
|
||||
if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check(chargecost = 0) && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
|
||||
var/bonus_damage = bonus_burn //normally a total of 20 damage, 30 with ratvar
|
||||
if(issilicon(target))
|
||||
target.visible_message("<span class='warning'>[target] shudders violently at [src]'s touch!</span>", "<span class='userdanger'>ERROR: Temperature rising!</span>")
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
to_chat(user, "<span class='userdanger'>The helmet tries to drive a spike through your head as you scramble to remove it!</span>")
|
||||
user.emote("scream")
|
||||
user.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
|
||||
user.adjustBrainLoss(30)
|
||||
user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30)
|
||||
addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off.
|
||||
|
||||
/obj/item/clothing/head/helmet/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
/obj/item/clockwork/slab/cyborg/janitor //six scriptures, plus a fabricator
|
||||
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transgression, \
|
||||
/datum/clockwork_scripture/create_object/stargazer, /datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor)
|
||||
/datum/clockwork_scripture/create_object/stargazer, /datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor)
|
||||
|
||||
/obj/item/clockwork/slab/cyborg/service //six scriptures, plus xray vision
|
||||
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant,/datum/clockwork_scripture/create_object/stargazer, \
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
if(A && construct_type)
|
||||
notify_ghosts("A [construct_name] chassis has been created in [A.name]!", 'sound/magic/clockwork/fellowship_armory.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_CONSTRUCT)
|
||||
notify_ghosts("A [construct_name] chassis has been created in [A.name]!", 'sound/magic/clockwork/fellowship_armory.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_CONSTRUCT, ignore_dnr_observers = TRUE)
|
||||
GLOB.poi_list += src
|
||||
LAZYADD(GLOB.mob_spawners[name], src)
|
||||
|
||||
@@ -39,7 +39,9 @@
|
||||
. = ..()
|
||||
|
||||
//ATTACK GHOST IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clockwork/construct_chassis/attack_ghost(mob/user)
|
||||
/obj/item/clockwork/construct_chassis/attack_ghost(mob/dead/observer/user)
|
||||
if(!user.can_reenter_round())
|
||||
return FALSE
|
||||
if(!SSticker.mode)
|
||||
to_chat(user, "<span class='danger'>You cannot use that before the game has started.</span>")
|
||||
return
|
||||
@@ -55,7 +57,7 @@
|
||||
pre_spawn()
|
||||
visible_message(creation_message)
|
||||
var/mob/living/construct = new construct_type(get_turf(src))
|
||||
construct.key = user.key
|
||||
user.transfer_ckey(construct, FALSE)
|
||||
post_spawn(construct)
|
||||
qdel(user)
|
||||
qdel(src)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
qdel(blaster)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/glasses/judicial_visor/item_action_slot_check(slot, mob/user)
|
||||
/obj/item/clothing/glasses/judicial_visor/item_action_slot_check(slot, mob/user, datum/action/A)
|
||||
if(slot != SLOT_GLASSES)
|
||||
return 0
|
||||
return ..()
|
||||
@@ -190,8 +190,8 @@
|
||||
for(var/mob/living/L in range(1, src))
|
||||
if(is_servant_of_ratvar(L))
|
||||
continue
|
||||
if(L.anti_magic_check())
|
||||
var/atom/I = L.anti_magic_check()
|
||||
var/atom/I = L.anti_magic_check()
|
||||
if(I)
|
||||
if(isitem(I))
|
||||
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
|
||||
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
|
||||
|
||||
@@ -119,3 +119,33 @@
|
||||
var/datum/clockwork_scripture/create_object/construct/clockwork_marauder/CM = new()
|
||||
CM.recent_marauders--
|
||||
qdel(CM)
|
||||
|
||||
//Summon Neovgre: Summon a very powerful combat mech that explodes when destroyed for massive damage.
|
||||
/datum/clockwork_scripture/create_object/summon_arbiter
|
||||
descname = "Powerful Assault Mech"
|
||||
name = "Summon Neovgre, the Anima Bulwark"
|
||||
desc = "Calls forth the mighty Anima Bulwark, a weapon of unmatched power,\
|
||||
mech with superior defensive and offensive capabilities. It will \
|
||||
steadily regenerate HP and triple its regeneration speed while standing \
|
||||
on a clockwork tile. It will automatically draw power from nearby sigils of \
|
||||
transmission should the need arise. Its Arbiter laser cannon can decimate foes \
|
||||
from a range and is capable of smashing through any barrier presented to it. \
|
||||
Be warned, choosing to pilot Neovgre is a lifetime commitment, once you are \
|
||||
in you cannot leave and when it is destroyed it will explode catastrophically with you inside."
|
||||
invocations = list("By the strength of the alloy...!!", "...call forth the Arbiter!!")
|
||||
channel_time = 200 // This is a strong fucking weapon, 20 seconds channel time is getting off light I tell ya.
|
||||
power_cost = 75000 //75 KW
|
||||
usage_tip = "Neovgre is a powerful mech that will crush your enemies!"
|
||||
invokers_required = 5
|
||||
multiple_invokers_used = TRUE
|
||||
object_path = /obj/mecha/combat/neovgre
|
||||
tier = SCRIPTURE_APPLICATION
|
||||
primary_component = BELLIGERENT_EYE
|
||||
sort_priority = 2
|
||||
creator_message = "<span class='brass'>Neovgre, the Anima Bulwark towers over you... your enemies reckoning has come.</span>"
|
||||
|
||||
/datum/clockwork_scripture/create_object/summon_arbiter/check_special_requirements()
|
||||
if(GLOB.neovgre_exists)
|
||||
to_chat(invoker, "<span class='brass'>\"You've already got one...\"</span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
power_cost = 125
|
||||
whispered = TRUE
|
||||
object_path = /obj/effect/clockwork/sigil/submission
|
||||
creator_message = "<span class='brass'>A luminous sigil appears below you. Any non-Servants to cross it will be converted after 8 seconds if they do not move.</span>"
|
||||
creator_message = "<span class='brass'>A luminous sigil appears below you. Any non-Servants to cross it will be converted and healed of some of their wounds after 8 seconds if they do not move.</span>"
|
||||
usage_tip = "This is the primary conversion method, though it will not penetrate mindshield implants."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
one_per_tile = TRUE
|
||||
@@ -216,6 +216,9 @@
|
||||
if(is_reebe(invoker.z))
|
||||
to_chat(invoker, "<span class='danger'>You're already at Reebe.</span>")
|
||||
return
|
||||
if(!isturf(invoker.loc))
|
||||
to_chat(invoker, "<span class='danger'>You must be visible to return!</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/datum/clockwork_scripture/abscond/recital()
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
return TRUE
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/proc/activate()
|
||||
return
|
||||
|
||||
//These objects send signals to normal traps to activate
|
||||
/obj/structure/destructible/clockwork/trap/trigger
|
||||
@@ -79,6 +80,14 @@
|
||||
break_message = "<span class='warning'>The trigger breaks apart!</span>"
|
||||
density = FALSE
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/trigger/Initialize()
|
||||
. = ..()
|
||||
for(var/obj/structure/destructible/clockwork/trap/T in get_turf(src))
|
||||
if(!istype(T, /obj/structure/destructible/clockwork/trap/trigger))
|
||||
wired_to += T
|
||||
T.wired_to += src
|
||||
to_chat(usr, "<span class='alloy'>[src] automatically links with [T] beneath it.</span>")
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/trigger/activate()
|
||||
for(var/obj/structure/destructible/clockwork/trap/T in wired_to)
|
||||
if(istype(T, /obj/structure/destructible/clockwork/trap/trigger)) //Triggers don't go off multiple times
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
message_admins("<span class='danger'>Admin [key_name_admin(user)] directly became the Eminence of the cult!</span>")
|
||||
log_admin("Admin [key_name(user)] made themselves the Eminence.")
|
||||
var/mob/camera/eminence/eminence = new(get_turf(src))
|
||||
eminence.key = user.key
|
||||
user.transfer_ckey(eminence, FALSE)
|
||||
hierophant_message("<span class='bold large_brass'>Ratvar has directly assigned the Eminence!</span>")
|
||||
for(var/mob/M in servants_and_ghosts())
|
||||
M.playsound_local(M, 'sound/machines/clockcult/eminence_selected.ogg', 50, FALSE)
|
||||
@@ -138,7 +138,7 @@
|
||||
playsound(src, 'sound/machines/clockcult/ark_damage.ogg', 50, FALSE)
|
||||
var/mob/camera/eminence/eminence = new(get_turf(src))
|
||||
eminence_nominee = pick(candidates)
|
||||
eminence.key = eminence_nominee.key
|
||||
eminence_nominee.transfer_ckey(eminence)
|
||||
hierophant_message("<span class='bold large_brass'>A ghost has ascended into the Eminence!</span>")
|
||||
for(var/mob/M in servants_and_ghosts())
|
||||
M.playsound_local(M, 'sound/machines/clockcult/eminence_selected.ogg', 50, FALSE)
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
return
|
||||
voters += user.key
|
||||
else
|
||||
if(!user.key in voters)
|
||||
if(!(user.key in voters))
|
||||
return
|
||||
voters -= user.key
|
||||
var/votes_left = votes_needed - voters.len
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
else
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
if(!L.anti_magic_check())
|
||||
if(!L.anti_magic_check(chargecost = 0))
|
||||
if(isrevenant(L))
|
||||
var/mob/living/simple_animal/revenant/R = L
|
||||
if(R.revealed)
|
||||
@@ -110,9 +110,7 @@
|
||||
if(!(BI.resistance_flags & ON_FIRE))
|
||||
BI.fire_act()
|
||||
continue
|
||||
if(is_servant_of_ratvar(L) || (HAS_TRAIT(L, TRAIT_BLIND)) || L.anti_magic_check(TRUE, TRUE))
|
||||
continue
|
||||
if(L.stat || L.lying)
|
||||
if(is_servant_of_ratvar(L) || (HAS_TRAIT(L, TRAIT_BLIND)) || L.anti_magic_check(TRUE, TRUE) || L.incapacitated(TRUE))
|
||||
continue
|
||||
if (iscarbon(L))
|
||||
var/mob/living/carbon/c = L
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@
|
||||
return FALSE
|
||||
var/mob/living/simple_animal/drone/cogscarab/ratvar/R = new/mob/living/simple_animal/drone/cogscarab/ratvar(get_turf(src))
|
||||
R.visible_message("<span class='heavy_brass'>[R] forms, and its eyes blink open, glowing bright red!</span>")
|
||||
R.key = O.key
|
||||
O.transfer_ckey(R, FALSE)
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/ratvar/Bump(atom/A)
|
||||
var/turf/T = get_turf(A)
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
/obj/structure/destructible/clockwork/taunting_trail/proc/affect_mob(mob/living/L)
|
||||
if(istype(L) && !is_servant_of_ratvar(L))
|
||||
if(!L.anti_magic_check())
|
||||
if(!L.anti_magic_check(chargecost = 0))
|
||||
L.confused = min(L.confused + 15, 50)
|
||||
L.dizziness = min(L.dizziness + 15, 50)
|
||||
if(L.confused >= 25)
|
||||
|
||||
+1
-9
@@ -7,18 +7,10 @@
|
||||
icon_state = "pressure_sensor"
|
||||
alpha = 50
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/trigger/Initialize()
|
||||
. = ..()
|
||||
for(var/obj/structure/destructible/clockwork/trap/T in get_turf(src))
|
||||
if(!istype(T, /obj/structure/destructible/clockwork/trap/trigger))
|
||||
wired_to += T
|
||||
T.wired_to += src
|
||||
to_chat(usr, "<span class='alloy'>[src] automatically links with [T] beneath it.</span>")
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/trigger/pressure_sensor/Crossed(atom/movable/AM)
|
||||
if(isliving(AM) && !is_servant_of_ratvar(AM))
|
||||
var/mob/living/L = AM
|
||||
if(L.stat || L.m_intent == MOVE_INTENT_WALK || L.lying)
|
||||
if(L.stat || L.m_intent == MOVE_INTENT_WALK || L.movement_type & (FLYING|FLOATING))
|
||||
return
|
||||
audible_message("<i>*click*</i>")
|
||||
playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
break_message = "<span class='warning'>The vent snaps and collapses!</span>"
|
||||
max_integrity = 100
|
||||
density = FALSE
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/steam_vent/activate()
|
||||
opacity = !opacity
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
unanchored_icon = "wall_gear"
|
||||
climbable = TRUE
|
||||
max_integrity = 100
|
||||
layer = BELOW_OBJ_LAYER
|
||||
construction_value = 3
|
||||
desc = "A massive brass gear. You could probably secure or unsecure it with a wrench, or just climb over it."
|
||||
break_message = "<span class='warning'>The gear breaks apart into shards of alloy!</span>"
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
|
||||
/datum/antagonist/cult/proc/add_objectives()
|
||||
objectives |= cult_team.objectives
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/cult/Destroy()
|
||||
QDEL_NULL(communion)
|
||||
|
||||
@@ -275,7 +275,7 @@
|
||||
desc = "A torn, dust-caked hood. Strange letters line the inside."
|
||||
flags_inv = HIDEFACE|HIDEHAIR|HIDEEARS
|
||||
flags_cover = HEADCOVERSEYES
|
||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
|
||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 65, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
|
||||
cold_protection = HEAD
|
||||
min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT
|
||||
heat_protection = HEAD
|
||||
@@ -288,7 +288,7 @@
|
||||
item_state = "cultrobes"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
allowed = list(/obj/item/tome, /obj/item/melee/cultblade)
|
||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
|
||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 65, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
|
||||
flags_inv = HIDEJUMPSUIT
|
||||
cold_protection = CHEST|GROIN|LEGS|ARMS
|
||||
min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
|
||||
@@ -493,7 +493,7 @@
|
||||
desc = "You peer within this smokey orb and glimpse terrible fates befalling the escape shuttle."
|
||||
icon = 'icons/obj/cult.dmi'
|
||||
icon_state ="shuttlecurse"
|
||||
var/global/curselimit = 0
|
||||
var/static/curselimit = 0
|
||||
|
||||
/obj/item/shuttle_curse/attack_self(mob/living/user)
|
||||
if(!iscultist(user))
|
||||
@@ -530,7 +530,7 @@
|
||||
playsound(user.loc, 'sound/effects/glassbr1.ogg', 50, 1)
|
||||
qdel(src)
|
||||
sleep(20)
|
||||
var/global/list/curses
|
||||
var/static/list/curses
|
||||
if(!curses)
|
||||
curses = list("A fuel technician just slit his own throat and begged for death.",
|
||||
"The shuttle's navigation programming was replaced by a file containing just two words: IT COMES.",
|
||||
|
||||
@@ -107,7 +107,7 @@ This file contains the cult dagger and rune list code
|
||||
if(!(A in summon_objective.summon_spots)) // Check again to make sure they didn't move
|
||||
to_chat(user, "<span class='cultlarge'>The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!</span>")
|
||||
return
|
||||
priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/ai/spanomalies.ogg')
|
||||
priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", "spanomalies")
|
||||
for(var/B in spiral_range_turfs(1, user, 1))
|
||||
var/obj/structure/emergency_shield/sanguine/N = new(B)
|
||||
shields += N
|
||||
|
||||
@@ -237,7 +237,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
to_chat(M, "<span class='warning'>You need at least two invokers to convert [convertee]!</span>")
|
||||
log_game("Offer rune failed - tried conversion with one invoker")
|
||||
return 0
|
||||
if(convertee.anti_magic_check(TRUE, TRUE, FALSE, 0)) //Not chargecost because it can be spammed
|
||||
if(convertee.anti_magic_check(TRUE, TRUE, chargecost = 0)) //Not major because it can be spammed
|
||||
for(var/M in invokers)
|
||||
to_chat(M, "<span class='warning'>Something is shielding [convertee]'s mind!</span>")
|
||||
log_game("Offer rune failed - convertee had anti-magic")
|
||||
@@ -249,7 +249,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
convertee.adjustFireLoss(-(burndamage * 0.75))
|
||||
convertee.visible_message("<span class='warning'>[convertee] writhes in pain \
|
||||
[brutedamage || burndamage ? "even as [convertee.p_their()] wounds heal and close" : "as the markings below [convertee.p_them()] glow a bloody red"]!</span>", \
|
||||
"<span class='cultlarge'><i>AAAAAAAAAAAAAA-</i></span>")
|
||||
"<span class='cultlarge'><i>AAAAAAAAAAAAAA-</i></span>")
|
||||
SSticker.mode.add_cultist(convertee.mind, 1)
|
||||
new /obj/item/melee/cultblade/dagger(get_turf(src))
|
||||
convertee.mind.special_role = ROLE_CULTIST
|
||||
@@ -575,7 +575,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
to_chat(mob_to_revive.mind, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form.")
|
||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(mob_to_revive)]) to replace an AFK player.")
|
||||
mob_to_revive.ghostize(0)
|
||||
mob_to_revive.key = C.key
|
||||
C.transfer_ckey(mob_to_revive, FALSE)
|
||||
else
|
||||
fail_invoke()
|
||||
return
|
||||
@@ -767,7 +767,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
set_light(6, 1, color)
|
||||
for(var/mob/living/L in viewers(T))
|
||||
if(!iscultist(L) && L.blood_volume)
|
||||
var/atom/I = L.anti_magic_check()
|
||||
var/atom/I = L.anti_magic_check(chargecost = 0)
|
||||
if(I)
|
||||
if(isitem(I))
|
||||
to_chat(L, "<span class='userdanger'>[I] suddenly burns hotly before returning to normal!</span>")
|
||||
@@ -797,7 +797,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
set_light(6, 1, color)
|
||||
for(var/mob/living/L in viewers(T))
|
||||
if(!iscultist(L) && L.blood_volume)
|
||||
if(L.anti_magic_check())
|
||||
if(L.anti_magic_check(chargecost = 0))
|
||||
continue
|
||||
L.take_overall_damage(tick_damage*multiplier, tick_damage*multiplier)
|
||||
if(is_servant_of_ratvar(L))
|
||||
@@ -848,10 +848,10 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
fail_invoke()
|
||||
log_game("Manifest rune failed - too many summoned ghosts")
|
||||
return list()
|
||||
notify_ghosts("Manifest rune invoked in [get_area(src)].", 'sound/effects/ghost2.ogg', source = src)
|
||||
notify_ghosts("Manifest rune invoked in [get_area(src)].", 'sound/effects/ghost2.ogg', source = src, ignore_dnr_observers = TRUE)
|
||||
var/list/ghosts_on_rune = list()
|
||||
for(var/mob/dead/observer/O in T)
|
||||
if(O.client && !jobban_isbanned(O, ROLE_CULTIST) && !QDELETED(src) && !QDELETED(O))
|
||||
if(!QDELETED(O) && O.client && !jobban_isbanned(O, ROLE_CULTIST) && !QDELETED(src) && O.can_reenter_round())
|
||||
ghosts_on_rune += O
|
||||
if(!ghosts_on_rune.len)
|
||||
to_chat(user, "<span class='cultitalic'>There are no spirits near [src]!</span>")
|
||||
@@ -870,7 +870,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
visible_message("<span class='warning'>A cloud of red mist forms above [src], and from within steps... a [new_human.gender == FEMALE ? "wo":""]man.</span>")
|
||||
to_chat(user, "<span class='cultitalic'>Your blood begins flowing into [src]. You must remain in place and conscious to maintain the forms of those summoned. This will hurt you slowly but surely...</span>")
|
||||
var/obj/structure/emergency_shield/invoker/N = new(T)
|
||||
new_human.key = ghost_to_spawn.key
|
||||
ghost_to_spawn.transfer_ckey(new_human, FALSE)
|
||||
SSticker.mode.add_cultist(new_human.mind, 0)
|
||||
to_chat(new_human, "<span class='cultitalic'><b>You are a servant of the Geometer. You have been made semi-corporeal by the cult of Nar'Sie, and you are to serve them at all costs.</b></span>")
|
||||
|
||||
|
||||
@@ -539,17 +539,17 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
|
||||
var/list/parts = list()
|
||||
parts += "The devil's true name is: [truename]"
|
||||
parts += "The devil's bans were:"
|
||||
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][ban]]"
|
||||
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][bane]]"
|
||||
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][obligation]]"
|
||||
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][banish]]"
|
||||
parts += "[FOURSPACES][GLOB.lawlorify[LORE][ban]]"
|
||||
parts += "[FOURSPACES][GLOB.lawlorify[LORE][bane]]"
|
||||
parts += "[FOURSPACES][GLOB.lawlorify[LORE][obligation]]"
|
||||
parts += "[FOURSPACES][GLOB.lawlorify[LORE][banish]]"
|
||||
return parts.Join("<br>")
|
||||
|
||||
/datum/antagonist/devil/roundend_report()
|
||||
var/list/parts = list()
|
||||
parts += printplayer(owner)
|
||||
parts += printdevilinfo()
|
||||
parts += printobjectives(owner)
|
||||
parts += printobjectives(objectives)
|
||||
return parts.Join("<br>")
|
||||
|
||||
//A simple super light weight datum for the codex gigas.
|
||||
|
||||
@@ -57,3 +57,18 @@
|
||||
visible_message("<span class='danger'>[src] screams in agony as it sublimates into a sulfurous smoke.</span>")
|
||||
ghostize()
|
||||
qdel(src)
|
||||
|
||||
/datum/antagonist/imp
|
||||
name = "Imp"
|
||||
antagpanel_category = "Devil"
|
||||
show_in_roundend = FALSE
|
||||
|
||||
/datum/antagonist/imp/on_gain()
|
||||
. = ..()
|
||||
give_objectives()
|
||||
|
||||
/datum/antagonist/imp/proc/give_objectives()
|
||||
var/datum/objective/newobjective = new
|
||||
newobjective.explanation_text = "Try to get a promotion to a higher devilic rank."
|
||||
newobjective.owner = owner
|
||||
objectives += newobjective
|
||||
@@ -106,7 +106,7 @@
|
||||
/mob/living/carbon/true_devil/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
|
||||
return 666
|
||||
|
||||
/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
|
||||
/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
|
||||
if(mind && has_bane(BANE_LIGHT))
|
||||
mind.disrupt_spells(-500)
|
||||
return ..() //flashes don't stop devils UNLESS it's their bane.
|
||||
@@ -146,14 +146,9 @@
|
||||
/mob/living/carbon/true_devil/attack_ghost(mob/dead/observer/user as mob)
|
||||
if(ascended || user.mind.soulOwner == src.mind)
|
||||
var/mob/living/simple_animal/imp/S = new(get_turf(loc))
|
||||
S.key = user.key
|
||||
S.mind.assigned_role = "Imp"
|
||||
S.mind.special_role = "Imp"
|
||||
var/datum/objective/newobjective = new
|
||||
newobjective.explanation_text = "Try to get a promotion to a higher devilic rank."
|
||||
S.mind.objectives += newobjective
|
||||
to_chat(S, S.playstyle_string)
|
||||
to_chat(S, "<B>Objective #[1]</B>: [newobjective.explanation_text]")
|
||||
user.transfer_ckey(S, FALSE)
|
||||
var/datum/antagonist/imp/A = new()
|
||||
S.mind.add_antag_datum(A)
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -5,25 +5,48 @@ is currently following.
|
||||
*/
|
||||
|
||||
GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
new /datum/disease_ability/action/cough(),
|
||||
new /datum/disease_ability/action/sneeze(),
|
||||
new /datum/disease_ability/action/infect(),
|
||||
new /datum/disease_ability/symptom/cough(),
|
||||
new /datum/disease_ability/symptom/sneeze(),\
|
||||
new /datum/disease_ability/symptom/hallucigen(),
|
||||
new /datum/disease_ability/symptom/choking(),
|
||||
new /datum/disease_ability/symptom/confusion(),
|
||||
new /datum/disease_ability/symptom/youth(),
|
||||
new /datum/disease_ability/symptom/vomit(),
|
||||
new /datum/disease_ability/symptom/voice_change(),
|
||||
new /datum/disease_ability/symptom/visionloss(),
|
||||
new /datum/disease_ability/symptom/viraladaptation(),
|
||||
new /datum/disease_ability/symptom/vitiligo(),
|
||||
new /datum/disease_ability/symptom/sensory_restoration(),
|
||||
new /datum/disease_ability/symptom/itching(),
|
||||
new /datum/disease_ability/symptom/weight_loss(),
|
||||
new /datum/disease_ability/symptom/metabolism_heal(),
|
||||
new /datum/disease_ability/symptom/coma_heal()
|
||||
new /datum/disease_ability/action/cough,
|
||||
new /datum/disease_ability/action/sneeze,
|
||||
new /datum/disease_ability/action/infect,
|
||||
new /datum/disease_ability/symptom/mild/cough,
|
||||
new /datum/disease_ability/symptom/mild/sneeze,
|
||||
new /datum/disease_ability/symptom/medium/shedding,
|
||||
new /datum/disease_ability/symptom/medium/beard,
|
||||
new /datum/disease_ability/symptom/medium/hallucigen,
|
||||
new /datum/disease_ability/symptom/medium/choking,
|
||||
new /datum/disease_ability/symptom/medium/confusion,
|
||||
new /datum/disease_ability/symptom/medium/vomit,
|
||||
new /datum/disease_ability/symptom/medium/voice_change,
|
||||
new /datum/disease_ability/symptom/medium/visionloss,
|
||||
new /datum/disease_ability/symptom/medium/deafness,
|
||||
new /datum/disease_ability/symptom/powerful/narcolepsy,
|
||||
new /datum/disease_ability/symptom/medium/fever,
|
||||
new /datum/disease_ability/symptom/medium/shivering,
|
||||
new /datum/disease_ability/symptom/medium/headache,
|
||||
new /datum/disease_ability/symptom/medium/nano_boost,
|
||||
new /datum/disease_ability/symptom/medium/nano_destroy,
|
||||
new /datum/disease_ability/symptom/medium/viraladaptation,
|
||||
new /datum/disease_ability/symptom/medium/viralevolution,
|
||||
new /datum/disease_ability/symptom/medium/vitiligo,
|
||||
new /datum/disease_ability/symptom/medium/revitiligo,
|
||||
new /datum/disease_ability/symptom/medium/itching,
|
||||
new /datum/disease_ability/symptom/medium/heal/weight_loss,
|
||||
new /datum/disease_ability/symptom/medium/heal/sensory_restoration,
|
||||
new /datum/disease_ability/symptom/medium/heal/mind_restoration,
|
||||
new /datum/disease_ability/symptom/powerful/fire,
|
||||
new /datum/disease_ability/symptom/powerful/flesh_eating,
|
||||
// new /datum/disease_ability/symptom/powerful/genetic_mutation,
|
||||
new /datum/disease_ability/symptom/powerful/inorganic_adaptation,
|
||||
new /datum/disease_ability/symptom/powerful/heal/starlight,
|
||||
new /datum/disease_ability/symptom/powerful/heal/oxygen,
|
||||
new /datum/disease_ability/symptom/powerful/heal/chem,
|
||||
new /datum/disease_ability/symptom/powerful/heal/metabolism,
|
||||
new /datum/disease_ability/symptom/powerful/heal/dark,
|
||||
new /datum/disease_ability/symptom/powerful/heal/water,
|
||||
new /datum/disease_ability/symptom/powerful/heal/plasma,
|
||||
new /datum/disease_ability/symptom/powerful/heal/radiation,
|
||||
new /datum/disease_ability/symptom/powerful/heal/coma,
|
||||
new /datum/disease_ability/symptom/powerful/youth
|
||||
))
|
||||
|
||||
/datum/disease_ability
|
||||
@@ -54,7 +77,13 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
stage_speed += initial(S.stage_speed)
|
||||
transmittable += initial(S.transmittable)
|
||||
threshold_block += "<br><br>[initial(S.threshold_desc)]"
|
||||
stat_block = "Resistance: [resistance]<br>Stealth: [stealth]<br>Stage Speed: [stage_speed]<br>Transmissibility: [transmittable]<br><br>"
|
||||
stat_block = "Resistance: [resistance]<br>Stealth: [stealth]<br>Stage Speed: [stage_speed]<br>Transmissibility: [transmittable]<br><br>"
|
||||
if(symptoms.len == 1) //lazy boy's dream
|
||||
name = initial(S.name)
|
||||
if(short_desc == "")
|
||||
short_desc = initial(S.desc)
|
||||
if(long_desc == "")
|
||||
long_desc = initial(S.desc)
|
||||
|
||||
/datum/disease_ability/proc/CanBuy(mob/camera/disease/D)
|
||||
if(world.time < D.next_adaptation_time)
|
||||
@@ -77,8 +106,10 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
for(var/T in symptoms)
|
||||
var/datum/symptom/S = new T()
|
||||
SD.symptoms += S
|
||||
S.OnAdd(SD)
|
||||
if(SD.processing)
|
||||
S.Start(SD)
|
||||
if(S.Start(SD))
|
||||
S.next_activation = world.time + rand(S.symptom_delay_min * 10, S.symptom_delay_max * 10)
|
||||
SD.Refresh()
|
||||
for(var/T in actions)
|
||||
var/datum/action/A = new T()
|
||||
@@ -105,6 +136,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
var/datum/symptom/S = locate(T) in SD.symptoms
|
||||
if(S)
|
||||
SD.symptoms -= S
|
||||
S.OnRemove(SD)
|
||||
if(SD.processing)
|
||||
S.End(SD)
|
||||
qdel(S)
|
||||
@@ -152,8 +184,9 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
return FALSE
|
||||
to_chat(D, "<span class='notice'>You force [L.real_name] to cough.</span>")
|
||||
L.emote("cough")
|
||||
var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
|
||||
SD.spread(2)
|
||||
if(L.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth
|
||||
var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
|
||||
SD.spread(2)
|
||||
StartCooldown()
|
||||
return TRUE
|
||||
|
||||
@@ -185,11 +218,12 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
return FALSE
|
||||
to_chat(D, "<span class='notice'>You force [L.real_name] to sneeze.</span>")
|
||||
L.emote("sneeze")
|
||||
var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
|
||||
if(L.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth
|
||||
var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
|
||||
|
||||
for(var/mob/living/M in oview(4, SD.affected_mob))
|
||||
if(is_A_facing_B(SD.affected_mob, M) && disease_air_spread_walk(get_turf(SD.affected_mob), get_turf(M)))
|
||||
M.AirborneContractDisease(SD, TRUE)
|
||||
for(var/mob/living/M in oview(4, SD.affected_mob))
|
||||
if(is_A_facing_B(SD.affected_mob, M) && disease_air_spread_walk(get_turf(SD.affected_mob), get_turf(M)))
|
||||
M.AirborneContractDisease(SD, TRUE)
|
||||
|
||||
StartCooldown()
|
||||
return TRUE
|
||||
@@ -235,154 +269,192 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
StartCooldown()
|
||||
return TRUE
|
||||
|
||||
//passive symptom abilities
|
||||
/*******************BASE SYMPTOM TYPES*******************/
|
||||
// cost is for convenience and can be changed. If you're changing req_tot_points then don't use the subtype...
|
||||
//healing costs more so you have to techswitch from naughty disease otherwise we'd have friendly disease for easy greentext (no fun!)
|
||||
|
||||
/datum/disease_ability/symptom/cough
|
||||
name = "Involuntary Coughing"
|
||||
symptoms = list(/datum/symptom/cough)
|
||||
/datum/disease_ability/symptom/mild
|
||||
cost = 2
|
||||
required_total_points = 4
|
||||
category = "Symptom (Weak)"
|
||||
|
||||
/datum/disease_ability/symptom/medium
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
category = "Symptom"
|
||||
|
||||
/datum/disease_ability/symptom/medium/heal
|
||||
cost = 5
|
||||
category = "Symptom (+)"
|
||||
|
||||
/datum/disease_ability/symptom/powerful
|
||||
cost = 4
|
||||
required_total_points = 16
|
||||
category = "Symptom (Strong)"
|
||||
|
||||
/datum/disease_ability/symptom/powerful/heal
|
||||
cost = 8
|
||||
category = "Symptom (Strong+)"
|
||||
|
||||
|
||||
/******MILD******/
|
||||
|
||||
/datum/disease_ability/symptom/mild/cough
|
||||
name = "Involuntary Coughing"
|
||||
symptoms = list(/datum/symptom/cough)
|
||||
short_desc = "Cause victims to cough intermittently."
|
||||
long_desc = "Cause victims to cough intermittently, spreading your infection if your transmissibility is high."
|
||||
|
||||
/datum/disease_ability/symptom/sneeze
|
||||
/datum/disease_ability/symptom/mild/sneeze
|
||||
name = "Involuntary Sneezing"
|
||||
symptoms = list(/datum/symptom/sneeze)
|
||||
cost = 2
|
||||
required_total_points = 4
|
||||
short_desc = "Cause victims to sneeze intermittently."
|
||||
long_desc = "Cause victims to sneeze intermittently, spreading your infection and also increasing transmissibility and resistance, at the cost of stealth."
|
||||
|
||||
/datum/disease_ability/symptom/beard
|
||||
//I don't think I need to justify the fact that this is the best symptom
|
||||
name = "Beard Growth"
|
||||
symptoms = list(/datum/symptom/beard)
|
||||
cost = 1
|
||||
required_total_points = 8
|
||||
short_desc = "Cause all victims to grow a luscious beard."
|
||||
long_desc = "Cause all victims to grow a luscious beard. Decreases stats slightly. Ineffective against Santa Claus."
|
||||
/******MEDIUM******/
|
||||
|
||||
/datum/disease_ability/symptom/hallucigen
|
||||
name = "Hallucinations"
|
||||
/datum/disease_ability/symptom/medium/shedding
|
||||
symptoms = list(/datum/symptom/shedding)
|
||||
|
||||
/datum/disease_ability/symptom/medium/beard
|
||||
symptoms = list(/datum/symptom/beard)
|
||||
short_desc = "Cause all victims to grow a luscious beard."
|
||||
long_desc = "Cause all victims to grow a luscious beard. Ineffective against Santa Claus."
|
||||
|
||||
/datum/disease_ability/symptom/medium/hallucigen
|
||||
symptoms = list(/datum/symptom/hallucigen)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to hallucinate."
|
||||
long_desc = "Cause victims to hallucinate. Decreases stats, especially resistance."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/choking
|
||||
name = "Choking"
|
||||
/datum/disease_ability/symptom/medium/choking
|
||||
symptoms = list(/datum/symptom/choking)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to choke."
|
||||
long_desc = "Cause victims to choke, threatening asphyxiation. Decreases stats, especially transmissibility."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/confusion
|
||||
name = "Confusion"
|
||||
/datum/disease_ability/symptom/medium/confusion
|
||||
symptoms = list(/datum/symptom/confusion)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to become confused."
|
||||
long_desc = "Cause victims to become confused intermittently."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/youth
|
||||
name = "Eternal Youth"
|
||||
symptoms = list(/datum/symptom/youth)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to become eternally young."
|
||||
long_desc = "Cause victims to become eternally young. Provides boosts to all stats except transmissibility."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/vomit
|
||||
name = "Vomiting"
|
||||
/datum/disease_ability/symptom/medium/vomit
|
||||
symptoms = list(/datum/symptom/vomit)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to vomit."
|
||||
long_desc = "Cause victims to vomit. Slightly increases transmissibility. Vomiting also also causes the victims to lose nutrition and removes some toxin damage."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/voice_change
|
||||
name = "Voice Changing"
|
||||
/datum/disease_ability/symptom/medium/voice_change
|
||||
symptoms = list(/datum/symptom/voice_change)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Change the voice of victims."
|
||||
long_desc = "Change the voice of victims, causing confusion in communications."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/visionloss
|
||||
name = "Vision Loss"
|
||||
/datum/disease_ability/symptom/medium/visionloss
|
||||
symptoms = list(/datum/symptom/visionloss)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Damage the eyes of victims, eventually causing blindness."
|
||||
long_desc = "Damage the eyes of victims, eventually causing blindness. Decreases all stats."
|
||||
|
||||
/datum/disease_ability/symptom/medium/deafness
|
||||
symptoms = list(/datum/symptom/deafness)
|
||||
|
||||
/datum/disease_ability/symptom/viraladaptation
|
||||
name = "Self-Adaptation"
|
||||
/datum/disease_ability/symptom/medium/fever
|
||||
symptoms = list(/datum/symptom/fever)
|
||||
|
||||
/datum/disease_ability/symptom/medium/shivering
|
||||
symptoms = list(/datum/symptom/shivering)
|
||||
|
||||
/datum/disease_ability/symptom/medium/headache
|
||||
symptoms = list(/datum/symptom/headache)
|
||||
|
||||
/datum/disease_ability/symptom/medium/nano_boost
|
||||
symptoms = list(/datum/symptom/nano_boost)
|
||||
|
||||
/datum/disease_ability/symptom/medium/nano_destroy
|
||||
symptoms = list(/datum/symptom/nano_destroy)
|
||||
|
||||
/datum/disease_ability/symptom/medium/viraladaptation
|
||||
symptoms = list(/datum/symptom/viraladaptation)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause your infection to become more resistant to detection and eradication."
|
||||
long_desc = "Cause your infection to mimic the function of normal body cells, becoming much harder to spot and to eradicate, but reducing its speed."
|
||||
|
||||
/datum/disease_ability/symptom/medium/viralevolution
|
||||
symptoms = list(/datum/symptom/viralevolution)
|
||||
|
||||
/datum/disease_ability/symptom/vitiligo
|
||||
name = "Skin Paleness"
|
||||
/datum/disease_ability/symptom/medium/vitiligo
|
||||
symptoms = list(/datum/symptom/vitiligo)
|
||||
cost = 1
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to become pale."
|
||||
long_desc = "Cause victims to become pale. Decreases all stats."
|
||||
|
||||
/datum/disease_ability/symptom/medium/revitiligo
|
||||
symptoms = list(/datum/symptom/revitiligo)
|
||||
|
||||
/datum/disease_ability/symptom/sensory_restoration
|
||||
name = "Sensory Restoration"
|
||||
symptoms = list(/datum/symptom/sensory_restoration)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Regenerate eye and ear damage of victims."
|
||||
long_desc = "Regenerate eye and ear damage of victims."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/itching
|
||||
name = "Itching"
|
||||
/datum/disease_ability/symptom/medium/itching
|
||||
symptoms = list(/datum/symptom/itching)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to itch."
|
||||
long_desc = "Cause victims to itch, increasing all stats except stealth."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/weight_loss
|
||||
name = "Weight Loss"
|
||||
/datum/disease_ability/symptom/medium/heal/weight_loss
|
||||
symptoms = list(/datum/symptom/weight_loss)
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to lose weight."
|
||||
long_desc = "Cause victims to lose weight, and make it almost impossible for them to gain nutrition from food. Reduced nutrition allows your infection to spread more easily from hosts, especially by sneezing."
|
||||
|
||||
/datum/disease_ability/symptom/medium/heal/sensory_restoration
|
||||
symptoms = list(/datum/symptom/sensory_restoration)
|
||||
short_desc = "Regenerate eye and ear damage of victims."
|
||||
long_desc = "Regenerate eye and ear damage of victims."
|
||||
|
||||
/datum/disease_ability/symptom/metabolism_heal
|
||||
name = "Metabolic Boost"
|
||||
/datum/disease_ability/symptom/medium/heal/mind_restoration
|
||||
symptoms = list(/datum/symptom/mind_restoration)
|
||||
|
||||
/******POWERFUL******/
|
||||
|
||||
/datum/disease_ability/symptom/powerful/fire
|
||||
symptoms = list(/datum/symptom/fire)
|
||||
|
||||
/datum/disease_ability/symptom/powerful/flesh_eating
|
||||
symptoms = list(/datum/symptom/flesh_eating)
|
||||
|
||||
/*
|
||||
/datum/disease_ability/symptom/powerful/genetic_mutation
|
||||
symptoms = list(/datum/symptom/genetic_mutation)
|
||||
cost = 8
|
||||
*/
|
||||
|
||||
/datum/disease_ability/symptom/powerful/inorganic_adaptation
|
||||
symptoms = list(/datum/symptom/inorganic_adaptation)
|
||||
|
||||
/datum/disease_ability/symptom/powerful/narcolepsy
|
||||
symptoms = list(/datum/symptom/narcolepsy)
|
||||
|
||||
/datum/disease_ability/symptom/powerful/youth
|
||||
symptoms = list(/datum/symptom/youth)
|
||||
short_desc = "Cause victims to become eternally young."
|
||||
long_desc = "Cause victims to become eternally young. Provides boosts to all stats except transmissibility."
|
||||
|
||||
/****HEALING SUBTYPE****/
|
||||
|
||||
/datum/disease_ability/symptom/powerful/heal/starlight
|
||||
symptoms = list(/datum/symptom/heal/starlight)
|
||||
|
||||
/datum/disease_ability/symptom/powerful/heal/oxygen
|
||||
symptoms = list(/datum/symptom/oxygen)
|
||||
|
||||
/datum/disease_ability/symptom/powerful/heal/chem
|
||||
symptoms = list(/datum/symptom/heal/chem)
|
||||
|
||||
/datum/disease_ability/symptom/powerful/heal/metabolism
|
||||
symptoms = list(/datum/symptom/heal/metabolism)
|
||||
cost = 4
|
||||
required_total_points = 16
|
||||
short_desc = "Increase the metabolism of victims, causing them to process chemicals and grow hungry faster."
|
||||
long_desc = "Increase the metabolism of victims, causing them to process chemicals twice as fast and grow hungry more quickly."
|
||||
|
||||
/datum/disease_ability/symptom/powerful/heal/dark
|
||||
symptoms = list(/datum/symptom/heal/darkness)
|
||||
|
||||
/datum/disease_ability/symptom/coma_heal
|
||||
name = "Regenerative Coma"
|
||||
/datum/disease_ability/symptom/powerful/heal/water
|
||||
symptoms = list(/datum/symptom/heal/water)
|
||||
|
||||
/datum/disease_ability/symptom/powerful/heal/plasma
|
||||
symptoms = list(/datum/symptom/heal/plasma)
|
||||
|
||||
/datum/disease_ability/symptom/powerful/heal/radiation
|
||||
symptoms = list(/datum/symptom/heal/radiation)
|
||||
|
||||
/datum/disease_ability/symptom/powerful/heal/coma
|
||||
symptoms = list(/datum/symptom/heal/coma)
|
||||
cost = 8
|
||||
required_total_points = 16
|
||||
short_desc = "Cause victims to fall into a healing coma when hurt."
|
||||
long_desc = "Cause victims to fall into a healing coma when hurt."
|
||||
|
||||
@@ -10,12 +10,10 @@
|
||||
var/datum/objective/O = new /datum/objective/disease_infect()
|
||||
O.owner = owner
|
||||
objectives += O
|
||||
owner.objectives += O
|
||||
|
||||
O = new /datum/objective/disease_infect_centcom()
|
||||
O.owner = owner
|
||||
objectives += O
|
||||
owner.objectives += O
|
||||
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
if(cures.len)
|
||||
return
|
||||
var/list/not_used = advance_cures.Copy()
|
||||
not_used.Cut(1, 6) // Removes the first five tiers of cures.
|
||||
cures = list(pick(pick_n_take(not_used)), pick(pick_n_take(not_used)))
|
||||
|
||||
// Get the cure name from the cure_id
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
name = "Spawn Sentient Disease"
|
||||
typepath = /datum/round_event/ghost_role/sentient_disease
|
||||
weight = 7
|
||||
gamemode_blacklist = list("dynamic")
|
||||
max_occurrences = 1
|
||||
min_players = 5
|
||||
|
||||
@@ -18,7 +19,7 @@
|
||||
var/mob/dead/observer/selected = pick_n_take(candidates)
|
||||
|
||||
var/mob/camera/disease/virus = new /mob/camera/disease(SSmapping.get_station_center())
|
||||
virus.key = selected.key
|
||||
selected.transfer_ckey(virus, FALSE)
|
||||
INVOKE_ASYNC(virus, /mob/camera/disease/proc/pick_name)
|
||||
message_admins("[ADMIN_LOOKUPFLW(virus)] has been made into a sentient disease by an event.")
|
||||
log_game("[key_name(virus)] was spawned as a sentient disease by an event.")
|
||||
|
||||
@@ -9,7 +9,7 @@ the new instance inside the host to be updated to the template's stats.
|
||||
name = "Sentient Disease"
|
||||
real_name = "Sentient Disease"
|
||||
desc = ""
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
icon = 'icons/mob/cameramob.dmi'
|
||||
icon_state = "marker"
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
move_on_shuttle = FALSE
|
||||
@@ -18,7 +18,7 @@ the new instance inside the host to be updated to the template's stats.
|
||||
layer = BELOW_MOB_LAYER
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
sight = SEE_SELF|SEE_THRU
|
||||
initial_language_holder = /datum/language_holder/empty
|
||||
initial_language_holder = /datum/language_holder/universal
|
||||
|
||||
var/freemove = TRUE
|
||||
var/freemove_end = 0
|
||||
@@ -31,7 +31,6 @@ the new instance inside the host to be updated to the template's stats.
|
||||
var/browser_open = FALSE
|
||||
|
||||
var/mob/living/following_host
|
||||
var/datum/component/redirect/move_listener
|
||||
var/list/disease_instances
|
||||
var/list/hosts //this list is associative, affected_mob -> disease_instance
|
||||
var/datum/disease/advance/sentient_disease/disease_template
|
||||
@@ -43,7 +42,7 @@ the new instance inside the host to be updated to the template's stats.
|
||||
var/move_delay = 1
|
||||
|
||||
var/next_adaptation_time = 0
|
||||
var/adaptation_cooldown = 1200
|
||||
var/adaptation_cooldown = 600
|
||||
|
||||
var/list/purchased_abilities
|
||||
var/list/unpurchased_abilities
|
||||
@@ -118,10 +117,28 @@ the new instance inside the host to be updated to the template's stats.
|
||||
follow_next(Dir & NORTHWEST)
|
||||
last_move_tick = world.time
|
||||
|
||||
/mob/camera/disease/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
. = ..()
|
||||
var/atom/movable/to_follow = speaker
|
||||
if(radio_freq)
|
||||
var/atom/movable/virtualspeaker/V = speaker
|
||||
to_follow = V.source
|
||||
var/link
|
||||
if(to_follow in hosts)
|
||||
link = FOLLOW_LINK(src, to_follow)
|
||||
else
|
||||
link = ""
|
||||
// Recompose the message, because it's scrambled by default
|
||||
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
to_chat(src, "[link] [message]")
|
||||
|
||||
|
||||
/mob/camera/disease/mind_initialize()
|
||||
. = ..()
|
||||
if(!mind.has_antag_datum(/datum/antagonist/disease))
|
||||
mind.add_antag_datum(/datum/antagonist/disease)
|
||||
var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
medsensor.add_hud_to(src)
|
||||
|
||||
/mob/camera/disease/proc/pick_name()
|
||||
var/static/list/taken_names
|
||||
@@ -243,13 +260,10 @@ the new instance inside the host to be updated to the template's stats.
|
||||
refresh_adaptation_menu()
|
||||
|
||||
/mob/camera/disease/proc/set_following(mob/living/L)
|
||||
if(following_host)
|
||||
UnregisterSignal(following_host, COMSIG_MOVABLE_MOVED)
|
||||
RegisterSignal(L, COMSIG_MOVABLE_MOVED, .proc/follow_mob)
|
||||
following_host = L
|
||||
if(!move_listener)
|
||||
move_listener = L.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/follow_mob)))
|
||||
else
|
||||
L.TakeComponent(move_listener)
|
||||
if(QDELING(move_listener))
|
||||
move_listener = null
|
||||
follow_mob()
|
||||
|
||||
/mob/camera/disease/proc/follow_next(reverse = FALSE)
|
||||
|
||||
@@ -113,7 +113,6 @@
|
||||
/datum/antagonist/ert/proc/forge_objectives()
|
||||
if(ert_team)
|
||||
objectives |= ert_team.objectives
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/ert/proc/equipERT()
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
O.completed = TRUE //YES!
|
||||
O.owner = owner
|
||||
objectives += O
|
||||
owner.objectives += objectives
|
||||
|
||||
/datum/antagonist/greentext/on_gain()
|
||||
forge_objectives()
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
hijack_objective.owner = owner
|
||||
objectives += hijack_objective
|
||||
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/highlander/on_gain()
|
||||
forge_objectives()
|
||||
owner.special_role = "highlander"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/datum/antagonist/magic_servant
|
||||
name = "Magic Servant"
|
||||
show_in_roundend = FALSE
|
||||
show_in_antagpanel = FALSE
|
||||
|
||||
/datum/antagonist/magic_servant/proc/setup_master(mob/M)
|
||||
var/datum/objective/O = new("Serve [M.real_name].")
|
||||
O.owner = owner
|
||||
objectives |= O
|
||||
@@ -63,7 +63,6 @@
|
||||
|
||||
/datum/antagonist/monkey/proc/forge_objectives()
|
||||
objectives |= monkey_team.objectives
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/monkey/admin_remove(mob/admin)
|
||||
var/mob/living/carbon/monkey/M = owner.current
|
||||
|
||||
@@ -96,7 +96,6 @@
|
||||
var/datum/objective/O = new /datum/objective/survive()
|
||||
O.owner = owner
|
||||
objectives += O
|
||||
owner.objectives |= objectives
|
||||
|
||||
/proc/remove_ninja(mob/living/L)
|
||||
if(!L || !L.mind)
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/obj/item/borg_chameleon
|
||||
name = "cyborg chameleon projector"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "shield0"
|
||||
flags_1 = CONDUCT_1
|
||||
item_flags = NOBLUDGEON
|
||||
item_state = "electronic"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/friendlyName
|
||||
var/savedName
|
||||
var/active = FALSE
|
||||
var/activationCost = 300
|
||||
var/activationUpkeep = 50
|
||||
var/disguise = null
|
||||
var/disguise_icon_override = null
|
||||
var/disguise_pixel_offset = null
|
||||
var/mob/listeningTo
|
||||
var/static/list/signalCache = list( // list here all signals that should break the camouflage
|
||||
COMSIG_PARENT_ATTACKBY,
|
||||
COMSIG_ATOM_ATTACK_HAND,
|
||||
COMSIG_MOVABLE_IMPACT_ZONE,
|
||||
COMSIG_ATOM_BULLET_ACT,
|
||||
COMSIG_ATOM_EX_ACT,
|
||||
COMSIG_ATOM_FIRE_ACT,
|
||||
COMSIG_ATOM_EMP_ACT,
|
||||
)
|
||||
var/mob/living/silicon/robot/user // needed for process()
|
||||
var/animation_playing = FALSE
|
||||
|
||||
var/list/engymodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Marina", "Can", "Spider", "Loader","Handy", "Pup Dozer", "Vale")
|
||||
|
||||
|
||||
/obj/item/borg_chameleon/Initialize()
|
||||
. = ..()
|
||||
friendlyName = pick(GLOB.ai_names)
|
||||
|
||||
/obj/item/borg_chameleon/Destroy()
|
||||
listeningTo = null
|
||||
return ..()
|
||||
|
||||
/obj/item/borg_chameleon/dropped(mob/user)
|
||||
. = ..()
|
||||
disrupt(user)
|
||||
|
||||
/obj/item/borg_chameleon/equipped(mob/user)
|
||||
. = ..()
|
||||
disrupt(user)
|
||||
|
||||
/obj/item/borg_chameleon/attack_self(mob/living/silicon/robot/user)
|
||||
if (user && user.cell && user.cell.charge > activationCost)
|
||||
if (isturf(user.loc))
|
||||
toggle(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You can't use [src] while inside something!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need at least [activationCost] charge in your cell to use [src]!</span>")
|
||||
|
||||
/obj/item/borg_chameleon/proc/toggle(mob/living/silicon/robot/user)
|
||||
if(active)
|
||||
playsound(src, 'sound/effects/pop.ogg', 100, TRUE, -6)
|
||||
to_chat(user, "<span class='notice'>You deactivate \the [src].</span>")
|
||||
deactivate(user)
|
||||
else
|
||||
if(animation_playing)
|
||||
to_chat(user, "<span class='notice'>\the [src] is recharging.</span>")
|
||||
return
|
||||
var/borg_icon = input(user, "Select an icon!", "Robot Icon", null) as null|anything in engymodels
|
||||
if(!borg_icon)
|
||||
return FALSE
|
||||
switch(borg_icon)
|
||||
if("Default")
|
||||
disguise = "engineer"
|
||||
disguise_icon_override = 'icons/mob/robots.dmi'
|
||||
if("Default - Treads")
|
||||
disguise = "engi-tread"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Loader")
|
||||
disguise = "loaderborg"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Handy")
|
||||
disguise = "handyeng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Sleek")
|
||||
disguise = "sleekeng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Can")
|
||||
disguise = "caneng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Marina")
|
||||
disguise = "marinaeng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Spider")
|
||||
disguise = "spidereng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Heavy")
|
||||
disguise = "heavyeng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Pup Dozer")
|
||||
disguise = "pupdozer"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
|
||||
disguise_pixel_offset = -16
|
||||
if("Vale")
|
||||
disguise = "valeeng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
|
||||
disguise_pixel_offset = -16
|
||||
animation_playing = TRUE
|
||||
to_chat(user, "<span class='notice'>You activate \the [src].</span>")
|
||||
playsound(src, 'sound/effects/seedling_chargeup.ogg', 100, TRUE, -6)
|
||||
var/start = user.filters.len
|
||||
var/X,Y,rsq,i,f
|
||||
for(i=1, i<=7, ++i)
|
||||
do
|
||||
X = 60*rand() - 30
|
||||
Y = 60*rand() - 30
|
||||
rsq = X*X + Y*Y
|
||||
while(rsq<100 || rsq>900)
|
||||
user.filters += filter(type="wave", x=X, y=Y, size=rand()*2.5+0.5, offset=rand())
|
||||
for(i=1, i<=7, ++i)
|
||||
f = user.filters[start+i]
|
||||
animate(f, offset=f:offset, time=0, loop=3, flags=ANIMATION_PARALLEL)
|
||||
animate(offset=f:offset-1, time=rand()*20+10)
|
||||
if (do_after(user, 50, target=user) && user.cell.use(activationCost))
|
||||
playsound(src, 'sound/effects/bamf.ogg', 100, TRUE, -6)
|
||||
to_chat(user, "<span class='notice'>You are now disguised as the Nanotrasen engineering borg \"[friendlyName]\".</span>")
|
||||
activate(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The chameleon field fizzles.</span>")
|
||||
do_sparks(3, FALSE, user)
|
||||
for(i=1, i<=min(7, user.filters.len), ++i) // removing filters that are animating does nothing, we gotta stop the animations first
|
||||
f = user.filters[start+i]
|
||||
animate(f)
|
||||
user.filters = null
|
||||
animation_playing = FALSE
|
||||
|
||||
/obj/item/borg_chameleon/process()
|
||||
if (user)
|
||||
if (!user.cell || !user.cell.use(activationUpkeep))
|
||||
disrupt(user)
|
||||
else
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/item/borg_chameleon/proc/activate(mob/living/silicon/robot/user)
|
||||
START_PROCESSING(SSobj, src)
|
||||
src.user = user
|
||||
savedName = user.name
|
||||
user.name = friendlyName
|
||||
user.module.cyborg_base_icon = disguise
|
||||
user.module.cyborg_icon_override = disguise_icon_override
|
||||
user.module.cyborg_pixel_offset = disguise_pixel_offset
|
||||
user.bubble_icon = "robot"
|
||||
active = TRUE
|
||||
user.update_icons()
|
||||
|
||||
if(listeningTo == user)
|
||||
return
|
||||
if(listeningTo)
|
||||
UnregisterSignal(listeningTo, signalCache)
|
||||
RegisterSignal(user, signalCache, .proc/disrupt)
|
||||
listeningTo = user
|
||||
|
||||
/obj/item/borg_chameleon/proc/deactivate(mob/living/silicon/robot/user)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(listeningTo)
|
||||
UnregisterSignal(listeningTo, signalCache)
|
||||
listeningTo = null
|
||||
do_sparks(5, FALSE, user)
|
||||
user.name = savedName
|
||||
user.module.cyborg_base_icon = initial(user.module.cyborg_base_icon)
|
||||
user.module.cyborg_icon_override = 'icons/mob/robots.dmi'
|
||||
user.bubble_icon = "syndibot"
|
||||
active = FALSE
|
||||
user.update_icons()
|
||||
user.pixel_x = 0 //this solely exists because of dogborgs. I want anyone who ever reads this code later on to know this. Don't ask me why it's here, doesn't work above update_icons()
|
||||
src.user = user
|
||||
|
||||
/obj/item/borg_chameleon/proc/disrupt(mob/living/silicon/robot/user)
|
||||
if(active)
|
||||
to_chat(user, "<span class='danger'>Your chameleon field deactivates.</span>")
|
||||
deactivate(user)
|
||||
@@ -1,7 +1,8 @@
|
||||
#define CHALLENGE_TELECRYSTALS 280
|
||||
#define PLAYER_SCALING 1.5
|
||||
#define CHALLENGE_TIME_LIMIT 3000
|
||||
#define CHALLENGE_MIN_PLAYERS 50
|
||||
#define CHALLENGE_PLAYERS_TARGET 50 //target players population. anything below is a malus to the challenge tc bonus.
|
||||
#define TELECRYSTALS_MALUS_SCALING 1 //the higher the value, the bigger the malus.
|
||||
#define CHALLENGE_SHUTTLE_DELAY 15000 // 25 minutes, so the ops have at least 5 minutes before the shuttle is callable.
|
||||
|
||||
GLOBAL_LIST_EMPTY(jam_on_wardec)
|
||||
@@ -62,14 +63,22 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
|
||||
|
||||
for(var/obj/machinery/computer/camera_advanced/shuttle_docker/D in GLOB.jam_on_wardec)
|
||||
D.jammed = TRUE
|
||||
|
||||
GLOB.war_declared = TRUE
|
||||
|
||||
GLOB.war_declared = TRUE
|
||||
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
|
||||
var/actual_players = GLOB.joined_player_list.len - nukeops.len
|
||||
var/tc_malus = 0
|
||||
if(actual_players < CHALLENGE_PLAYERS_TARGET)
|
||||
tc_malus = FLOOR(((CHALLENGE_TELECRYSTALS / CHALLENGE_PLAYERS_TARGET) * (CHALLENGE_PLAYERS_TARGET - actual_players)) * TELECRYSTALS_MALUS_SCALING, 1)
|
||||
|
||||
new uplink_type(get_turf(user), user.key, CHALLENGE_TELECRYSTALS + CEILING(PLAYER_SCALING * actual_players, 1))
|
||||
new uplink_type(get_turf(user), user.key, CHALLENGE_TELECRYSTALS - tc_malus + CEILING(PLAYER_SCALING * actual_players, 1))
|
||||
|
||||
CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY))
|
||||
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
var/threat_spent = CONFIG_GET(number/dynamic_warops_cost)
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Nuke ops spent [threat_spent] on war ops.")
|
||||
SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1)
|
||||
|
||||
qdel(src)
|
||||
@@ -79,11 +88,6 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
|
||||
to_chat(user, "You are already in the process of declaring war! Make your mind up.")
|
||||
return FALSE
|
||||
|
||||
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
|
||||
var/actual_players = GLOB.joined_player_list.len - nukeops.len
|
||||
if(actual_players < CHALLENGE_MIN_PLAYERS)
|
||||
to_chat(user, "The enemy crew is too small to be worth declaring war on.")
|
||||
return FALSE
|
||||
if(!user.onSyndieBase())
|
||||
to_chat(user, "You have to be at your base to use this.")
|
||||
return FALSE
|
||||
@@ -95,6 +99,14 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
|
||||
if(board.moved)
|
||||
to_chat(user, "The shuttle has already been moved! You have forfeit the right to declare war.")
|
||||
return FALSE
|
||||
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat_level < CONFIG_GET(number/dynamic_warops_requirement))
|
||||
to_chat(user, "Due to the dynamic space in which the station resides, you are too deep into Nanotrasen territory to reasonably go loud.")
|
||||
return FALSE
|
||||
else if(mode.threat < CONFIG_GET(number/dynamic_warops_cost))
|
||||
to_chat(user, "Due to recent threats on the station, Nanotrasen is looking too closely for a war declaration to be wise.")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/nuclear_challenge/clownops
|
||||
@@ -102,5 +114,6 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
|
||||
|
||||
#undef CHALLENGE_TELECRYSTALS
|
||||
#undef CHALLENGE_TIME_LIMIT
|
||||
#undef CHALLENGE_MIN_PLAYERS
|
||||
#undef CHALLENGE_PLAYERS_TARGET
|
||||
#undef TELECRYSTALS_MALUS_SCALING
|
||||
#undef CHALLENGE_SHUTTLE_DELAY
|
||||
|
||||
@@ -343,10 +343,10 @@
|
||||
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/set_anchor()
|
||||
if(!isinspace())
|
||||
anchored = !anchored
|
||||
else
|
||||
if(isinspace() && !anchored)
|
||||
to_chat(usr, "<span class='warning'>There is nothing to anchor to!</span>")
|
||||
else
|
||||
anchored = !anchored
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/set_safety()
|
||||
safety = !safety
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
|
||||
/datum/antagonist/nukeop/proc/forge_objectives()
|
||||
if(nuke_team)
|
||||
owner.objectives |= nuke_team.objectives
|
||||
objectives |= nuke_team.objectives
|
||||
|
||||
/datum/antagonist/nukeop/proc/move_to_spawnpoint()
|
||||
var/team_number = 1
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
missionobj.completed = 1
|
||||
mission = missionobj
|
||||
objectives |= mission
|
||||
owner.objectives |= objectives
|
||||
|
||||
|
||||
/datum/antagonist/official/on_gain()
|
||||
forge_objectives()
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
// Sets objectives, equips all antags with the storage implant.
|
||||
/datum/antagonist/overthrow/on_gain()
|
||||
objectives += team.objectives
|
||||
owner.objectives += objectives
|
||||
..()
|
||||
owner.announce_objectives()
|
||||
equip_overthrow()
|
||||
@@ -34,7 +33,6 @@
|
||||
|
||||
/datum/antagonist/overthrow/on_removal()
|
||||
owner.special_role = null
|
||||
owner.objectives -= objectives
|
||||
..()
|
||||
|
||||
// Creates the overthrow team, or sets it. The objectives are static for all the team members.
|
||||
@@ -107,9 +105,9 @@
|
||||
/datum/antagonist/overthrow/proc/equip_overthrow()
|
||||
if(!owner || !owner.current || !ishuman(owner.current)) // only equip existing human overthrow members. This excludes the AI, in particular.
|
||||
return
|
||||
var/obj/item/implant/storage/S = locate(/obj/item/implant/storage) in owner.current
|
||||
var/obj/item/implant/storage/S = locate(/obj/item/implant/storage) in owner.current.implants
|
||||
if(!S)
|
||||
S = new(owner.current)
|
||||
S = new
|
||||
S.implant(owner.current)
|
||||
var/I = pick(possible_useful_items)
|
||||
if(ispath(I)) // in case some admin decides to fuck the list up for fun
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
objectives += heads_obj
|
||||
for(var/i in members)
|
||||
var/datum/mind/M = i
|
||||
M.objectives += heads_obj
|
||||
var/datum/antagonist/overthrow/O = M.has_antag_datum(/datum/antagonist/overthrow)
|
||||
if(O)
|
||||
O.objectives += heads_obj
|
||||
heads_obj.find_targets()
|
||||
|
||||
addtimer(CALLBACK(src,.proc/update_objectives),OBJECTIVE_UPDATING_TIME,TIMER_UNIQUE)
|
||||
|
||||
@@ -31,12 +31,7 @@
|
||||
|
||||
/datum/antagonist/pirate/on_gain()
|
||||
if(crew)
|
||||
owner.objectives |= crew.objectives
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/pirate/on_removal()
|
||||
if(crew)
|
||||
owner.objectives -= crew.objectives
|
||||
objectives |= crew.objectives
|
||||
. = ..()
|
||||
|
||||
/datum/team/pirate
|
||||
@@ -53,7 +48,9 @@
|
||||
getbooty.update_explanation_text()
|
||||
objectives += getbooty
|
||||
for(var/datum/mind/M in members)
|
||||
M.objectives |= objectives
|
||||
var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate)
|
||||
if(P)
|
||||
P.objectives |= objectives
|
||||
|
||||
|
||||
/datum/objective/loot
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
/mob/living/simple_animal/revenant/Initialize(mapload)
|
||||
. = ..()
|
||||
AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/targeted/telepathy/revenant(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/overload(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/blight(null))
|
||||
@@ -377,14 +377,15 @@
|
||||
/obj/item/ectoplasm/revenant/proc/reform()
|
||||
if(QDELETED(src) || QDELETED(revenant) || inert)
|
||||
return
|
||||
var/key_of_revenant
|
||||
var/key_of_revenant = FALSE
|
||||
message_admins("Revenant ectoplasm was left undestroyed for 1 minute and is reforming into a new revenant.")
|
||||
forceMove(drop_location()) //In case it's in a backpack or someone's hand
|
||||
revenant.forceMove(loc)
|
||||
if(old_key)
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
if(M.client && M.client.key == old_key) //Only recreates the mob if the mob the client is in is dead
|
||||
key_of_revenant = old_key
|
||||
M.transfer_ckey(revenant.key, FALSE)
|
||||
key_of_revenant = TRUE
|
||||
break
|
||||
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...")
|
||||
@@ -396,22 +397,21 @@
|
||||
visible_message("<span class='revenwarning'>[src] settles down and seems lifeless.</span>")
|
||||
return
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
key_of_revenant = C.key
|
||||
if(!key_of_revenant)
|
||||
C.transfer_ckey(revenant.key, FALSE)
|
||||
if(!revenant.key)
|
||||
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
|
||||
|
||||
message_admins("[key_of_revenant] has been [old_key == key_of_revenant ? "re":""]made into a revenant by reforming ectoplasm.")
|
||||
log_game("[key_of_revenant] was [old_key == key_of_revenant ? "re":""]made as a revenant by reforming ectoplasm.")
|
||||
message_admins("[key_of_revenant] has been [old_key == revenant.key ? "re":""]made into a revenant by reforming ectoplasm.")
|
||||
log_game("[key_of_revenant] was [old_key == revenant.key ? "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)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
if(prob(10))
|
||||
to_chat(target, "You feel as if you are being watched.")
|
||||
return
|
||||
face_atom(target)
|
||||
draining = TRUE
|
||||
essence_drained += rand(15, 20)
|
||||
to_chat(src, "<span class='revennotice'>You search for the soul of [target].</span>")
|
||||
@@ -65,7 +66,7 @@
|
||||
if(target.anti_magic_check(FALSE, TRUE))
|
||||
to_chat(src, "<span class='revenminor'>Something's wrong! [target] seems to be resisting the siphoning, leaving you vulnerable!</span>")
|
||||
target.visible_message("<span class='warning'>[target] slumps onto the ground.</span>", \
|
||||
"<span class='revenwarning'>Violets lights, dancing in your vision, receding--</span>")
|
||||
"<span class='revenwarning'>Violet lights, dancing in your vision, receding--</span>")
|
||||
draining = FALSE
|
||||
return
|
||||
var/datum/beam/B = Beam(target,icon_state="drain_life",time=INFINITY)
|
||||
@@ -104,36 +105,16 @@
|
||||
action_background_icon_state = "bg_revenant"
|
||||
|
||||
//Transmit: the revemant's only direct way to communicate. Sends a single message silently to a single mob
|
||||
/obj/effect/proc_holder/spell/targeted/revenant_transmit
|
||||
name = "Transmit"
|
||||
desc = "Telepathically transmits a message to the target."
|
||||
/obj/effect/proc_holder/spell/targeted/telepathy/revenant
|
||||
name = "Revenant Transmit"
|
||||
panel = "Revenant Abilities"
|
||||
charge_max = 0
|
||||
clothes_req = 0
|
||||
range = 7
|
||||
include_user = 0
|
||||
action_icon = 'icons/mob/actions/actions_revenant.dmi'
|
||||
action_icon_state = "r_transmit"
|
||||
action_background_icon_state = "bg_revenant"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/revenant_transmit/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
|
||||
for(var/mob/living/M in targets)
|
||||
var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "")
|
||||
if(!msg)
|
||||
charge_counter = charge_max
|
||||
return
|
||||
log_directed_talk(user, M, msg, LOG_SAY, "revenant whisper")
|
||||
to_chat(user, "<span class='revenboldnotice'>You transmit to [M]:</span> <span class='revennotice'>[msg]</span>")
|
||||
if(!M.anti_magic_check(FALSE, TRUE)) //hear no evil
|
||||
to_chat(M, "<span class='revenboldnotice'>You hear something behind you talking...</span> <span class='revennotice'>[msg]</span>")
|
||||
for(var/ded in GLOB.dead_mob_list)
|
||||
if(!isobserver(ded))
|
||||
continue
|
||||
var/follow_rev = FOLLOW_LINK(ded, user)
|
||||
var/follow_whispee = FOLLOW_LINK(ded, M)
|
||||
to_chat(ded, "[follow_rev] <span class='revenboldnotice'>[user] Revenant Transmit:</span> <span class='revennotice'>\"[msg]\" to</span> [follow_whispee] <span class='name'>[M]</span>")
|
||||
|
||||
|
||||
notice = "revennotice"
|
||||
boldnotice = "revenboldnotice"
|
||||
holy_check = TRUE
|
||||
tinfoil_check = FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/revenant
|
||||
clothes_req = 0
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
objective2.owner = owner
|
||||
objectives += objective2
|
||||
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/revenant/on_gain()
|
||||
forge_objectives()
|
||||
. = ..()
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
viable_mobtypes = list(/mob/living/carbon/human)
|
||||
disease_flags = CURABLE
|
||||
permeability_mod = 1
|
||||
severity = DISEASE_SEVERITY_HARMFUL
|
||||
var/stagedamage = 0 //Highest stage reached.
|
||||
var/finalstage = 0 //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
|
||||
severity = DISEASE_SEVERITY_DANGEROUS
|
||||
var/finalstage = FALSE //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
|
||||
var/depression = FALSE
|
||||
|
||||
/datum/disease/revblight/cure()
|
||||
if(affected_mob)
|
||||
@@ -21,12 +21,13 @@
|
||||
if(affected_mob.dna && affected_mob.dna.species)
|
||||
affected_mob.dna.species.handle_mutant_bodyparts(affected_mob)
|
||||
affected_mob.dna.species.handle_hair(affected_mob)
|
||||
to_chat(affected_mob, "<span class='notice'>You feel better.</span>")
|
||||
SEND_SIGNAL(affected_mob, COMSIG_CLEAR_MOOD_EVENT, "rev_blight")
|
||||
..()
|
||||
|
||||
/datum/disease/revblight/stage_act()
|
||||
if(!finalstage)
|
||||
if(affected_mob.lying && prob(stage*6))
|
||||
if(affected_mob.lying && prob(stage*4))
|
||||
to_chat(affected_mob, "<span class='notice'>You feel better.</span>")
|
||||
cure()
|
||||
return
|
||||
if(prob(stage*3))
|
||||
@@ -34,10 +35,6 @@
|
||||
affected_mob.confused += 8
|
||||
affected_mob.adjustStaminaLoss(8)
|
||||
new /obj/effect/temp_visual/revenant(affected_mob.loc)
|
||||
if(stagedamage < stage)
|
||||
stagedamage++
|
||||
affected_mob.adjustToxLoss(stage*2) //should, normally, do about 30 toxin damage.
|
||||
new /obj/effect/temp_visual/revenant(affected_mob.loc)
|
||||
if(prob(45))
|
||||
affected_mob.adjustStaminaLoss(stage)
|
||||
..() //So we don't increase a stage before applying the stage damage.
|
||||
@@ -46,9 +43,14 @@
|
||||
if(prob(5))
|
||||
affected_mob.emote("pale")
|
||||
if(3)
|
||||
if(!depression)
|
||||
SEND_SIGNAL(affected_mob, COMSIG_ADD_MOOD_EVENT, "rev_blight", /datum/mood_event/revenant_blight)
|
||||
depression = TRUE
|
||||
SEND_SIGNAL(affected_mob, COMSIG_MODIFY_SANITY, -0.12, SANITY_CRAZY)
|
||||
if(prob(10))
|
||||
affected_mob.emote(pick("pale","shiver"))
|
||||
if(4)
|
||||
SEND_SIGNAL(affected_mob, COMSIG_MODIFY_SANITY, -0.18, SANITY_CRAZY)
|
||||
if(prob(15))
|
||||
affected_mob.emote(pick("pale","shiver","cries"))
|
||||
if(5)
|
||||
@@ -56,12 +58,18 @@
|
||||
finalstage = TRUE
|
||||
to_chat(affected_mob, "<span class='revenbignotice'>You feel like [pick("nothing's worth it anymore", "nobody ever needed your help", "nothing you did mattered", "everything you tried to do was worthless")].</span>")
|
||||
affected_mob.adjustStaminaLoss(45)
|
||||
new /obj/effect/temp_visual/revenant(affected_mob.loc)
|
||||
if(affected_mob.dna && affected_mob.dna.species)
|
||||
if(affected_mob.dna?.species)
|
||||
affected_mob.dna.species.handle_mutant_bodyparts(affected_mob,"#1d2953")
|
||||
affected_mob.dna.species.handle_hair(affected_mob,"#1d2953")
|
||||
affected_mob.visible_message("<span class='warning'>[affected_mob] looks terrifyingly gaunt...</span>", "<span class='revennotice'>You suddenly feel like your skin is <i>wrong</i>...</span>")
|
||||
affected_mob.add_atom_colour("#1d2953", TEMPORARY_COLOUR_PRIORITY)
|
||||
addtimer(CALLBACK(src, .proc/cure), 100)
|
||||
else
|
||||
return
|
||||
new /obj/effect/temp_visual/revenant(affected_mob.loc)
|
||||
addtimer(CALLBACK(src, .proc/curses), 150)
|
||||
|
||||
/datum/disease/revblight/proc/curses()
|
||||
if(QDELETED(affected_mob))
|
||||
return
|
||||
affected_mob.playsound_local(affected_mob, 'sound/effects/curse5.ogg', 40, 1, -1)
|
||||
to_chat(affected_mob, "<span class='revendanger'>You sense the terrific curse of a vengeful ghost befall upon you...</span>")
|
||||
affected_mob.apply_necropolis_curse(null, 7 MINUTES) //Once the blight has done its course without being cured beforehand, it will cast a necrocurse to compensate how underpowered it's.
|
||||
cure()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
name = "Spawn Revenant" // Did you mean 'griefghost'?
|
||||
typepath = /datum/round_event/ghost_role/revenant
|
||||
weight = 7
|
||||
gamemode_blacklist = list("dynamic")
|
||||
max_occurrences = 1
|
||||
min_players = 5
|
||||
|
||||
@@ -52,7 +53,7 @@
|
||||
return MAP_ERROR
|
||||
|
||||
var/mob/living/simple_animal/revenant/revvie = new(pick(spawn_locs))
|
||||
revvie.key = selected.key
|
||||
selected.transfer_ckey(revvie, FALSE)
|
||||
message_admins("[ADMIN_LOOKUPFLW(revvie)] has been made into a revenant by an event.")
|
||||
log_game("[key_name(revvie)] was spawned as a revenant by an event.")
|
||||
spawned_mobs += revvie
|
||||
|
||||
@@ -66,10 +66,10 @@
|
||||
return rev_team
|
||||
|
||||
/datum/antagonist/rev/proc/create_objectives()
|
||||
owner.objectives |= rev_team.objectives
|
||||
objectives |= rev_team.objectives
|
||||
|
||||
/datum/antagonist/rev/proc/remove_objectives()
|
||||
owner.objectives -= rev_team.objectives
|
||||
objectives -= rev_team.objectives
|
||||
|
||||
//Bump up to head_rev
|
||||
/datum/antagonist/rev/proc/promote()
|
||||
@@ -207,9 +207,20 @@
|
||||
owner.current.visible_message("<span class='deconversion_message'>The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.</span>", null, null, null, owner.current)
|
||||
to_chat(owner, "<span class='userdanger'>The frame's firmware detects and deletes your neural reprogramming! You remember nothing of your time spent reprogrammed, you can't even remember the names or identities of anyone involved...</span>")
|
||||
|
||||
/datum/antagonist/rev/head/farewell()
|
||||
if((ishuman(owner.current) || ismonkey(owner.current)))
|
||||
if(owner.current.stat != DEAD)
|
||||
owner.current.visible_message("<span class='deconversion_message'>[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!</span>", null, null, null, owner.current)
|
||||
to_chat(owner, "<span class ='deconversion_message bold'>You have given up your cause of overthrowing the command staff. You are no longer a Head Revolutionary.</span>")
|
||||
else
|
||||
to_chat(owner, "<span class ='deconversion_message bold'>The sweet release of death. You are no longer a Head Revolutionary.</span>")
|
||||
else if(issilicon(owner.current))
|
||||
owner.current.visible_message("<span class='deconversion_message'>The frame beeps contentedly, suppressing the disloyal personality traits from the MMI before initalizing it.</span>", null, null, null, owner.current)
|
||||
to_chat(owner, "<span class='userdanger'>The frame's firmware detects and suppresses your unwanted personality traits! You feel more content with the leadership around these parts.</span>")
|
||||
|
||||
//blunt trauma deconversions call this through species.dm spec_attacked_by()
|
||||
/datum/antagonist/rev/proc/remove_revolutionary(borged, deconverter)
|
||||
log_attack("[key_name(owner.current)] has been deconverted from the revolution by [key_name(deconverter)]!")
|
||||
log_attack("[key_name(owner.current)] has been deconverted from the revolution by [ismob(deconverter) ? key_name(deconverter) : deconverter]!")
|
||||
if(borged)
|
||||
message_admins("[ADMIN_LOOKUPFLW(owner.current)] has been borged while being a [name]")
|
||||
owner.special_role = null
|
||||
@@ -219,9 +230,8 @@
|
||||
owner.remove_antag_datum(type)
|
||||
|
||||
/datum/antagonist/rev/head/remove_revolutionary(borged,deconverter)
|
||||
if(!borged)
|
||||
return
|
||||
. = ..()
|
||||
if(borged || deconverter == "gamemode")
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/rev/head/equip_rev()
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
@@ -253,6 +263,8 @@
|
||||
/datum/team/revolution
|
||||
name = "Revolution"
|
||||
var/max_headrevs = 3
|
||||
var/list/ex_headrevs = list() // Dynamic removes revs on loss, used to keep a list for the roundend report.
|
||||
var/list/ex_revs = list()
|
||||
|
||||
/datum/team/revolution/proc/update_objectives(initial = FALSE)
|
||||
var/untracked_heads = SSjob.get_all_heads()
|
||||
@@ -265,7 +277,8 @@
|
||||
new_target.update_explanation_text()
|
||||
objectives += new_target
|
||||
for(var/datum/mind/M in members)
|
||||
M.objectives |= objectives
|
||||
var/datum/antagonist/rev/R = M.has_antag_datum(/datum/antagonist/rev)
|
||||
R.objectives |= objectives
|
||||
|
||||
addtimer(CALLBACK(src,.proc/update_objectives),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
|
||||
|
||||
@@ -295,9 +308,12 @@
|
||||
|
||||
addtimer(CALLBACK(src,.proc/update_heads),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
|
||||
|
||||
/datum/team/revolution/proc/save_members()
|
||||
ex_headrevs = get_antag_minds(/datum/antagonist/rev/head, TRUE)
|
||||
ex_revs = get_antag_minds(/datum/antagonist/rev, TRUE)
|
||||
|
||||
/datum/team/revolution/roundend_report()
|
||||
if(!members.len)
|
||||
if(!members.len && !ex_headrevs.len)
|
||||
return
|
||||
|
||||
var/list/result = list()
|
||||
@@ -317,8 +333,17 @@
|
||||
|
||||
|
||||
var/list/targets = list()
|
||||
var/list/datum/mind/headrevs = get_antag_minds(/datum/antagonist/rev/head)
|
||||
var/list/datum/mind/revs = get_antag_minds(/datum/antagonist/rev,TRUE)
|
||||
var/list/datum/mind/headrevs
|
||||
var/list/datum/mind/revs
|
||||
if(ex_headrevs.len)
|
||||
headrevs = ex_headrevs
|
||||
else
|
||||
headrevs = get_antag_minds(/datum/antagonist/rev/head, TRUE)
|
||||
|
||||
if(ex_revs.len)
|
||||
revs = ex_revs
|
||||
else
|
||||
revs = get_antag_minds(/datum/antagonist/rev, TRUE)
|
||||
if(headrevs.len)
|
||||
var/list/headrev_part = list()
|
||||
headrev_part += "<span class='header'>The head revolutionaries were:</span>"
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/datum/antagonist/santa
|
||||
name = "Santa"
|
||||
show_in_antagpanel = FALSE
|
||||
|
||||
/datum/antagonist/santa/on_gain()
|
||||
. = ..()
|
||||
give_equipment()
|
||||
give_objective()
|
||||
|
||||
/datum/antagonist/santa/greet()
|
||||
. = ..()
|
||||
to_chat(owner, "<span class='boldannounce'>You are Santa! Your objective is to bring joy to the people on this station. You can conjure more presents using a spell, and there are several presents in your bag.</span>")
|
||||
|
||||
/datum/antagonist/santa/proc/give_equipment()
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(istype(H))
|
||||
H.equipOutfit(/datum/outfit/santa)
|
||||
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/presents)
|
||||
var/obj/effect/proc_holder/spell/targeted/area_teleport/teleport/telespell = new
|
||||
telespell.clothes_req = 0 //santa robes aren't actually magical.
|
||||
owner.AddSpell(telespell) //does the station have chimneys? WHO KNOWS!
|
||||
|
||||
/datum/antagonist/santa/proc/give_objective()
|
||||
var/datum/objective/santa_objective = new()
|
||||
santa_objective.explanation_text = "Bring joy and presents to the station!"
|
||||
santa_objective.completed = 1 //lets cut our santas some slack.
|
||||
santa_objective.owner = owner
|
||||
objectives |= santa_objective
|
||||
@@ -34,7 +34,6 @@
|
||||
melee_damage_upper = 30
|
||||
see_in_dark = 8
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
var/boost = 0
|
||||
bloodcrawl = BLOODCRAWL_EAT
|
||||
var/playstyle_string = "<span class='big bold'>You are a slaughter demon,</span><B> a terrible creature from another realm. You have a single desire: To kill. \
|
||||
You may use the \"Blood Crawl\" ability near blood pools to travel through them, appearing and disappearing from the station at will. \
|
||||
@@ -54,24 +53,18 @@
|
||||
if(istype(loc, /obj/effect/dummy/phased_mob/slaughter))
|
||||
bloodspell.phased = TRUE
|
||||
|
||||
/mob/living/simple_animal/slaughter/Life()
|
||||
..()
|
||||
if(boost<world.time)
|
||||
speed = 1
|
||||
else
|
||||
speed = 0
|
||||
|
||||
/obj/effect/decal/cleanable/blood/innards
|
||||
icon = 'icons/obj/surgery.dmi'
|
||||
name = "pile of viscera"
|
||||
desc = "A repulsive pile of guts and gore."
|
||||
gender = NEUTER
|
||||
icon_state = "innards"
|
||||
random_icon_states = null
|
||||
|
||||
/mob/living/simple_animal/slaughter/phasein()
|
||||
. = ..()
|
||||
speed = 0
|
||||
boost = world.time + 60
|
||||
add_movespeed_modifier(MOVESPEED_ID_SLAUGHTER, update=TRUE, priority=100, multiplicative_slowdown=-1)
|
||||
addtimer(CALLBACK(src, .proc/remove_movespeed_modifier, MOVESPEED_ID_SLAUGHTER, TRUE), 6 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
|
||||
|
||||
|
||||
//The loot from killing a slaughter demon - can be consumed to allow the user to blood crawl
|
||||
@@ -80,6 +73,7 @@
|
||||
desc = "Still it beats furiously, emanating an aura of utter hate."
|
||||
icon = 'icons/obj/surgery.dmi'
|
||||
icon_state = "demon_heart-on"
|
||||
decay_factor = 0
|
||||
|
||||
/obj/item/organ/heart/demon/update_icon()
|
||||
return //always beating visually
|
||||
@@ -100,7 +94,7 @@
|
||||
user.temporarilyRemoveItemFromInventory(src, TRUE)
|
||||
src.Insert(user) //Consuming the heart literally replaces your heart with a demon heart. H A R D C O R E
|
||||
|
||||
/obj/item/organ/heart/demon/Insert(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/heart/demon/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
|
||||
..()
|
||||
if(M.mind)
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null))
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
new_objective2.explanation_text = "[objective_verb] everyone[summoner ? " else while you're at it":""]."
|
||||
objectives += new_objective2
|
||||
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/slaughter/laughter
|
||||
name = "Laughter demon"
|
||||
objective_verb = "Hug and Tickle"
|
||||
@@ -3,6 +3,7 @@
|
||||
typepath = /datum/round_event/ghost_role/slaughter
|
||||
weight = 1 //Very rare
|
||||
max_occurrences = 1
|
||||
gamemode_blacklist = list("dynamic")
|
||||
earliest_start = 1 HOURS
|
||||
min_players = 20
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
var/datum/objective/survive/survive = new
|
||||
survive.owner = owner
|
||||
objectives += survive
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/survivalist/on_gain()
|
||||
owner.special_role = "survivalist"
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE)
|
||||
notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
|
||||
|
||||
/obj/effect/mob_spawn/swarmer/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
|
||||
@@ -78,15 +78,14 @@
|
||||
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
|
||||
for(var/datum/objective/objective_ in owner.mind.get_all_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)
|
||||
@@ -100,9 +99,9 @@
|
||||
return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal))
|
||||
|
||||
/datum/antagonist/traitor/proc/replace_escape_objective()
|
||||
if(!owner||!owner.objectives)
|
||||
if(!owner || !objectives.len)
|
||||
return
|
||||
for (var/objective_ in owner.objectives)
|
||||
for (var/objective_ in objectives)
|
||||
if(!(istype(objective_, /datum/objective/escape)||istype(objective_, /datum/objective/survive)))
|
||||
continue
|
||||
remove_objective(objective_)
|
||||
@@ -112,9 +111,9 @@
|
||||
add_objective(martyr_objective)
|
||||
|
||||
/datum/antagonist/traitor/proc/reinstate_escape_objective()
|
||||
if(!owner||!owner.objectives)
|
||||
if(!owner||!objectives.len)
|
||||
return
|
||||
for (var/objective_ in owner.objectives)
|
||||
for (var/objective_ in objectives)
|
||||
if(!istype(objective_, /datum/objective/martyr))
|
||||
continue
|
||||
remove_objective(objective_)
|
||||
@@ -131,7 +130,7 @@
|
||||
return
|
||||
to_chat(owner.current, "<span class='userdanger'> Target eliminated: [victim.name]</span>")
|
||||
LAZYINITLIST(targets_stolen)
|
||||
for(var/objective_ in victim.objectives)
|
||||
for(var/objective_ in victim.get_all_objectives())
|
||||
if(istype(objective_, /datum/objective/assassinate/internal))
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(objective.target==owner)
|
||||
@@ -159,7 +158,7 @@
|
||||
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>")
|
||||
last_man_standing = TRUE
|
||||
for(var/objective_ in owner.objectives)
|
||||
for(var/objective_ in objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
@@ -175,7 +174,7 @@
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/proc/iaa_process()
|
||||
if(owner&&owner.current&&owner.current.stat!=DEAD)
|
||||
for(var/objective_ in owner.objectives)
|
||||
for(var/objective_ in objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
@@ -224,8 +223,6 @@
|
||||
special_role = TRAITOR_AGENT_ROLE
|
||||
syndicate = TRUE
|
||||
forge_single_objective()
|
||||
else
|
||||
..() // Give them standard objectives.
|
||||
return
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/forge_traitor_objectives()
|
||||
|
||||
@@ -61,12 +61,10 @@
|
||||
owner.special_role = null
|
||||
..()
|
||||
|
||||
/datum/antagonist/traitor/proc/add_objective(var/datum/objective/O)
|
||||
owner.objectives += O
|
||||
/datum/antagonist/traitor/proc/add_objective(datum/objective/O)
|
||||
objectives += O
|
||||
|
||||
/datum/antagonist/traitor/proc/remove_objective(var/datum/objective/O)
|
||||
owner.objectives -= O
|
||||
/datum/antagonist/traitor/proc/remove_objective(datum/objective/O)
|
||||
objectives -= O
|
||||
|
||||
/datum/antagonist/traitor/proc/forge_traitor_objectives()
|
||||
@@ -78,7 +76,17 @@
|
||||
|
||||
/datum/antagonist/traitor/proc/forge_human_objectives()
|
||||
var/is_hijacker = FALSE
|
||||
if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks
|
||||
var/datum/game_mode/dynamic/mode
|
||||
var/is_dynamic = FALSE
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
mode = SSticker.mode
|
||||
is_dynamic = TRUE
|
||||
if(GLOB.joined_player_list.len>=GLOB.dynamic_high_pop_limit)
|
||||
is_hijacker = (prob(10) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement))
|
||||
else
|
||||
var/indice_pop = min(10,round(GLOB.joined_player_list.len/mode.pop_per_requirement)+1)
|
||||
is_hijacker = (prob(10) && (mode.threat_level >= CONFIG_GET(number_list/dynamic_hijack_requirements)[indice_pop]))
|
||||
else if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks
|
||||
is_hijacker = prob(10)
|
||||
var/martyr_chance = prob(20)
|
||||
var/objective_count = is_hijacker //Hijacking counts towards number of objectives
|
||||
@@ -95,15 +103,19 @@
|
||||
forge_single_objective()
|
||||
|
||||
if(is_hijacker && objective_count <= toa) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
|
||||
if (!(locate(/datum/objective/hijack) in owner.objectives))
|
||||
if (!(locate(/datum/objective/hijack) in objectives))
|
||||
var/datum/objective/hijack/hijack_objective = new
|
||||
hijack_objective.owner = owner
|
||||
add_objective(hijack_objective)
|
||||
if(is_dynamic)
|
||||
var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost)
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("[owner.name] spent [threat_spent] on hijack.")
|
||||
return
|
||||
|
||||
|
||||
var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead.
|
||||
for(var/datum/objective/O in owner.objectives)
|
||||
for(var/datum/objective/O in objectives)
|
||||
if(!O.martyr_compatible)
|
||||
martyr_compatibility = 0
|
||||
break
|
||||
@@ -112,10 +124,14 @@
|
||||
var/datum/objective/martyr/martyr_objective = new
|
||||
martyr_objective.owner = owner
|
||||
add_objective(martyr_objective)
|
||||
if(is_dynamic)
|
||||
var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost)
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("[owner.name] spent [threat_spent] on glorious death.")
|
||||
return
|
||||
|
||||
else
|
||||
if(!(locate(/datum/objective/escape) in owner.objectives))
|
||||
if(!(locate(/datum/objective/escape) in objectives))
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
add_objective(escape_objective)
|
||||
@@ -147,7 +163,18 @@
|
||||
|
||||
/datum/antagonist/traitor/proc/forge_single_human_objective() //Returns how many objectives are added
|
||||
.=1
|
||||
if(prob(50))
|
||||
var/assassin_prob = 50
|
||||
var/is_dynamic = FALSE
|
||||
var/datum/game_mode/dynamic/mode
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
mode = SSticker.mode
|
||||
is_dynamic = TRUE
|
||||
assassin_prob = mode.threat_level*(2/3)
|
||||
if(prob(assassin_prob))
|
||||
if(is_dynamic)
|
||||
var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost)
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("[owner.name] spent [threat_spent] on an assassination target.")
|
||||
var/list/active_ais = active_ais()
|
||||
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
|
||||
var/datum/objective/destroy/destroy_objective = new
|
||||
@@ -165,7 +192,7 @@
|
||||
kill_objective.find_target()
|
||||
add_objective(kill_objective)
|
||||
else
|
||||
if(prob(15) && !(locate(/datum/objective/download) in owner.objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
|
||||
if(prob(15) && !(locate(/datum/objective/download) in objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
|
||||
var/datum/objective/download/download_objective = new
|
||||
download_objective.owner = owner
|
||||
download_objective.gen_amount_goal()
|
||||
|
||||
@@ -208,7 +208,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
var/unlock_text = "<span class='notice'>Hello World!</span>" //Text shown when an ability is unlocked
|
||||
var/unlock_sound //Sound played when an ability is unlocked
|
||||
|
||||
/datum/AI_Module/proc/upgrade(mob/living/silicon/AI/AI) //Apply upgrades!
|
||||
/datum/AI_Module/proc/upgrade(mob/living/silicon/ai/AI) //Apply upgrades!
|
||||
return
|
||||
|
||||
/datum/AI_Module/large //Big, powerful stuff that can only be used once.
|
||||
@@ -304,7 +304,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
sleep(30)
|
||||
if(!owner || QDELETED(owner))
|
||||
return
|
||||
priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", 'sound/ai/aimalf.ogg')
|
||||
priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", "aimalf")
|
||||
set_security_level("delta")
|
||||
var/obj/machinery/doomsday_device/DOOM = new(owner_AI)
|
||||
owner_AI.nuking = TRUE
|
||||
@@ -397,7 +397,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
unlock_text = "<span class='notice'>You establish a power diversion to your turrets, upgrading their health and damage.</span>"
|
||||
unlock_sound = 'sound/items/rped.ogg'
|
||||
|
||||
/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/AI/AI)
|
||||
/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/ai/AI)
|
||||
for(var/obj/machinery/porta_turret/ai/turret in GLOB.machines)
|
||||
turret.obj_integrity += 30
|
||||
turret.lethal_projectile = /obj/item/projectile/beam/laser/heavylaser //Once you see it, you will know what it means to FEAR.
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
var/datum/objective/martyr/normiesgetout = new
|
||||
normiesgetout.owner = owner
|
||||
objectives += normiesgetout
|
||||
owner.objectives += objectives
|
||||
|
||||
/datum/antagonist/heartbreaker/on_gain()
|
||||
forge_objectives()
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
protect_objective.human_check = FALSE
|
||||
protect_objective.explanation_text = "Protect [date.name], your date."
|
||||
objectives += protect_objective
|
||||
owner.objectives += objectives
|
||||
|
||||
/datum/antagonist/valentine/on_gain()
|
||||
forge_objectives()
|
||||
@@ -34,8 +33,8 @@
|
||||
//Squashed up a bit
|
||||
/datum/antagonist/valentine/roundend_report()
|
||||
var/objectives_complete = TRUE
|
||||
if(owner.objectives.len)
|
||||
for(var/datum/objective/objective in owner.objectives)
|
||||
if(objectives.len)
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(!objective.check_completion())
|
||||
objectives_complete = FALSE
|
||||
break
|
||||
@@ -51,8 +50,8 @@
|
||||
|
||||
/datum/antagonist/valentine/chem/roundend_report()
|
||||
var/objectives_complete = TRUE
|
||||
if(owner.objectives.len)
|
||||
for(var/datum/objective/objective in owner.objectives)
|
||||
if(objectives.len)
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(!objective.check_completion())
|
||||
objectives_complete = FALSE
|
||||
break
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
var/datum/objective/hijack/hijack = new
|
||||
hijack.owner = owner
|
||||
objectives += hijack
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/wishgranter/on_gain()
|
||||
owner.special_role = "Avatar of the Wish Granter"
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
/obj/singularity/wizard/attack_tk(mob/user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
GET_COMPONENT_FROM(insaneinthemembrane, /datum/component/mood, C)
|
||||
var/datum/component/mood/insaneinthemembrane = C.GetComponent(/datum/component/mood)
|
||||
if(insaneinthemembrane.sanity < 15)
|
||||
return //they've already seen it and are about to die, or are just too insane to care
|
||||
to_chat(C, "<span class='userdanger'>OH GOD! NONE OF IT IS REAL! NONE OF IT IS REEEEEEEEEEEEEEEEEEEEEEEEAL!</span>")
|
||||
@@ -198,7 +198,7 @@
|
||||
to_chat(user, "<span class='warning'>This artifact can only affect three undead at a time!</span>")
|
||||
return
|
||||
|
||||
M.set_species(/datum/species/skeleton, icon_update=0)
|
||||
M.set_species(/datum/species/skeleton/space, icon_update=0)
|
||||
M.revive(full_heal = 1, admin_revive = 1)
|
||||
spooky_scaries |= M
|
||||
to_chat(M, "<span class='userdanger'>You have been revived by </span><B>[user.real_name]!</B>")
|
||||
@@ -255,7 +255,7 @@
|
||||
|
||||
/obj/item/voodoo/attackby(obj/item/I, mob/user, params)
|
||||
if(target && cooldown < world.time)
|
||||
if(I.is_hot())
|
||||
if(I.get_temperature())
|
||||
to_chat(target, "<span class='userdanger'>You suddenly feel very hot</span>")
|
||||
target.adjust_bodytemperature(50)
|
||||
GiveHint(target)
|
||||
@@ -324,14 +324,11 @@
|
||||
cooldown = world.time + cooldown_time
|
||||
|
||||
/obj/item/voodoo/proc/update_targets()
|
||||
possible = list()
|
||||
LAZYINITLIST(possible)
|
||||
if(!voodoo_link)
|
||||
return
|
||||
var/list/prints = voodoo_link.return_fingerprints()
|
||||
if(!length(prints))
|
||||
return FALSE
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
if(prints[md5(H.dna.uni_identity)])
|
||||
if(md5(H.dna.uni_identity) in voodoo_link.fingerprints)
|
||||
possible |= H
|
||||
|
||||
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)
|
||||
@@ -343,9 +340,9 @@
|
||||
to_chat(victim, "<span class='notice'>You feel a dark presence from [A.name]</span>")
|
||||
|
||||
/obj/item/voodoo/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message("<span class='suicide'>[user] links the voodoo doll to [user.p_them()]self and sits on it, infinitely crushing [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
user.gib()
|
||||
return(BRUTELOSS)
|
||||
user.visible_message("<span class='suicide'>[user] links the voodoo doll to [user.p_them()]self and sits on it, infinitely crushing [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
user.gib()
|
||||
return(BRUTELOSS)
|
||||
|
||||
/obj/item/voodoo/fire_act(exposed_temperature, exposed_volume)
|
||||
if(target)
|
||||
@@ -386,7 +383,9 @@
|
||||
if(!istype(user) || on_cooldown)
|
||||
return
|
||||
var/turf/T = get_turf(user)
|
||||
if(!T)
|
||||
var/area/A = get_area(user)
|
||||
if(!T || !A || A.noteleport)
|
||||
to_chat(user, "<span class='warning'>You play \the [src], yet no sound comes out of it... Looks like it won't work here.</span>")
|
||||
return
|
||||
on_cooldown = TRUE
|
||||
last_user = user
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
newstruct.master = stoner
|
||||
var/datum/action/innate/seek_master/SM = new()
|
||||
SM.Grant(newstruct)
|
||||
newstruct.key = target.key
|
||||
target.transfer_ckey(newstruct)
|
||||
var/obj/screen/alert/bloodsense/BS
|
||||
if(newstruct.mind && ((stoner && iscultist(stoner)) || cultoverride) && SSticker && SSticker.mode)
|
||||
SSticker.mode.add_cultist(newstruct.mind, 0)
|
||||
@@ -238,12 +238,13 @@
|
||||
T.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
T.invisibility = INVISIBILITY_ABSTRACT
|
||||
T.dust_animation()
|
||||
QDEL_IN(T, 5)
|
||||
var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade(src)
|
||||
S.status_flags |= GODMODE //So they won't die inside the stone somehow
|
||||
S.canmove = FALSE//Can't move out of the soul stone
|
||||
S.name = "Shade of [T.real_name]"
|
||||
S.real_name = "Shade of [T.real_name]"
|
||||
S.key = T.key
|
||||
T.transfer_ckey(S)
|
||||
S.language_holder = U.language_holder.copy(S)
|
||||
if(U)
|
||||
S.faction |= "[REF(U)]" //Add the master as a faction, allowing inter-mob cooperation
|
||||
|
||||
@@ -11,12 +11,18 @@
|
||||
var/buy_word = "Learn"
|
||||
var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook
|
||||
var/list/no_coexistance_typecache //Used so you can't have specific spells together
|
||||
var/dynamic_cost = 0 // How much threat the spell costs to purchase for dynamic.
|
||||
var/dynamic_requirement = 0 // How high the threat level needs to be for purchasing in dynamic.
|
||||
|
||||
/datum/spellbook_entry/New()
|
||||
..()
|
||||
no_coexistance_typecache = typecacheof(no_coexistance_typecache)
|
||||
|
||||
/datum/spellbook_entry/proc/IsAvailible() // For config prefs / gamemode restrictions - these are round applied
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(dynamic_requirement > 0 && mode.threat_level < dynamic_requirement)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/spellbook_entry/proc/CanBuy(mob/living/carbon/human/user,obj/item/spellbook/book) // Specific circumstances
|
||||
@@ -25,6 +31,10 @@
|
||||
for(var/spell in user.mind.spell_list)
|
||||
if(is_type_in_typecache(spell, no_coexistance_typecache))
|
||||
return 0
|
||||
if(dynamic_cost>0 && istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat < dynamic_cost)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/spellbook_entry/proc/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) //return 1 on success
|
||||
@@ -60,6 +70,10 @@
|
||||
SSblackbox.record_feedback("nested tally", "wizard_spell_improved", 1, list("[name]", "[aspell.spell_level]"))
|
||||
return 1
|
||||
//No same spell found - just learn it
|
||||
if(dynamic_cost > 0 && istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
mode.spend_threat(dynamic_cost)
|
||||
mode.log_threat("Wizard spent [dynamic_cost] on [name].")
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
user.mind.AddSpell(S)
|
||||
to_chat(user, "<span class='notice'>You have learned [S.name].</span>")
|
||||
@@ -83,6 +97,10 @@
|
||||
if(!S)
|
||||
S = new spell_type()
|
||||
var/spell_levels = 0
|
||||
if(dynamic_cost > 0 && istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
mode.refund_threat(dynamic_cost)
|
||||
mode.log_threat("Wizard refunded [dynamic_cost] on [name].")
|
||||
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
|
||||
if(initial(S.name) == initial(aspell.name))
|
||||
spell_levels = aspell.spell_level
|
||||
@@ -285,6 +303,8 @@
|
||||
name = "Staff of Change"
|
||||
desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself."
|
||||
item_path = /obj/item/gun/magic/staff/change
|
||||
dynamic_requirement = 60
|
||||
dynamic_cost = 20
|
||||
|
||||
/datum/spellbook_entry/item/staffanimation
|
||||
name = "Staff of Animation"
|
||||
@@ -369,6 +389,8 @@
|
||||
desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side."
|
||||
item_path = /obj/item/antag_spawner/contract
|
||||
category = "Assistance"
|
||||
dynamic_requirement = 50
|
||||
dynamic_cost = 10
|
||||
|
||||
/datum/spellbook_entry/item/guardian
|
||||
name = "Guardian Deck"
|
||||
@@ -388,6 +410,11 @@
|
||||
item_path = /obj/item/antag_spawner/slaughter_demon
|
||||
limit = 3
|
||||
category = "Assistance"
|
||||
dynamic_requirement = 60
|
||||
|
||||
/datum/spellbook_entry/item/bloodbottle/New()
|
||||
..()
|
||||
dynamic_cost = CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"]
|
||||
|
||||
/datum/spellbook_entry/item/hugbottle
|
||||
name = "Bottle of Tickles"
|
||||
@@ -402,6 +429,11 @@
|
||||
cost = 1 //non-destructive; it's just a jape, sibling!
|
||||
limit = 3
|
||||
category = "Assistance"
|
||||
dynamic_requirement = 40
|
||||
|
||||
/datum/spellbook_entry/item/hugbottle/New()
|
||||
..()
|
||||
dynamic_cost = CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"]/3
|
||||
|
||||
/datum/spellbook_entry/item/mjolnir
|
||||
name = "Mjolnir"
|
||||
@@ -465,7 +497,7 @@
|
||||
if(!SSticker.mode)
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
@@ -478,11 +510,13 @@
|
||||
/datum/spellbook_entry/summon/guns
|
||||
name = "Summon Guns"
|
||||
desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. Just be careful not to stand still too long!"
|
||||
dynamic_cost = 10
|
||||
dynamic_requirement = 60
|
||||
|
||||
/datum/spellbook_entry/summon/guns/IsAvailible()
|
||||
if(!SSticker.mode) // In case spellbook is placed on map
|
||||
return 0
|
||||
return !CONFIG_GET(flag/no_summon_guns)
|
||||
return (!CONFIG_GET(flag/no_summon_guns) && ..())
|
||||
|
||||
/datum/spellbook_entry/summon/guns/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
@@ -490,16 +524,23 @@
|
||||
active = 1
|
||||
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You have cast summon guns!</span>")
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
var/threat_spent = dynamic_cost
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Wizard spent [threat_spent] on summon guns.")
|
||||
return 1
|
||||
|
||||
/datum/spellbook_entry/summon/magic
|
||||
name = "Summon Magic"
|
||||
desc = "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time."
|
||||
dynamic_cost = 10
|
||||
dynamic_requirement = 60
|
||||
|
||||
/datum/spellbook_entry/summon/magic/IsAvailible()
|
||||
if(!SSticker.mode) // In case spellbook is placed on map
|
||||
return 0
|
||||
return !CONFIG_GET(flag/no_summon_magic)
|
||||
return (!CONFIG_GET(flag/no_summon_guns) && ..())
|
||||
|
||||
/datum/spellbook_entry/summon/magic/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
@@ -507,21 +548,33 @@
|
||||
active = 1
|
||||
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You have cast summon magic!</span>")
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
var/threat_spent = dynamic_cost
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Wizard spent [threat_spent] on summon magic.")
|
||||
return 1
|
||||
|
||||
/datum/spellbook_entry/summon/events
|
||||
name = "Summon Events"
|
||||
desc = "Give Murphy's law a little push and replace all events with special wizard ones that will confound and confuse everyone. Multiple castings increase the rate of these events."
|
||||
dynamic_cost = 20
|
||||
dynamic_requirement = 60
|
||||
var/times = 0
|
||||
|
||||
/datum/spellbook_entry/summon/events/IsAvailible()
|
||||
if(!SSticker.mode) // In case spellbook is placed on map
|
||||
return 0
|
||||
return !CONFIG_GET(flag/no_summon_events)
|
||||
return (!CONFIG_GET(flag/no_summon_events) && ..())
|
||||
|
||||
/datum/spellbook_entry/summon/events/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
summonevents()
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic) && times == 0)
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
var/threat_spent = dynamic_cost
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Wizard spent [threat_spent] on summon events.")
|
||||
times++
|
||||
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You have cast summon events.</span>")
|
||||
@@ -626,16 +679,16 @@
|
||||
dat += {"
|
||||
<head>
|
||||
<style type="text/css">
|
||||
body { font-size: 80%; font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif; }
|
||||
ul#tabs { list-style-type: none; margin: 30px 0 0 0; padding: 0 0 0.3em 0; }
|
||||
ul#tabs li { display: inline; }
|
||||
ul#tabs li a { color: #42454a; background-color: #dedbde; border: 1px solid #c9c3ba; border-bottom: none; padding: 0.3em; text-decoration: none; }
|
||||
ul#tabs li a:hover { background-color: #f1f0ee; }
|
||||
ul#tabs li a.selected { color: #000; background-color: #f1f0ee; font-weight: bold; padding: 0.7em 0.3em 0.38em 0.3em; }
|
||||
div.tabContent { border: 1px solid #c9c3ba; padding: 0.5em; background-color: #f1f0ee; }
|
||||
div.tabContent.hide { display: none; }
|
||||
</style>
|
||||
</head>
|
||||
body { font-size: 80%; font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif; }
|
||||
ul#tabs { list-style-type: none; margin: 30px 0 0 0; padding: 0 0 0.3em 0; }
|
||||
ul#tabs li { display: inline; }
|
||||
ul#tabs li a { color: #42454a; background-color: #dedbde; border: 1px solid #c9c3ba; border-bottom: none; padding: 0.3em; text-decoration: none; }
|
||||
ul#tabs li a:hover { background-color: #f1f0ee; }
|
||||
ul#tabs li a.selected { color: #000; background-color: #f1f0ee; font-weight: bold; padding: 0.7em 0.3em 0.38em 0.3em; }
|
||||
div.tabContent { border: 1px solid #c9c3ba; padding: 0.5em; background-color: #f1f0ee; }
|
||||
div.tabContent.hide { display: none; }
|
||||
</style>
|
||||
</head>
|
||||
"}
|
||||
dat += {"[content]</body></html>"}
|
||||
return dat
|
||||
|
||||
@@ -57,19 +57,19 @@
|
||||
if(!GLOB.wizardstart.len)
|
||||
SSjob.SendToLateJoin(owner.current)
|
||||
to_chat(owner, "HOT INSERTION, GO GO GO")
|
||||
owner.current.forceMove(pick(GLOB.wizardstart))
|
||||
else
|
||||
owner.current.forceMove(pick(GLOB.wizardstart))
|
||||
|
||||
/datum/antagonist/wizard/proc/create_objectives()
|
||||
var/datum/objective/new_objective = new("Cause as much creative mayhem as you can aboard the station! The more outlandish your methods of achieving this, the better! Make sure there's a decent amount of crew alive to tell of your tale.")
|
||||
new_objective.completed = TRUE //So they can greentext without admin intervention.
|
||||
new_objective.owner = owner
|
||||
objectives += new_objective
|
||||
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
objectives += escape_objective
|
||||
|
||||
for(var/datum/objective/O in objectives)
|
||||
owner.objectives += O
|
||||
if (!(locate(/datum/objective/escape) in objectives))
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
objectives += escape_objective
|
||||
|
||||
/datum/antagonist/wizard/on_removal()
|
||||
unregister()
|
||||
@@ -165,7 +165,7 @@
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/aimed/fireball(null))
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned powerful, destructive spells. You are able to cast magic missile and fireball.")
|
||||
if(APPRENTICE_BLUESPACE)
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null))
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned reality bending mobility spells. You are able to cast teleport and ethereal jaunt.")
|
||||
if(APPRENTICE_HEALING)
|
||||
@@ -183,7 +183,6 @@
|
||||
new_objective.owner = owner
|
||||
new_objective.target = master
|
||||
new_objective.explanation_text = "Protect [master.current.real_name], the wizard."
|
||||
owner.objectives += new_objective
|
||||
objectives += new_objective
|
||||
|
||||
//Random event wizard
|
||||
@@ -245,13 +244,12 @@
|
||||
if(!istype(M))
|
||||
return
|
||||
|
||||
var/obj/item/implant/exile/Implant = new/obj/item/implant/exile(M)
|
||||
var/obj/item/implant/exile/Implant = new
|
||||
Implant.implant(M)
|
||||
|
||||
/datum/antagonist/wizard/academy/create_objectives()
|
||||
var/datum/objective/new_objective = new("Protect Wizard Academy from the intruders")
|
||||
new_objective.owner = owner
|
||||
owner.objectives += new_objective
|
||||
objectives += new_objective
|
||||
|
||||
//Solo wizard report
|
||||
|
||||
Reference in New Issue
Block a user