Merge branch 'master' into QM-as-Head

This commit is contained in:
Chayse Ramsay
2018-02-16 13:09:58 +00:00
committed by GitHub
794 changed files with 66974 additions and 68251 deletions
+18 -3
View File
@@ -8,11 +8,18 @@ GLOBAL_PROTECT(admin_ranks)
var/list/subs
/datum/admin_rank/New(init_name, init_rights, list/init_adds, list/init_subs)
if(IsAdminAdvancedProcCall())
var/msg = " has tried to elevate permissions!"
message_admins("[key_name_admin(usr)][msg]")
log_admin("[key_name(usr)][msg]")
if (name == "NoRank") //only del if this is a true creation (and not just a New() proc call), other wise trialmins/coders could abuse this to deadmin other admins
QDEL_IN(src, 0)
CRASH("Admin proc call creation of admin datum")
return
name = init_name
switch(name)
if("Removed",null,"")
spawn(0)
qdel(src)
QDEL_IN(src, 0)
throw EXCEPTION("invalid admin-rank name")
return
if(init_rights)
@@ -24,6 +31,14 @@ GLOBAL_PROTECT(admin_ranks)
adds = init_adds
subs = init_subs
/datum/admin_rank/Destroy()
if(IsAdminAdvancedProcCall())
var/msg = " has tried to elevate permissions!"
message_admins("[key_name_admin(usr)][msg]")
log_admin("[key_name(usr)][msg]")
return QDEL_HINT_LETMELIVE
. = ..()
/datum/admin_rank/vv_edit_var(var_name, var_value)
return FALSE
@@ -78,7 +93,7 @@ GLOBAL_PROTECT(admin_ranks)
if(IsAdminAdvancedProcCall())
var/msg = " has tried to elevate permissions!"
message_admins("[key_name_admin(usr)][msg]")
log_admin_private("[key_name(usr)][msg]")
log_admin("[key_name(usr)][msg]")
return
var/flag = admin_keyword_to_flag(word, previous_rights)
if(flag)
-1
View File
@@ -75,7 +75,6 @@ GLOBAL_LIST(round_end_notifiees)
/datum/server_tools_command/notify
name = "notify"
help_text = "Pings the invoker when the round ends"
admin_only = TRUE
/datum/server_tools_command/notify/Run(sender, params)
if(!SSticker.IsRoundInProgress() && SSticker.HasRoundStarted())
+33 -3
View File
@@ -27,6 +27,14 @@ GLOBAL_PROTECT(href_token)
var/deadmined
/datum/admins/New(datum/admin_rank/R, ckey, force_active = FALSE)
if(IsAdminAdvancedProcCall())
var/msg = " has tried to elevate permissions!"
message_admins("[key_name_admin(usr)][msg]")
log_admin("[key_name(usr)][msg]")
if (!target) //only del if this is a true creation (and not just a New() proc call), other wise trialmins/coders could abuse this to deadmin other admins
QDEL_IN(src, 0)
CRASH("Admin proc call creation of admin datum")
return
if(!ckey)
QDEL_IN(src, 0)
throw EXCEPTION("Admin datum created without a ckey")
@@ -48,8 +56,20 @@ GLOBAL_PROTECT(href_token)
else
deactivate()
/datum/admins/Destroy()
if(IsAdminAdvancedProcCall())
var/msg = " has tried to elevate permissions!"
message_admins("[key_name_admin(usr)][msg]")
log_admin("[key_name(usr)][msg]")
return QDEL_HINT_LETMELIVE
. = ..()
/datum/admins/proc/activate()
if(IsAdminAdvancedProcCall())
var/msg = " has tried to elevate permissions!"
message_admins("[key_name_admin(usr)][msg]")
log_admin("[key_name(usr)][msg]")
return
GLOB.deadmins -= target
GLOB.admin_datums[target] = src
deadmined = FALSE
@@ -58,6 +78,11 @@ GLOBAL_PROTECT(href_token)
/datum/admins/proc/deactivate()
if(IsAdminAdvancedProcCall())
var/msg = " has tried to elevate permissions!"
message_admins("[key_name_admin(usr)][msg]")
log_admin("[key_name(usr)][msg]")
return
GLOB.deadmins[target] = src
GLOB.admin_datums -= target
deadmined = TRUE
@@ -70,14 +95,14 @@ GLOBAL_PROTECT(href_token)
if(IsAdminAdvancedProcCall())
var/msg = " has tried to elevate permissions!"
message_admins("[key_name_admin(usr)][msg]")
log_admin_private("[key_name(usr)][msg]")
log_admin("[key_name(usr)][msg]")
return
if(istype(C))
if(C.ckey != target)
var/msg = " has attempted to associate with [target]'s admin datum"
message_admins("[key_name_admin(C)][msg]")
log_admin_private("[key_name(C)][msg]")
log_admin("[key_name(C)][msg]")
return
if (deadmined)
activate()
@@ -88,6 +113,11 @@ GLOBAL_PROTECT(href_token)
GLOB.admins |= C
/datum/admins/proc/disassociate()
if(IsAdminAdvancedProcCall())
var/msg = " has tried to elevate permissions!"
message_admins("[key_name_admin(usr)][msg]")
log_admin("[key_name(usr)][msg]")
return
if(owner)
GLOB.admins -= owner
owner.remove_admin_verbs()
@@ -173,4 +203,4 @@ you will have to do something like if(client.rights & R_ADMIN) yourself.
return "admin_token=[RawHrefToken(forceGlobal)]"
/proc/HrefTokenFormField(forceGlobal = FALSE)
return "<input type='hidden' name='admin_token' value='[RawHrefToken(forceGlobal)]'>"
return "<input type='hidden' name='admin_token' value='[RawHrefToken(forceGlobal)]'>"
+1 -53
View File
@@ -26,56 +26,4 @@ GLOBAL_VAR_INIT(highlander, FALSE)
addtimer(CALLBACK(src, .proc/only_one), 420)
/mob/living/carbon/human/proc/make_scottish()
mind.special_role = "highlander"
dna.species.species_traits |= NOGUNS //nice try jackass
var/datum/objective/steal/steal_objective = new
steal_objective.owner = mind
steal_objective.set_target(new /datum/objective_item/steal/nukedisc)
mind.objectives += steal_objective
var/datum/objective/hijack/hijack_objective = new
hijack_objective.explanation_text = "Escape on the shuttle alone. Ensure that nobody else makes it out."
hijack_objective.owner = mind
mind.objectives += hijack_objective
mind.add_antag_datum(/datum/antagonist/auto_custom)
mind.announce_objectives()
for(var/obj/item/I in get_equipped_items())
qdel(I)
for(var/obj/item/I in held_items)
qdel(I)
equip_to_slot_or_del(new /obj/item/clothing/under/kilt/highlander(src), slot_w_uniform)
equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(src), slot_ears)
equip_to_slot_or_del(new /obj/item/clothing/head/beret/highlander(src), slot_head)
equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(src), slot_shoes)
equip_to_slot_or_del(new /obj/item/pinpointer/nuke(src), slot_l_store)
for(var/obj/item/pinpointer/nuke/P in src)
P.attack_self(src)
var/obj/item/card/id/W = new(src)
W.icon_state = "centcom"
W.access = get_all_accesses()
W.access += get_all_centcom_access()
W.assignment = "Highlander"
W.registered_name = real_name
W.flags_1 |= NODROP_1
W.update_label(real_name)
equip_to_slot_or_del(W, slot_wear_id)
var/obj/item/claymore/highlander/H1 = new(src)
if(!GLOB.highlander)
H1.admin_spawned = TRUE //To prevent announcing
put_in_hands(H1)
H1.pickup(src) //For the stun shielding
var/obj/item/bloodcrawl/antiwelder = new(src)
antiwelder.name = "compulsion of honor"
antiwelder.desc = "You are unable to hold anything in this hand until you're the last one left!"
antiwelder.icon_state = "bloodhand_right"
put_in_hands(antiwelder)
to_chat(src, "<span class='boldannounce'>Your [H1.name] cries out for blood. Claim the lives of others, and your own will be restored!\n\
Activate it in your hand, and it will lead to the nearest target. Attack the nuclear authentication disk with it, and you will store it.</span>")
mind.add_antag_datum(/datum/antagonist/highlander)
@@ -73,19 +73,18 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/is_banned(mob/M)
if(!M)
return FALSE
. = (jobban_isbanned(M,"Syndicate") || (job_rank && jobban_isbanned(M,job_rank)))
. = (jobban_isbanned(M, ROLE_SYNDICATE) || (job_rank && jobban_isbanned(M,job_rank)))
/datum/antagonist/proc/replace_banned_player()
set waitfor = FALSE
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [name]?", "[name]", null, job_rank, 50, owner.current)
var/mob/dead/observer/theghost = null
if(candidates.len)
theghost = pick(candidates)
if(LAZYLEN(candidates))
var/client/C = pick(candidates)
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(theghost)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
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 = theghost.key
owner.current.key = C.key
/datum/antagonist/proc/on_removal()
remove_innate_effects()
@@ -2,7 +2,7 @@
throw_speed = 1
throw_range = 5
w_class = WEIGHT_CLASS_TINY
var/used = 0
var/used = FALSE
/obj/item/antag_spawner/proc/spawn_antag(client/C, turf/T, kind = "", datum/mind/user)
return
@@ -57,13 +57,13 @@
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)
if(candidates.len)
if(LAZYLEN(candidates))
if(used)
to_chat(H, "You already used this contract!")
return
used = 1
var/mob/dead/observer/theghost = pick(candidates)
spawn_antag(theghost.client, get_turf(src), href_list["school"],H.mind)
used = TRUE
var/client/C = pick(candidates)
spawn_antag(C, get_turf(src), href_list["school"],H.mind)
else
to_chat(H, "Unable to reach your apprentice! You can either attack the spellbook with the contract to refund your points, or wait and try again later.")
@@ -120,12 +120,12 @@
to_chat(user, "<span class='notice'>You activate [src] and wait for confirmation.</span>")
var/list/nuke_candidates = pollGhostCandidates("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150, POLL_IGNORE_SYNDICATE)
if(nuke_candidates.len)
if(LAZYLEN(nuke_candidates))
if(!(check_usability(user)))
return
used = TRUE
var/mob/dead/observer/theghost = pick(nuke_candidates)
spawn_antag(theghost.client, get_turf(src), "syndieborg", user.mind)
var/client/C = pick(nuke_candidates)
spawn_antag(C, get_turf(src), "syndieborg", user.mind)
do_sparks(4, TRUE, src)
qdel(src)
else
@@ -213,13 +213,13 @@
return
if(used)
return
var/list/demon_candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", null, null, ROLE_ALIEN, 50, src)
if(demon_candidates.len)
var/list/candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, src)
if(LAZYLEN(candidates))
if(used)
return
used = 1
var/mob/dead/observer/theghost = pick(demon_candidates)
spawn_antag(theghost.client, get_turf(src), initial(demon_type.name),user.mind)
used = TRUE
var/client/C = pick(candidates)
spawn_antag(C, get_turf(src), initial(demon_type.name),user.mind)
to_chat(user, shatter_msg)
to_chat(user, veil_msg)
playsound(user.loc, 'sound/effects/glassbr1.ogg', 100, 1)
@@ -682,8 +682,8 @@ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/structure/table_frame/abductor/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wrench))
to_chat(user, "<span class='notice'>You start disassembling [src]...</span>")
playsound(src.loc, I.usesound, 50, 1)
if(do_after(user, 30*I.toolspeed, target = src))
I.play_tool_sound(src)
if(I.use_tool(src, user, 30))
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
for(var/i = 1, i <= framestackamount, i++)
new framestack(get_turf(src))
@@ -262,10 +262,9 @@
mind_control_duration = 1800
/obj/item/organ/heart/gland/egg/activate()
to_chat(owner, "<span class='boldannounce'>You lay an egg!</span>")
var/obj/item/reagent_containers/food/snacks/egg/egg = new(owner.drop_location())
egg.reagents.add_reagent(get_random_reagent_id(), 15)
egg.desc += " It looks weird..."
owner.visible_message("<span class='alertalien'>[owner] [pick(EGG_LAYING_MESSAGES)]</span>")
var/turf/T = owner.drop_location()
new /obj/item/reagent_containers/food/snacks/egg/gland(T)
/obj/item/organ/heart/gland/electric
cooldown_low = 800
@@ -148,7 +148,7 @@
// Attach the smoke spreader and setup/start it.
S.attach(location)
S.set_up(reagents, death_cloud_size, location, silent=1)
S.set_up(reagents, death_cloud_size, location, silent = TRUE)
S.start()
if(factory)
factory.spore_delay = world.time + factory.spore_cooldown //put the factory on cooldown
+1 -1
View File
@@ -2,7 +2,7 @@
name = "Brother"
antagpanel_category = "Brother"
job_rank = ROLE_BROTHER
var/special_role = "blood brother"
var/special_role = ROLE_BROTHER
var/datum/team/brother_team/team
/datum/antagonist/brother/create_team(datum/team/brother_team/new_team)
@@ -76,6 +76,13 @@
. = ..()
/datum/antagonist/changeling/on_removal()
//We'll be using this from now on
var/mob/living/carbon/C = owner.current
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.decoy_override = FALSE
remove_changeling_powers()
owner.objectives -= objectives
. = ..()
@@ -389,7 +396,7 @@
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
if(team_mode) //No backstabbing while in a team
kill_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
kill_objective.find_target_by_role(role = ROLE_CHANGELING, role_type = 1, invert = 1)
else
kill_objective.find_target()
objectives += kill_objective
@@ -397,7 +404,7 @@
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = owner
if(team_mode)
maroon_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
maroon_objective.find_target_by_role(role = ROLE_CHANGELING, role_type = 1, invert = 1)
else
maroon_objective.find_target()
objectives += maroon_objective
@@ -419,7 +426,7 @@
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = owner
if(team_mode)
identity_theft.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
identity_theft.find_target_by_role(role = ROLE_CHANGELING, role_type = 1, invert = 1)
else
identity_theft.find_target()
objectives += identity_theft
@@ -16,7 +16,7 @@
for(var/obj/item/organ/I in organs)
I.Remove(user, 1)
explosion(get_turf(user),0,0,2,0,silent=1)
explosion(get_turf(user), 0, 0, 2, 0, TRUE)
for(var/mob/living/carbon/human/H in range(2,user))
to_chat(H, "<span class='userdanger'>You are blinded by a shower of blood!</span>")
H.Stun(20)
@@ -352,12 +352,12 @@
if(INTENT_GRAB)
C.visible_message("<span class='danger'>[L] is grabbed by [H]'s tentacle!</span>","<span class='userdanger'>A tentacle grabs you and pulls you towards [H]!</span>")
C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(src, .proc/tentacle_grab, H, C))
C.throw_at(get_step_towards(H,C), 8, 2, H, TRUE, TRUE, callback=CALLBACK(src, .proc/tentacle_grab, H, C))
return 1
if(INTENT_HARM)
C.visible_message("<span class='danger'>[L] is thrown towards [H] by a tentacle!</span>","<span class='userdanger'>A tentacle grabs you and throws you towards [H]!</span>")
C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(src, .proc/tentacle_stab, H, C))
C.throw_at(get_step_towards(H,C), 8, 2, H, TRUE, TRUE, callback=CALLBACK(src, .proc/tentacle_stab, H, C))
return 1
else
L.visible_message("<span class='danger'>[L] is pulled by [H]'s tentacle!</span>","<span class='userdanger'>A tentacle grabs you and pulls you towards [H]!</span>")
@@ -160,7 +160,7 @@
access_display(user)
/obj/item/clockwork/slab/AltClick(mob/living/user)
if(is_servant_of_ratvar(user) && linking)
if(is_servant_of_ratvar(user) && linking && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
linking = null
to_chat(user, "<span class='notice'>Object link canceled.</span>")
@@ -34,4 +34,4 @@
else
adjust_clockwork_power(1) //Continue generating power when the cell has run dry; 5 W/second
#undef COG_MAX_SIPHON_THRESHOLD
#undef COG_MAX_SIPHON_THRESHOLD
@@ -27,11 +27,11 @@
var/distance = get_dist(src, O)
to_chat(user, "[O] ([distance == 0 ? "same tile" : "[distance] tiles [dir2text(get_dir(src, O))]"])")
/obj/structure/destructible/clockwork/trap/wrench_act(mob/living/user, obj/item/wrench)
/obj/structure/destructible/clockwork/trap/wrench_act(mob/living/user, obj/item/I)
if(!is_servant_of_ratvar(user))
return ..()
to_chat(user, "<span class='notice'>You break down the delicate components of [src] into brass.</span>")
playsound(src, wrench.usesound, 50, TRUE)
I.play_tool_sound(src)
new/obj/item/stack/tile/brass(get_turf(src))
qdel(src)
return TRUE
@@ -56,14 +56,14 @@
return
..()
/obj/structure/destructible/clockwork/trap/wirecutter_act(mob/living/user, obj/item/wirecutters)
/obj/structure/destructible/clockwork/trap/wirecutter_act(mob/living/user, obj/item/I)
if(!is_servant_of_ratvar(user))
return
if(!wired_to.len)
to_chat(user, "<span class='warning'>[src] has no connections!</span>")
return
to_chat(user, "<span class='notice'>You sever all connections to [src].</span>")
playsound(src, wirecutters.usesound, 50, TRUE)
I.play_tool_sound(src)
for(var/V in wired_to)
var/obj/structure/destructible/clockwork/trap/T = V
T.wired_to -= src
@@ -100,12 +100,8 @@
R.time *= 2 //Building walls becomes slower when the Ark activates
mass_recall()
recalls_remaining++ //So it doesn't use up a charge
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/open_portal(turf/T)
new/obj/effect/clockwork/city_of_cogs_rift(T)
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/spawn_animation()
var/turf/T = get_turf(src)
var/turf/T = get_turf(src)
var/list/open_turfs = list()
for(var/turf/open/OT in orange(1, T))
if(!is_blocked_turf(OT, TRUE))
@@ -113,6 +109,11 @@
if(open_turfs.len)
for(var/mob/living/L in T)
L.forceMove(pick(open_turfs))
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/open_portal(turf/T)
new/obj/effect/clockwork/city_of_cogs_rift(T)
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/spawn_animation()
hierophant_message("<span class='bold large_brass'>The Ark has activated! [grace_period ? "You have [round(grace_period / 60)] minutes until the crew invades! " : ""]Defend it at all costs!</span>", FALSE, src)
sound_to_playing_players(volume = 10, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_charging.ogg', TRUE))
seconds_until_activation = 0
@@ -130,7 +131,10 @@
if(!M || !M.current)
continue
if(isliving(M.current) && M.current.stat != DEAD)
M.current.forceMove(get_turf(src))
if(isAI(M.current))
M.current.forceMove(get_step(get_step(src, NORTH),NORTH)) // AI too fat, must make sure it always ends up a 2 tiles north instead of on the ark.
else
M.current.forceMove(get_turf(src))
M.current.overlay_fullscreen("flash", /obj/screen/fullscreen/flash)
M.current.clear_fullscreen("flash", 5)
playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 50, FALSE)
@@ -31,9 +31,8 @@
if(anchored)
to_chat(user, "<span class='warning'>[src] needs to be unsecured to disassemble it!</span>")
else
playsound(src, I.usesound, 100, 1)
user.visible_message("<span class='warning'>[user] starts to disassemble [src].</span>", "<span class='notice'>You start to disassemble [src]...</span>")
if(do_after(user, 30*I.toolspeed, target = src) && !anchored)
if(I.use_tool(src, user, 30, volume=100) && !anchored)
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
deconstruct(TRUE)
return 1
@@ -51,7 +51,7 @@
var/mob/living/current = owner.current
SSticker.mode.servants_of_ratvar += owner
SSticker.mode.update_servant_icons_added(owner)
owner.special_role = "Servant of Ratvar"
owner.special_role = ROLE_SERVANT_OF_RATVAR
owner.current.log_message("<font color=#BE8700>Has been converted to the cult of Ratvar!</font>", INDIVIDUAL_ATTACK_LOG)
if(issilicon(current))
if(iscyborg(current) && !silent)
@@ -0,0 +1,775 @@
/datum/action/innate/cult/blood_magic //Blood magic handles the creation of blood spells (formerly talismans)
name = "Prepare Blood Magic"
button_icon_state = "carve"
desc = "Prepare blood magic by carving runes into your flesh. This rite is most effective with an <b>empowering rune</b>"
var/list/spells = list()
var/channeling = FALSE
/datum/action/innate/cult/blood_magic/Grant()
..()
button.screen_loc = "6:-29,4:-2"
button.moved = "6:-29,4:-2"
/datum/action/innate/cult/blood_magic/Remove()
for(var/X in spells)
qdel(X)
..()
/datum/action/innate/cult/blood_magic/IsAvailable()
if(!iscultist(owner))
return FALSE
return ..()
/datum/action/innate/cult/blood_magic/proc/Positioning()
var/list/screen_loc_split = splittext(button.screen_loc,",")
var/list/screen_loc_X = splittext(screen_loc_split[1],":")
var/list/screen_loc_Y = splittext(screen_loc_split[2],":")
var/pix_X = text2num(screen_loc_X[2])
for(var/datum/action/innate/cult/blood_spell/B in spells)
if(B.button.locked)
var/order = pix_X+spells.Find(B)*31
B.button.screen_loc = "[screen_loc_X[1]]:[order],[screen_loc_Y[1]]:[screen_loc_Y[2]]"
B.button.moved = B.button.screen_loc
/datum/action/innate/cult/blood_magic/Activate()
var/rune = FALSE
var/limit = RUNELESS_MAX_BLOODCHARGE
for(var/obj/effect/rune/empower/R in range(1, owner))
rune = TRUE
break
if(rune)
limit = MAX_BLOODCHARGE
if(spells.len >= limit)
if(rune)
to_chat(owner, "<span class='cultitalic'>Your body has reached its limit, you cannot store more than [MAX_BLOODCHARGE] spells at once. <b>Pick a spell to nullify.</b></span>")
else
to_chat(owner, "<span class='cultitalic'>Your body has reached its limit, <b><u>you cannot have more than [RUNELESS_MAX_BLOODCHARGE] spells at once without an empowering rune! Pick a spell to nullify.</b></u></span>")
var/nullify_spell = input(owner, "Choose a spell to remove.", "Current Spells") as null|anything in spells
if(nullify_spell)
qdel(nullify_spell)
return
var/entered_spell_name
var/datum/action/innate/cult/blood_spell/BS
var/list/possible_spells = list()
for(var/I in subtypesof(/datum/action/innate/cult/blood_spell))
var/datum/action/innate/cult/blood_spell/J = I
var/cult_name = initial(J.name)
possible_spells[cult_name] = J
possible_spells += "(REMOVE SPELL)"
entered_spell_name = input(owner, "Pick a blood spell to prepare...", "Spell Choices") as null|anything in possible_spells
if(entered_spell_name == "(REMOVE SPELL)")
var/nullify_spell = input(owner, "Choose a spell to remove.", "Current Spells") as null|anything in spells
if(nullify_spell)
qdel(nullify_spell)
return
BS = possible_spells[entered_spell_name]
if(QDELETED(src) || owner.incapacitated() || !BS)
return
to_chat(owner,"<span class='warning'>You begin to carve unnatural symbols into your flesh!</span>")
SEND_SOUND(owner, sound('sound/weapons/slice.ogg',0,1,10))
if(!channeling)
channeling = TRUE
else
to_chat(owner, "<span class='cultitalic'>You are already invoking blood magic!")
return
if(do_after(owner, 100 - rune*65, target = owner))
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
H.bleed(30 - rune*25)
var/datum/action/innate/cult/blood_spell/new_spell = new BS(owner)
new_spell.Grant(owner, src)
spells += new_spell
Positioning()
to_chat(owner, "<span class='warning'>Your wounds glows with power, you have prepared a [new_spell.name] invocation!</span>")
channeling = FALSE
/datum/action/innate/cult/blood_spell //The next generation of talismans
name = "Blood Magic"
button_icon_state = "telerune"
desc = "Fear the Old Blood."
var/charges = 1
var/magic_path = null
var/obj/item/melee/blood_magic/hand_magic
var/datum/action/innate/cult/blood_magic/all_magic
var/base_desc //To allow for updating tooltips
var/invocation
var/health_cost = 0
/datum/action/innate/cult/blood_spell/Grant(mob/living/owner, datum/action/innate/cult/blood_magic/BM)
if(health_cost)
desc += "<br>Deals <u>[health_cost] damage</u> to your arm per use."
base_desc = desc
desc += "<br><b><u>Has [charges] use\s remaining</u></b>."
all_magic = BM
..()
button.locked = TRUE
/datum/action/innate/cult/blood_spell/Remove()
if(all_magic)
all_magic.spells -= src
if(hand_magic)
qdel(hand_magic)
hand_magic = null
..()
/datum/action/innate/cult/blood_spell/IsAvailable()
if(!iscultist(owner) || owner.incapacitated() || !charges)
return FALSE
return ..()
/datum/action/innate/cult/blood_spell/Activate()
if(magic_path) //If this spell flows from the hand
if(!hand_magic)
hand_magic = new magic_path(owner, src)
if(!owner.put_in_hands(hand_magic))
qdel(hand_magic)
hand_magic = null
to_chat(owner, "<span class='warning'>You have no empty hand for invoking blood magic!</span>")
return
to_chat(owner, "<span class='notice'>Your old wounds glow again as you invoke the [name].</span>")
return
if(hand_magic)
qdel(hand_magic)
hand_magic = null
to_chat(owner, "<span class='warning'>You snuff out the spell with your hand, saving its power for another time.</span>")
//Cult Blood Spells
/datum/action/innate/cult/blood_spell/stun
name = "Stun"
desc = "A potent spell that will stun and mute victims upon contact."
button_icon_state = "hand"
magic_path = "/obj/item/melee/blood_magic/stun"
health_cost = 10
/datum/action/innate/cult/blood_spell/teleport
name = "Teleport"
desc = "A useful spell that teleport cultists to a chosen destination on contact."
button_icon_state = "tele"
magic_path = "/obj/item/melee/blood_magic/teleport"
health_cost = 7
/datum/action/innate/cult/blood_spell/emp
name = "Electromagnetic Pulse"
desc = "A large spell that immediately disables all electronics in the area."
button_icon_state = "emp"
health_cost = 10
invocation = "Ta'gh fara'qha fel d'amar det!"
/datum/action/innate/cult/blood_spell/emp/Activate()
owner.visible_message("<span class='warning'>[owner]'s hand flashes a bright blue!</span>", \
"<span class='cultitalic'>You speak the cursed words, emitting an EMP blast from your hand.</span>")
empulse(owner, 3, 6)
owner.whisper(invocation, language = /datum/language/common)
charges--
if(charges<=0)
qdel(src)
/datum/action/innate/cult/blood_spell/shackles
name = "Shadow Shackles"
desc = "A stealthy spell that will handcuff and temporarily silence your victim."
button_icon_state = "cuff"
charges = 4
magic_path = "/obj/item/melee/blood_magic/shackles"
/datum/action/innate/cult/blood_spell/construction
name = "Twisted Construction"
desc = "<u>A sinister spell used to convert:</u><br>Plasteel into runed metal<br>25 metal into a construct shell<br>Cyborgs directly into constructs<br>Cyborg shells into construct shells<br>Airlocks into runed airlocks (harm intent)"
button_icon_state = "transmute"
magic_path = "/obj/item/melee/blood_magic/construction"
/datum/action/innate/cult/blood_spell/equipment
name = "Summon Equipment"
desc = "A crucial spell that enables you to summon either a ritual dagger or combat gear including armored robes, the nar'sien bola, and an eldritch longsword."
button_icon_state = "equip"
magic_path = "/obj/item/melee/blood_magic/armor"
/datum/action/innate/cult/blood_spell/equipment/Activate()
var/choice = alert(owner,"Choose your equipment type",,"Combat Equipment","Ritual Dagger","Cancel")
if(choice == "Ritual Dagger")
var/turf/T = get_turf(owner)
owner.visible_message("<span class='warning'>[owner]'s hand glows red for a moment.</span>", \
"<span class='cultitalic'>Red light begins to shimmer and take form within your hand!</span>")
var/obj/O = new /obj/item/melee/cultblade/dagger(T)
if(owner.put_in_hands(O))
to_chat(owner, "<span class='warning'>A ritual dagger appears in your hand!</span>")
else
owner.visible_message("<span class='warning'>A ritual dagger appears at [owner]'s feet!</span>", \
"<span class='cultitalic'>A ritual dagger materializes at your feet.</span>")
SEND_SOUND(owner, sound('sound/effects/magic.ogg',0,1,25))
charges--
desc = base_desc
desc += "<br><b><u>Has [charges] use\s remaining</u></b>."
if(charges<=0)
qdel(src)
else if(choice == "Combat Equipment")
..()
/datum/action/innate/cult/blood_spell/horror
name = "Hallucinations"
desc = "A <u>ranged yet stealthy</u> spell that will break the mind of the victim with nightmarish hallucinations."
button_icon_state = "horror"
var/obj/effect/proc_holder/horror/PH
charges = 4
/datum/action/innate/cult/blood_spell/horror/New()
PH = new()
PH.attached_action = src
..()
/datum/action/innate/cult/blood_spell/horror/Destroy()
var/obj/effect/proc_holder/horror/destroy = PH
. = ..()
if(destroy && !QDELETED(destroy))
QDEL_NULL(destroy)
/datum/action/innate/cult/blood_spell/horror/Activate()
PH.toggle(owner) //the important bit
return TRUE
/obj/effect/proc_holder/horror
active = FALSE
ranged_mousepointer = 'icons/effects/cult_target.dmi'
var/datum/action/innate/cult/blood_spell/attached_action
/obj/effect/proc_holder/horror/Destroy()
var/datum/action/innate/cult/blood_spell/AA = attached_action
. = ..()
if(AA && !QDELETED(AA))
QDEL_NULL(AA)
/obj/effect/proc_holder/horror/proc/toggle(mob/user)
if(active)
remove_ranged_ability("<span class='cult'>You dispel the magic...</span>")
else
add_ranged_ability(user, "<span class='cult'>You prepare to horrify a target...</span>")
/obj/effect/proc_holder/horror/InterceptClickOn(mob/living/caller, params, atom/target)
if(..())
return
if(ranged_ability_user.incapacitated() || !iscultist(caller))
remove_ranged_ability()
return
var/turf/T = get_turf(ranged_ability_user)
if(!isturf(T))
return FALSE
if(target in view(7, get_turf(ranged_ability_user)))
if(!ishuman(target) || iscultist(target))
return
var/mob/living/carbon/human/H = target
H.hallucination = max(H.hallucination, 240)
SEND_SOUND(ranged_ability_user, sound('sound/effects/ghost.ogg',0,1,50))
var/image/C = image('icons/effects/cult_effects.dmi',H,"bloodsparkles", ABOVE_MOB_LAYER)
add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/cult, "cult_apoc", C, FALSE)
addtimer(CALLBACK(H,/atom/.proc/remove_alt_appearance,"cult_apoc",TRUE), 2400, TIMER_OVERRIDE|TIMER_UNIQUE)
to_chat(ranged_ability_user,"<span class='cult'><b>[H] has been cursed with living nightmares!</b></span>")
attached_action.charges--
attached_action.desc = attached_action.base_desc
attached_action.desc += "<br><b><u>Has [attached_action.charges] use\s remaining</u></b>."
attached_action.UpdateButtonIcon()
if(attached_action.charges <= 0)
remove_mousepointer(ranged_ability_user.client)
remove_ranged_ability("<span class='cult'>You have exhausted the spell's power!</span>")
qdel(src)
/datum/action/innate/cult/blood_spell/veiling
name = "Conceal Presence"
desc = "A multi-function spell that alternates between hiding and revealing nearby cult runes, structures, turf, and airlocks."
invocation = "Kla'atu barada nikt'o!"
button_icon_state = "gone"
charges = 10
var/revealing = FALSE //if it reveals or not
/datum/action/innate/cult/blood_spell/veiling/Activate()
if(!revealing)
owner.visible_message("<span class='warning'>Thin grey dust falls from [owner]'s hand!</span>", \
"<span class='cultitalic'>You invoke the veiling spell, hiding nearby runes.</span>")
charges--
SEND_SOUND(owner, sound('sound/magic/smoke.ogg',0,1,25))
owner.whisper(invocation, language = /datum/language/common)
for(var/obj/effect/rune/R in range(5,owner))
R.conceal()
for(var/obj/structure/destructible/cult/S in range(5,owner))
S.conceal()
for(var/turf/open/floor/engine/cult/T in range(5,owner))
T.realappearance.alpha = 0
for(var/obj/machinery/door/airlock/cult/AL in range(5, owner))
AL.conceal()
revealing = TRUE
name = "Reveal Runes"
button_icon_state = "back"
else
owner.visible_message("<span class='warning'>A flash of light shines from [owner]'s hand!</span>", \
"<span class='cultitalic'>You invoke the counterspell, revealing nearby runes.</span>")
charges--
owner.whisper(invocation, language = /datum/language/common)
SEND_SOUND(owner, sound('sound/magic/enter_blood.ogg',0,1,25))
for(var/obj/effect/rune/R in range(7,owner)) //More range in case you weren't standing in exactly the same spot
R.reveal()
for(var/obj/structure/destructible/cult/S in range(6,owner))
S.reveal()
for(var/turf/open/floor/engine/cult/T in range(6,owner))
T.realappearance.alpha = initial(T.realappearance.alpha)
for(var/obj/machinery/door/airlock/cult/AL in range(6, owner))
AL.reveal()
revealing = FALSE
name = "Conceal Runes"
button_icon_state = "gone"
if(charges<= 0)
qdel(src)
desc = base_desc
desc += "<br><b><u>Has [charges] use\s remaining</u></b>."
UpdateButtonIcon()
/datum/action/innate/cult/blood_spell/manipulation
name = "Blood Rites"
desc = "A complex spell that allows you to gather blood and use it for healing or other powerful spells."
invocation = "Fel'th Dol Ab'orod!"
button_icon_state = "manip"
charges = 5
magic_path = "/obj/item/melee/blood_magic/manipulator"
// The "magic hand" items
/obj/item/melee/blood_magic
name = "\improper magical aura"
desc = "Sinister looking aura that distorts the flow of reality around it."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "disintegrate"
item_state = null
flags_1 = ABSTRACT_1 | NODROP_1 | DROPDEL_1
w_class = WEIGHT_CLASS_HUGE
throwforce = 0
throw_range = 0
throw_speed = 0
var/invocation
var/uses = 1
var/health_cost = 0 //The amount of health taken from the user when invoking the spell
var/datum/action/innate/cult/blood_spell/source
/obj/item/melee/blood_magic/New(loc, spell)
source = spell
uses = source.charges
health_cost = source.health_cost
..()
/obj/item/melee/blood_magic/Destroy()
if(!QDELETED(source))
if(uses <= 0)
source.hand_magic = null
qdel(source)
source = null
else
source.hand_magic = null
source.charges = uses
source.desc = source.base_desc
source.desc += "<br><b><u>Has [uses] use\s remaining</u></b>."
source.UpdateButtonIcon()
..()
/obj/item/melee/blood_magic/attack_self(mob/living/user)
afterattack(user, user, TRUE)
/obj/item/melee/blood_magic/attack(mob/living/M, mob/living/carbon/user)
if(!iscarbon(user) || !iscultist(user))
uses = 0
qdel(src)
return
add_logs(user, M, "used a cult spell on", source.name, "")
M.lastattacker = user.real_name
M.lastattackerckey = user.ckey
/obj/item/melee/blood_magic/afterattack(atom/target, mob/living/carbon/user, proximity)
if(invocation)
user.whisper(invocation, language = /datum/language/common)
if(health_cost)
if(user.active_hand_index == 1)
user.apply_damage(health_cost, BRUTE, "l_arm")
else
user.apply_damage(health_cost, BRUTE, "r_arm")
if(uses <= 0)
qdel(src)
else if(source)
source.desc = source.base_desc
source.desc += "<br><b><u>Has [uses] use\s remaining</u></b>."
source.UpdateButtonIcon()
//Stun
/obj/item/melee/blood_magic/stun
name = "Stunning Aura "
color = "#ff0000" // red
invocation = "Fuu ma'jin!"
/obj/item/melee/blood_magic/stun/afterattack(atom/target, mob/living/carbon/user, proximity)
if(!isliving(target) || !proximity)
return
var/mob/living/L = target
if(iscultist(target))
return
if(iscultist(user))
user.visible_message("<span class='warning'>[user] holds up their hand, which explodes in a flash of red light!</span>", \
"<span class='cultitalic'>You stun [L] with the spell!</span>")
var/obj/item/nullrod/N = locate() in L
if(N)
target.visible_message("<span class='warning'>[L]'s holy weapon absorbs the light!</span>", \
"<span class='userdanger'>Your holy weapon absorbs the blinding light!</span>")
else
L.Knockdown(180)
L.flash_act(1,1)
if(issilicon(target))
var/mob/living/silicon/S = L
S.emp_act(EMP_HEAVY)
else if(iscarbon(target))
var/mob/living/carbon/C = L
C.silent += 6
C.stuttering += 15
C.cultslurring += 15
C.Jitter(15)
if(is_servant_of_ratvar(L))
L.adjustBruteLoss(15)
uses--
..()
//Teleportation
/obj/item/melee/blood_magic/teleport
name = "Shifting Aura"
color = RUNE_COLOR_TELEPORT
desc = "A potent spell that teleport cultists on contact."
invocation = "Sas'so c'arta forbici!"
/obj/item/melee/blood_magic/teleport/afterattack(atom/target, mob/living/carbon/user, proximity)
if(!iscultist(target) || !proximity)
to_chat(user, "<span class='warning'>You can only teleport adjacent cultists with this spell!</span>")
return
if(iscultist(user))
var/list/potential_runes = list()
var/list/teleportnames = list()
for(var/R in GLOB.teleport_runes)
var/obj/effect/rune/teleport/T = R
potential_runes[avoid_assoc_duplicate_keys(T.listkey, teleportnames)] = T
if(!potential_runes.len)
to_chat(user, "<span class='warning'>There are no valid runes to teleport to!</span>")
log_game("Teleport talisman failed - no other teleport runes")
return
var/turf/T = get_turf(src)
if(is_away_level(T.z))
to_chat(user, "<span class='cultitalic'>You are not in the right dimension!</span>")
log_game("Teleport spell failed - user in away mission")
return
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune || !proximity)
return
var/turf/dest = get_turf(actual_selected_rune)
if(is_blocked_turf(dest, TRUE))
to_chat(user, "<span class='warning'>The target rune is blocked. Attempting to teleport to it would be massively unwise.</span>")
return
uses--
user.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!</span>", \
"<span class='cultitalic'>You speak the words of the talisman and find yourself somewhere else!</span>", "<i>You hear a sharp crack.</i>")
var/mob/living/L = target
L.forceMove(dest)
dest.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
..()
//Shackles
/obj/item/melee/blood_magic/shackles
name = "Binding Aura"
desc = "Allows you to bind a victim and temporarily silence them."
invocation = "In'totum Lig'abis!"
color = "#000000" // black
/obj/item/melee/blood_magic/shackles/afterattack(atom/target, mob/living/carbon/user, proximity)
if(iscultist(user) && iscarbon(target) && proximity)
var/mob/living/carbon/C = target
if(C.get_num_arms() >= 2 || C.get_arm_ignore())
CuffAttack(C, user)
else
user.visible_message("<span class='cultitalic'>This victim doesn't have enough arms to complete the restraint!</span>")
return
..()
/obj/item/melee/blood_magic/shackles/proc/CuffAttack(mob/living/carbon/C, mob/living/user)
if(!C.handcuffed)
playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
C.visible_message("<span class='danger'>[user] begins restraining [C] with dark magic!</span>", \
"<span class='userdanger'>[user] begins shaping a dark magic around your wrists!</span>")
if(do_mob(user, C, 30))
if(!C.handcuffed)
C.handcuffed = new /obj/item/restraints/handcuffs/energy/cult/used(C)
C.update_handcuffed()
C.silent += 5
to_chat(user, "<span class='notice'>You shackle [C].</span>")
add_logs(user, C, "shackled")
uses--
else
to_chat(user, "<span class='warning'>[C] is already bound.</span>")
else
to_chat(user, "<span class='warning'>You fail to shackle [C].</span>")
else
to_chat(user, "<span class='warning'>[C] is already bound.</span>")
/obj/item/restraints/handcuffs/energy/cult //For the shackling spell
name = "shadow shackles"
desc = "Shackles that bind the wrists with sinister magic."
trashtype = /obj/item/restraints/handcuffs/energy/used
flags_1 = DROPDEL_1
/obj/item/restraints/handcuffs/energy/cult/used/dropped(mob/user)
user.visible_message("<span class='danger'>[user]'s shackles shatter in a discharge of dark magic!</span>", \
"<span class='userdanger'>Your [src] shatters in a discharge of dark magic!</span>")
. = ..()
//Construction: Creates a construct shell out of 25 metal sheets, or converts plasteel into runed metal
/obj/item/melee/blood_magic/construction
name = "Corrupting Aura"
desc = "Corrupts metal and plasteel into more sinister forms."
invocation = "Ethra p'ni dedol!"
color = "#000000" // black
/obj/item/melee/blood_magic/construction/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
if(proximity_flag && iscultist(user))
var/turf/T = get_turf(target)
if(istype(target, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/candidate = target
if(candidate.use(50))
uses--
to_chat(user, "<span class='warning'>A dark cloud eminates from your hand and swirls around the metal, twisting it into a construct shell!</span>")
new /obj/structure/constructshell(T)
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
else
to_chat(user, "<span class='warning'>You need 50 metal to produce a construct shell!</span>")
else if(istype(target, /obj/item/stack/sheet/plasteel))
var/obj/item/stack/sheet/plasteel/candidate = target
var/quantity = min(candidate.amount, uses)
uses -= quantity
new /obj/item/stack/sheet/runed_metal(T,quantity)
candidate.use(quantity)
to_chat(user, "<span class='warning'>A dark cloud eminates from you hand and swirls around the plasteel, transforming it into runed metal!</span>")
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
else if(istype(target,/mob/living/silicon/robot))
var/mob/living/silicon/robot/candidate = target
if(candidate.mmi)
user.visible_message("<span class='danger'>A dark cloud eminates from [user]'s hand and swirls around [candidate]!</span>")
playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, 1)
var/prev_color = candidate.color
candidate.color = "black"
if(do_after(user, 90, target = candidate))
candidate.emp_act(EMP_HEAVY)
var/construct_class = alert(user, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer")
user.visible_message("<span class='danger'>The dark cloud receedes from what was formerly [candidate], revealing a\n [construct_class]!</span>")
switch(construct_class)
if("Juggernaut")
makeNewConstruct(/mob/living/simple_animal/hostile/construct/armored, candidate, user, 0, T)
if("Wraith")
makeNewConstruct(/mob/living/simple_animal/hostile/construct/wraith, candidate, user, 0, T)
if("Artificer")
makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder, candidate, user, 0, T)
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
uses--
candidate.mmi = null
qdel(candidate)
else
candidate.color = prev_color
else
uses--
to_chat(user, "<span class='warning'>A dark cloud eminates from you hand and swirls around [candidate] - twisting it into a construct shell!</span>")
new /obj/structure/constructshell(T)
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
else if(istype(target,/obj/machinery/door/airlock))
target.narsie_act()
uses--
user.visible_message("<span class='warning'>Black ribbons suddenly eminate from [user]'s hand and cling to the airlock - twisting and corrupting it!</span>")
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
else
to_chat(user, "<span class='warning'>The spell will not work on [target]!</span>")
..()
//Armor: Gives the target a basic cultist combat loadout
/obj/item/melee/blood_magic/armor
name = "Bladed Aura"
desc = "A spell that will equip the target with cultist equipment if there is a slot to equip it to."
color = "#33cc33" // green
/obj/item/melee/blood_magic/armor/afterattack(atom/target, mob/living/carbon/user, proximity)
if(iscarbon(target) && proximity)
uses--
var/mob/living/carbon/C = target
C.visible_message("<span class='warning'>Otherworldly armor suddenly appears on [C]!</span>")
C.equip_to_slot_or_del(new /obj/item/clothing/under/color/black,slot_w_uniform)
C.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head)
C.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit)
C.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), slot_shoes)
C.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), slot_back)
if(C == user)
qdel(src) //Clears the hands
C.put_in_hands(new /obj/item/melee/cultblade(user))
C.put_in_hands(new /obj/item/restraints/legcuffs/bola/cult(user))
..()
/obj/item/melee/blood_magic/manipulator
name = "Ritual Aura"
desc = "A spell that will absorb blood from anything you touch.<br>Touching cultists and constructs can heal them.<br><b>Clicking the hand will potentially let you focus the spell into something stronger.</b>"
color = "#7D1717"
/obj/item/melee/blood_magic/manipulator/afterattack(atom/target, mob/living/carbon/human/user, proximity)
if(proximity)
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(NOBLOOD in H.dna.species.species_traits)
to_chat(user,"<span class='warning'>Blood rites do not work on species with no blood!</span>")
return
if(iscultist(H))
if(H.stat == DEAD)
to_chat(user,"<span class='warning'>Only a revive rune can bring back the dead!</span>")
return
if(H.blood_volume < BLOOD_VOLUME_SAFE)
var/restore_blood = BLOOD_VOLUME_SAFE - H.blood_volume
if(uses*2 < restore_blood)
H.blood_volume += uses*2
to_chat(user,"<span class='danger'>You use the last of your blood rites to restore what blood you could!</span>")
uses = 0
return ..()
else
H.blood_volume = BLOOD_VOLUME_SAFE
uses -= round(restore_blood/2)
to_chat(user,"<span class='warning'>Your blood rites have restored [H == user ? "your" : "their"] blood to safe levels!</span>")
var/overall_damage = H.getBruteLoss() + H.getFireLoss() + H.getToxLoss() + H.getOxyLoss()
if(overall_damage == 0)
to_chat(user,"<span class='cult'>That cultist doesn't require healing!</span>")
else
var/ratio = uses/overall_damage
if(H == user)
to_chat(user,"<span class='cult'><b>Your blood healing is far less efficient when used on yourself!</b></span>")
ratio *= 0.35 // Healing is half as effective if you can't perform a full heal
uses -= round(overall_damage) // Healing is 65% more "expensive" even if you can still perform the full heal
if(ratio>1)
ratio = 1
uses -= round(overall_damage)
H.visible_message("<span class='warning'>[H] is fully healed by [H==user ? "their":"[H]'s"]'s blood magic!</span>")
else
H.visible_message("<span class='warning'>[H] is partially healed by [H==user ? "their":"[H]'s"] blood magic.</span>")
uses = 0
ratio *= -1
H.adjustOxyLoss((overall_damage*ratio) * (H.getOxyLoss() / overall_damage), 0)
H.adjustToxLoss((overall_damage*ratio) * (H.getToxLoss() / overall_damage), 0)
H.adjustFireLoss((overall_damage*ratio) * (H.getFireLoss() / overall_damage), 0)
H.adjustBruteLoss((overall_damage*ratio) * (H.getBruteLoss() / overall_damage), 0)
H.updatehealth()
playsound(get_turf(H), 'sound/magic/staff_healing.ogg', 25)
new /obj/effect/temp_visual/cult/sparks(get_turf(H))
user.Beam(H,icon_state="sendbeam",time=15)
else
if(H.stat == DEAD)
to_chat(user,"<span class='warning'>Their blood has stopped flowing, you'll have to find another way to extract it.</span>")
return
if(H.cultslurring)
to_chat(user,"<span class='danger'>Their blood has been tainted by an even stronger form of blood magic, it's no use to us like this!</span>")
return
if(H.blood_volume > BLOOD_VOLUME_SAFE)
H.blood_volume -= 100
uses += 50
user.Beam(H,icon_state="drainbeam",time=10)
playsound(get_turf(H), 'sound/magic/enter_blood.ogg', 50)
H.visible_message("<span class='danger'>[user] has drained some of [H]'s blood!</span>")
to_chat(user,"<span class='cultitalic'>Your blood rite gains 50 charges from draining [H]'s blood.</span>")
new /obj/effect/temp_visual/cult/sparks(get_turf(H))
else
to_chat(user,"<span class='danger'>They're missing too much blood - you cannot drain them further!</span>")
return
if(isconstruct(target))
var/mob/living/simple_animal/M = target
var/missing = M.maxHealth - M.health
if(missing)
if(uses > missing)
M.adjustHealth(-missing)
M.visible_message("<span class='warning'>[M] is fully healed by [user]'s blood magic!</span>")
uses -= missing
else
M.adjustHealth(-uses)
M.visible_message("<span class='warning'>[M] is partially healed by [user]'s blood magic!</span>")
uses = 0
playsound(get_turf(M), 'sound/magic/staff_healing.ogg', 25)
user.Beam(M,icon_state="sendbeam",time=10)
if(istype(target, /obj/effect/decal/cleanable/blood))
blood_draw(target, user)
..()
/obj/item/melee/blood_magic/manipulator/proc/blood_draw(atom/target, mob/living/carbon/human/user)
var/temp = 0
var/turf/T = get_turf(target)
if(T)
for(var/obj/effect/decal/cleanable/blood/B in view(T, 2))
if(B.blood_state == "blood")
if(B.bloodiness == 100) //Bonus for "pristine" bloodpools, also to prevent cheese with footprint spam
temp += 30
else
temp += max((B.bloodiness**2)/800,1)
new /obj/effect/temp_visual/cult/turf/floor(get_turf(B))
qdel(B)
for(var/obj/effect/decal/cleanable/trail_holder/TH in view(T, 2))
qdel(TH)
var/obj/item/clothing/shoes/shoecheck = user.shoes
if(shoecheck && shoecheck.bloody_shoes["blood"])
temp += shoecheck.bloody_shoes["blood"]/20
shoecheck.bloody_shoes["blood"] = 0
if(temp)
user.Beam(T,icon_state="drainbeam",time=15)
new /obj/effect/temp_visual/cult/sparks(get_turf(user))
playsound(T, 'sound/magic/enter_blood.ogg', 50)
to_chat(user, "<span class='cultitalic'>Your blood rite has gained [round(temp)] charge\s from blood sources around you!</span>")
uses += max(1, round(temp))
/obj/item/melee/blood_magic/manipulator/attack_self(mob/living/user)
if(iscultist(user))
var/list/options = list("Blood Spear (200)", "Blood Bolt Barrage (400)", "Blood Beam (600)")
var/choice = input(user, "Choose a greater blood rite...", "Greater Blood Rites") as null|anything in options
if(!choice)
to_chat(user, "<span class='cultitalic'>You decide against conducting a greater blood rite.</span>")
return
switch(choice)
if("Blood Spear (200)")
if(uses < 200)
to_chat(user, "<span class='cultitalic'>You need 200 charges to perform this rite.</span>")
else
uses -= 200
var/turf/T = get_turf(user)
qdel(src)
var/datum/action/innate/cult/spear/S = new(user)
var/obj/item/twohanded/cult_spear/rite = new(T)
S.Grant(user, rite)
rite.spear_act = S
if(user.put_in_hands(rite))
to_chat(user, "<span class='cultitalic'>A [rite.name] appears in your hand!</span>")
else
user.visible_message("<span class='warning'>A [rite.name] appears at [user]'s feet!</span>", \
"<span class='cultitalic'>A [rite.name] materializes at your feet.</span>")
if("Blood Bolt Barrage (400)")
if(uses < 400)
to_chat(user, "<span class='cultitalic'>You need 400 charges to perform this rite.</span>")
else
var/obj/rite = new /obj/item/gun/ballistic/shotgun/boltaction/enchanted/arcane_barrage/blood()
uses -= 400
qdel(src)
if(user.put_in_hands(rite))
to_chat(user, "<span class='cult'><b>Your hands glow with power!</b></span>")
else
to_chat(user, "<span class='cultitalic'>You need a free hand for this rite!</span>")
qdel(rite)
if("Blood Beam (600)")
if(uses < 600)
to_chat(user, "<span class='cultitalic'>You need 600 charges to perform this rite.</span>")
else
var/obj/rite = new /obj/item/blood_beam()
uses -= 600
qdel(src)
if(user.put_in_hands(rite))
to_chat(user, "<span class='cultlarge'><b>Your hands glow with POWER OVERWHELMING!!!</b></span>")
else
to_chat(user, "<span class='cultitalic'>You need a free hand for this rite!</span>")
qdel(rite)
+4 -2
View File
@@ -80,8 +80,10 @@
return ..()
/datum/action/innate/cult/mastervote/Activate()
var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
pollCultists(owner,C.cult_team)
var/choice = alert(owner, "The mantle of leadership is a heavy. Success in this role requires an expert level of communication and experience. Are you sure?",, "Yes", "No")
if(choice == "Yes" && IsAvailable())
var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
pollCultists(owner,C.cult_team)
/proc/pollCultists(var/mob/living/Nominee,datum/team/cult/team) //Cult Master Poll
if(world.time < CULT_POLL_WAIT)
+21 -7
View File
@@ -503,7 +503,19 @@
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
var/cursetime = 1800
var/timer = SSshuttle.emergency.timeLeft(1) + cursetime
var/security_num = seclevel2num(get_security_level())
var/set_coefficient = 1
switch(security_num)
if(SEC_LEVEL_GREEN)
set_coefficient = 2
if(SEC_LEVEL_BLUE)
set_coefficient = 1
else
set_coefficient = 0.5
var/surplus = timer - (SSshuttle.emergencyCallTime * set_coefficient)
SSshuttle.emergency.setTimer(timer)
if(surplus > 0)
SSshuttle.block_recall(surplus)
to_chat(user, "<span class='danger'>You shatter the orb! A dark essence spirals into the air, then disappears.</span>")
playsound(user.loc, 'sound/effects/glassbr1.ogg', 50, 1)
qdel(src)
@@ -511,18 +523,20 @@
var/global/list/curses
if(!curses)
curses = list("A fuel technician just slit his own throat and begged for death. The shuttle will be delayed by three minutes.",
"The shuttle's navigation programming was replaced by a file containing two words, IT COMES. The shuttle will be delayed by three minutes.",
"The shuttle's custodian tore out his guts and began painting strange shapes on the floor. The shuttle will be delayed by three minutes.",
"A shuttle engineer began screaming 'DEATH IS NOT THE END' and ripped out wires until an arc flash seared off her flesh. The shuttle will be delayed by three minutes.",
"A shuttle inspector started laughing madly over the radio and then threw herself into an engine turbine. The shuttle will be delayed by three minutes.",
"The shuttle dispatcher was found dead with bloody symbols carved into their flesh. The shuttle will be delayed by three minutes.")
"The shuttle's navigation programming was replaced by a file containing just two words: IT COMES.",
"The shuttle's custodian was found washing the windows with their own blood.",
"A shuttle engineer began screaming 'DEATH IS NOT THE END' and ripped out wires until an arc flash seared off her flesh.",
"A shuttle inspector started laughing madly over the radio and then threw herself into an engine turbine.",
"The shuttle dispatcher was found dead with bloody symbols carved into their flesh.",
"The shuttle's transponder is emitting the encoded message 'FEAR THE OLD BLOOD' in lieu of its assigned identification signal.")
var/message = pick_n_take(curses)
message += " The shuttle will be delayed by three minutes."
priority_announce("[message]", "System Failure", 'sound/misc/notice1.ogg')
curselimit++
/obj/item/device/cult_shift
name = "veil shifter"
desc = "This relic teleports you forward a medium distance."
desc = "This relic instantly teleports you, and anything you're pulling, forward by a moderate distance."
icon = 'icons/obj/cult.dmi'
icon_state ="shifter"
var/uses = 4
@@ -973,4 +987,4 @@
return
throw_at(D.thrower, 7, 1, D.thrower)
else
..()
..()
@@ -57,6 +57,7 @@
/obj/structure/destructible/cult/attackby(obj/I, mob/user, params)
if(istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user))
anchored = !anchored
density = !density
to_chat(user, "<span class='notice'>You [anchored ? "":"un"]secure \the [src] [anchored ? "to":"from"] the floor.</span>")
if(!anchored)
icon_state = "[initial(icon_state)]_off"
@@ -89,13 +90,12 @@
if(cooldowntime > world.time)
to_chat(user, "<span class='cult italic'>The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
return
var/choice = alert(user,"You study the schematics etched into the altar...",,"Eldritch Whetstone","Construct Shells","Flask of Unholy Water")
var/choice = alert(user,"You study the schematics etched into the altar...",,"Eldritch Whetstone","Construct Shell","Flask of Unholy Water")
var/list/pickedtype = list()
switch(choice)
if("Eldritch Whetstone")
pickedtype += /obj/item/sharpener/cult
if("Construct Shells")
pickedtype += /obj/structure/constructshell
if("Construct Shell")
pickedtype += /obj/structure/constructshell
if("Flask of Unholy Water")
pickedtype += /obj/item/reagent_containers/glass/beaker/unholywater
@@ -123,9 +123,11 @@
if(cooldowntime > world.time)
to_chat(user, "<span class='cult italic'>The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
return
var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Mirror Shield")
var/choice
if(user.mind.has_antag_datum(/datum/antagonist/cult/master))
choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Bastard Sword")
else
choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Mirror Shield")
var/list/pickedtype = list()
switch(choice)
if("Shielded Robe")
+3 -11
View File
@@ -68,6 +68,9 @@ This file contains the cult dagger and rune list code
A = get_area(src)
if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated() || !check_rune_turf(Turf, user))
return
if(ispath(rune_to_scribe, /obj/effect/rune/summon) && (!is_station_level(Turf.z) || A.map_name == "Space"))
to_chat(user, "<span class='cultitalic'><b>The veil is not weak enough here to summon a cultist, you must be on station!</b></span>")
return
if(ispath(rune_to_scribe, /obj/effect/rune/apocalypse))
if((world.time - SSticker.round_start_time) <= 6000)
var/wait = 6000 - (world.time - SSticker.round_start_time)
@@ -138,21 +141,10 @@ This file contains the cult dagger and rune list code
if(isspaceturf(T))
to_chat(user, "<span class='warning'>You cannot scribe runes in space!</span>")
return FALSE
if(locate(/obj/effect/rune) in T)
to_chat(user, "<span class='cult'>There is already a rune here.</span>")
return FALSE
if(!is_station_level(T.z) && !is_mining_level(T.z))
to_chat(user, "<span class='warning'>The veil is not weak enough here.</span>")
return FALSE
var/area/A = get_area(T)
if(A && !A.blob_allowed)
to_chat(user, "<span class='warning'>There's a passage in [src] specifically forbidding oyster consumption, triple-frying, and building outside of designated cult zones.</span>")
return FALSE
return TRUE
+18 -16
View File
@@ -125,16 +125,15 @@ structure_check() searches for nearby cultist structures required for the invoca
if(L.stat)
continue
invokers += L
if(invokers.len >= req_cultists)
invokers -= user
if(allow_excess_invokers)
chanters += invokers
else
shuffle_inplace(invokers)
for(var/i in 1 to req_cultists)
var/L = pick_n_take(invokers)
if(L)
chanters += L
var/C = pick_n_take(invokers)
if(!C)
break
chanters += C
return chanters
/obj/effect/rune/proc/invoke(var/list/invokers)
@@ -316,7 +315,7 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(M, "<span class='cultlarge'>\"I accept this meager sacrifice.\"</span>")
var/obj/item/device/soulstone/stone = new /obj/item/device/soulstone(get_turf(src))
if(sacrificial.mind)
if(sacrificial.mind && !sacrificial.suiciding)
stone.invisibility = INVISIBILITY_MAXIMUM //so it's not picked up during transfer_soul()
stone.transfer_soul("FORCE", sacrificial, usr)
stone.invisibility = 0
@@ -426,22 +425,19 @@ structure_check() searches for nearby cultist structures required for the invoca
else
var/area/A = get_area(T)
if(A.map_name == "Space")
actual_selected_rune.handle_portal("space")
actual_selected_rune.handle_portal("space", T)
target.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
else
fail_invoke()
/obj/effect/rune/teleport/proc/handle_portal(portal_type)
/obj/effect/rune/teleport/proc/handle_portal(portal_type, turf/origin)
var/turf/T = get_turf(src)
if(inner_portal)
qdel(inner_portal) //We need fresh effects/animations
if(outer_portal)
qdel(outer_portal)
close_portal() // To avoid stacking descriptions/animations
playsound(T, pick('sound/effects/sparks1.ogg', 'sound/effects/sparks2.ogg', 'sound/effects/sparks3.ogg', 'sound/effects/sparks4.ogg'), 100, TRUE, 14)
inner_portal = new /obj/effect/temp_visual/cult/portal(T)
if(portal_type == "space")
light_color = RUNE_COLOR_TELEPORT
desc += "<br><b>A tear in reality reveals a black void interspersed with dots of light... something recently teleported here from space!</b>"
light_color = color
desc += "<br><b>A tear in reality reveals a black void interspersed with dots of light... something recently teleported here from space.<br><u>The void feels like it's trying to pull you to the [dir2text(get_dir(T, origin))]!</u></b>"
else
inner_portal.icon_state = "lava"
light_color = LIGHT_COLOR_FIRE
@@ -452,6 +448,8 @@ structure_check() searches for nearby cultist structures required for the invoca
addtimer(CALLBACK(src, .proc/close_portal), 600, TIMER_UNIQUE)
/obj/effect/rune/teleport/proc/close_portal()
qdel(inner_portal)
qdel(outer_portal)
desc = initial(desc)
light_range = 0
update_light()
@@ -842,9 +840,13 @@ structure_check() searches for nearby cultist structures required for the invoca
var/turf/T = get_turf(src)
var/choice = alert(user,"You tear open a connection to the spirit realm...",,"Summon a Cult Ghost","Ascend as a Dark Spirit","Cancel")
if(choice == "Summon a Cult Ghost")
var/area/A = get_area(T)
if(A.map_name == "Space" || is_mining_level(T.z))
to_chat(user, "<span class='cultitalic'><b>The veil is not weak enough here to manifest spirits, you must be on station!</b></span>")
return
notify_ghosts("Manifest rune invoked in [get_area(src)].", 'sound/effects/ghost2.ogg', source = src)
var/list/ghosts_on_rune = list()
for(var/mob/dead/observer/O in get_turf(src))
for(var/mob/dead/observer/O in T)
if(O.client && !jobban_isbanned(O, ROLE_CULTIST))
ghosts_on_rune += O
if(!ghosts_on_rune.len)
@@ -853,7 +855,7 @@ structure_check() searches for nearby cultist structures required for the invoca
log_game("Manifest rune failed - no nearby ghosts")
return list()
var/mob/dead/observer/ghost_to_spawn = pick(ghosts_on_rune)
var/mob/living/carbon/human/cult_ghost/new_human = new(get_turf(src))
var/mob/living/carbon/human/cult_ghost/new_human = new(T)
new_human.real_name = ghost_to_spawn.real_name
new_human.alpha = 150 //Makes them translucent
new_human.equipOutfit(/datum/outfit/ghost_cultist) //give them armor
@@ -94,10 +94,12 @@
/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
if(incapacitated())
return 0
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
return FALSE
if(be_close && !in_range(M, src))
return 0
return 1
to_chat(src, "<span class='warning'>You are too far away!</span>")
return FALSE
return TRUE
/mob/living/carbon/true_devil/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
return 666
@@ -0,0 +1,19 @@
/datum/antagonist/greentext
name = "winner"
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE //Not that it will be there for long
/datum/antagonist/greentext/proc/forge_objectives()
var/datum/objective/O = new /datum/objective("Succeed")
O.completed = TRUE //YES!
O.owner = owner
objectives += O
owner.objectives += objectives
/datum/antagonist/greentext/on_gain()
forge_objectives()
. = ..()
/datum/antagonist/greentext/on_removal()
owner.objectives -= objectives
. = ..()
@@ -0,0 +1,85 @@
/datum/antagonist/highlander
name = "highlander"
var/obj/item/claymore/highlander/sword
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
/datum/antagonist/highlander/apply_innate_effects(mob/living/mob_override)
var/mob/living/carbon/human/H = owner.current || mob_override
if(!istype(H))
return
H.dna.species.species_traits |= NOGUNS //nice try jackass
/datum/antagonist/highlander/remove_innate_effects(mob/living/mob_override)
var/mob/living/carbon/human/H = owner.current || mob_override
if(!istype(H))
return
H.dna.species.species_traits &= ~NOGUNS
/datum/antagonist/highlander/on_removal()
owner.objectives -= objectives
. = ..()
/datum/antagonist/highlander/proc/forge_objectives()
var/datum/objective/steal/steal_objective = new
steal_objective.owner = owner
steal_objective.set_target(new /datum/objective_item/steal/nukedisc)
objectives += steal_objective
var/datum/objective/hijack/hijack_objective = new
hijack_objective.explanation_text = "Escape on the shuttle alone. Ensure that nobody else makes it out."
hijack_objective.owner = owner
objectives += hijack_objective
owner.objectives |= objectives
/datum/antagonist/highlander/on_gain()
forge_objectives()
owner.special_role = "highlander"
give_equipment()
. = ..()
/datum/antagonist/highlander/greet()
to_chat(owner, "<span class='boldannounce'>Your [sword.name] cries out for blood. Claim the lives of others, and your own will be restored!\n\
Activate it in your hand, and it will lead to the nearest target. Attack the nuclear authentication disk with it, and you will store it.</span>")
owner.announce_objectives()
/datum/antagonist/highlander/proc/give_equipment()
var/mob/living/carbon/human/H = owner.current
if(!istype(H))
return
for(var/obj/item/I in H.get_equipped_items())
qdel(I)
for(var/obj/item/I in H.held_items)
qdel(I)
H.equip_to_slot_or_del(new /obj/item/clothing/under/kilt/highlander(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(H), slot_ears)
H.equip_to_slot_or_del(new /obj/item/clothing/head/beret/highlander(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/pinpointer/nuke(H), slot_l_store)
for(var/obj/item/pinpointer/nuke/P in H)
P.attack_self(H)
var/obj/item/card/id/W = new(H)
W.icon_state = "centcom"
W.access = get_all_accesses()
W.access += get_all_centcom_access()
W.assignment = "Highlander"
W.registered_name = H.real_name
W.flags_1 |= NODROP_1
W.update_label(H.real_name)
H.equip_to_slot_or_del(W, slot_wear_id)
sword = new(H)
if(!GLOB.highlander)
sword.admin_spawned = TRUE //To prevent announcing
sword.pickup(H) //For the stun shielding
H.put_in_hands(sword)
var/obj/item/bloodcrawl/antiwelder = new(H)
antiwelder.name = "compulsion of honor"
antiwelder.desc = "You are unable to hold anything in this hand until you're the last one left!"
antiwelder.icon_state = "bloodhand_right"
H.put_in_hands(antiwelder)
+2 -2
View File
@@ -135,8 +135,8 @@
adj = "objectiveless"
else
return
new_owner.assigned_role = "Space Ninja"
new_owner.special_role = "Space Ninja"
new_owner.assigned_role = ROLE_NINJA
new_owner.special_role = ROLE_NINJA
new_owner.add_antag_datum(src)
message_admins("[key_name_admin(admin)] has [adj] ninja'ed [new_owner.current].")
log_admin("[key_name(admin)] has [adj] ninja'ed [new_owner.current].")
@@ -115,9 +115,8 @@
switch(deconstruction_state)
if(NUKESTATE_INTACT)
if(istype(I, /obj/item/screwdriver/nuke))
playsound(loc, I.usesound, 100, 1)
to_chat(user, "<span class='notice'>You start removing [src]'s front panel's screws...</span>")
if(do_after(user, 60*I.toolspeed,target=src))
if(I.use_tool(src, user, 60, volume=100))
deconstruction_state = NUKESTATE_UNSCREWED
to_chat(user, "<span class='notice'>You remove the screws from [src]'s front panel.</span>")
update_icon()
@@ -125,14 +124,13 @@
if(NUKESTATE_PANEL_REMOVED)
if(istype(I, /obj/item/weldingtool))
var/obj/item/weldingtool/welder = I
playsound(loc, I.usesound, 100, 1)
if(!I.tool_start_check(user, amount=1))
return
to_chat(user, "<span class='notice'>You start cutting [src]'s inner plate...</span>")
if(welder.remove_fuel(1,user))
if(do_after(user,80*I.toolspeed,target=src))
to_chat(user, "<span class='notice'>You cut [src]'s inner plate.</span>")
deconstruction_state = NUKESTATE_WELDED
update_icon()
if(I.use_tool(src, user, 80, volume=100, amount=1))
to_chat(user, "<span class='notice'>You cut [src]'s inner plate.</span>")
deconstruction_state = NUKESTATE_WELDED
update_icon()
return
if(NUKESTATE_CORE_EXPOSED)
if(istype(I, /obj/item/nuke_core_container))
@@ -148,19 +146,15 @@
to_chat(user, "<span class='warning'>You fail to load the plutonium core into [core_box]. [core_box] has already been used!</span>")
return
if(istype(I, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = I
if(M.amount >= 20)
to_chat(user, "<span class='notice'>You begin repairing [src]'s inner metal plate...</span>")
if(do_after(user, 100, target=src))
if(M.use(20))
to_chat(user, "<span class='notice'>You repair [src]'s inner metal plate. The radiation is contained.</span>")
deconstruction_state = NUKESTATE_PANEL_REMOVED
STOP_PROCESSING(SSobj, core)
update_icon()
else
to_chat(user, "<span class='warning'>You need more metal to do that!</span>")
else
to_chat(user, "<span class='warning'>You need more metal to do that!</span>")
if(!I.tool_start_check(user, amount=20))
return
to_chat(user, "<span class='notice'>You begin repairing [src]'s inner metal plate...</span>")
if(I.use_tool(src, user, 100, amount=20))
to_chat(user, "<span class='notice'>You repair [src]'s inner metal plate. The radiation is contained.</span>")
deconstruction_state = NUKESTATE_PANEL_REMOVED
STOP_PROCESSING(SSobj, core)
update_icon()
return
. = ..()
@@ -169,16 +163,14 @@
switch(deconstruction_state)
if(NUKESTATE_UNSCREWED)
to_chat(user, "<span class='notice'>You start removing [src]'s front panel...</span>")
playsound(loc, tool.usesound, 100, 1)
if(do_after(user, 30 * tool.toolspeed, target = src))
if(tool.use_tool(src, user, 30, volume=100))
to_chat(user, "<span class='notice'>You remove [src]'s front panel.</span>")
deconstruction_state = NUKESTATE_PANEL_REMOVED
update_icon()
return TRUE
if(NUKESTATE_WELDED)
to_chat(user, "<span class='notice'>You start prying off [src]'s inner plate...</span>")
playsound(loc, tool.usesound, 100, 1)
if(do_after(user, 50 * tool.toolspeed, target = src))
if(tool.use_tool(src, user, 30, volume=100))
to_chat(user, "<span class='notice'>You pry off [src]'s inner plate. You can see the core's green glow!</span>")
deconstruction_state = NUKESTATE_CORE_EXPOSED
update_icon()
+1 -1
View File
@@ -112,7 +112,7 @@
nuke_team = new_team
/datum/antagonist/nukeop/admin_add(datum/mind/new_owner,mob/admin)
new_owner.assigned_role = "Syndicate"
new_owner.assigned_role = ROLE_SYNDICATE
new_owner.add_antag_datum(src)
message_admins("[key_name_admin(admin)] has nuke op'ed [new_owner.current].")
log_admin("[key_name(admin)] has nuke op'ed [new_owner.current].")
@@ -184,7 +184,7 @@
carbon_mob.flash_act(1, 1)
rev_mind.current.Stun(100)
rev_mind.add_antag_datum(/datum/antagonist/rev,rev_team)
rev_mind.special_role = "Revolutionary"
rev_mind.special_role = ROLE_REV
return TRUE
/datum/antagonist/rev/head/proc/demote()
@@ -6,7 +6,7 @@
var/should_specialise = TRUE //do we split into AI and human, set to true on inital assignment only
var/ai_datum = /datum/antagonist/traitor/AI
var/human_datum = /datum/antagonist/traitor/human
var/special_role = "traitor"
var/special_role = ROLE_TRAITOR
var/employer = "The Syndicate"
var/give_objectives = TRUE
var/should_give_codewords = TRUE
@@ -85,7 +85,9 @@
return
/datum/antagonist/traitor/human/forge_traitor_objectives()
var/is_hijacker = prob(10)
var/is_hijacker = FALSE
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
if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors
@@ -219,6 +221,18 @@
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE)
owner.current.grant_language(/datum/language/codespeak)
/datum/antagonist/traitor/AI/apply_innate_effects(mob/living/mob_override)
. = ..()
var/mob/living/silicon/ai/A = mob_override || owner.current
if(istype(A))
A.hack_software = TRUE
/datum/antagonist/traitor/AI/remove_innate_effects(mob/living/mob_override)
. = ..()
var/mob/living/silicon/ai/A = mob_override || owner.current
if(istype(A))
A.hack_software = FALSE
/datum/antagonist/traitor/human/finalize_traitor()
..()
if(should_equip)
@@ -1,411 +1,411 @@
//Apprenticeship contract - moved to antag_spawner.dm
///////////////////////////Veil Render//////////////////////
/obj/item/veilrender
name = "veil render"
desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast city."
icon = 'icons/obj/wizard.dmi'
icon_state = "render"
item_state = "knife"
lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/kitchen_righthand.dmi'
force = 15
throwforce = 10
w_class = WEIGHT_CLASS_NORMAL
hitsound = 'sound/weapons/bladeslice.ogg'
var/charges = 1
var/spawn_type = /obj/singularity/wizard
var/spawn_amt = 1
var/activate_descriptor = "reality"
var/rend_desc = "You should run now."
var/spawn_fast = 0 //if 1, ignores checking for mobs on loc before spawning
/obj/item/veilrender/attack_self(mob/user)
if(charges > 0)
new /obj/effect/rend(get_turf(user), spawn_type, spawn_amt, rend_desc, spawn_fast)
charges--
user.visible_message("<span class='boldannounce'>[src] hums with power as [user] deals a blow to [activate_descriptor] itself!</span>")
else
to_chat(user, "<span class='danger'>The unearthly energies that powered the blade are now dormant.</span>")
/obj/effect/rend
name = "tear in the fabric of reality"
desc = "You should run now."
icon = 'icons/effects/effects.dmi'
icon_state = "rift"
density = TRUE
anchored = TRUE
var/spawn_path = /mob/living/simple_animal/cow //defaulty cows to prevent unintentional narsies
var/spawn_amt_left = 20
var/spawn_fast = 0
/obj/effect/rend/New(loc, var/spawn_type, var/spawn_amt, var/desc, var/spawn_fast)
src.spawn_path = spawn_type
src.spawn_amt_left = spawn_amt
src.desc = desc
src.spawn_fast = spawn_fast
START_PROCESSING(SSobj, src)
return
/obj/effect/rend/process()
if(!spawn_fast)
if(locate(/mob) in loc)
return
new spawn_path(loc)
spawn_amt_left--
if(spawn_amt_left <= 0)
qdel(src)
/obj/effect/rend/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/nullrod))
user.visible_message("<span class='danger'>[user] seals \the [src] with \the [I].</span>")
qdel(src)
return
else
return ..()
/obj/effect/rend/singularity_pull()
return
/obj/effect/rend/singularity_pull()
return
/obj/item/veilrender/vealrender
name = "veal render"
desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast farm."
spawn_type = /mob/living/simple_animal/cow
spawn_amt = 20
activate_descriptor = "hunger"
rend_desc = "Reverberates with the sound of ten thousand moos."
/obj/item/veilrender/honkrender
name = "honk render"
desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast circus."
spawn_type = /mob/living/simple_animal/hostile/retaliate/clown
spawn_amt = 10
activate_descriptor = "depression"
rend_desc = "Gently wafting with the sounds of endless laughter."
icon_state = "clownrender"
////TEAR IN REALITY
/obj/singularity/wizard
name = "tear in the fabric of reality"
desc = "This isn't right."
icon = 'icons/effects/224x224.dmi'
icon_state = "reality"
pixel_x = -96
pixel_y = -96
grav_pull = 6
consume_range = 3
current_size = STAGE_FOUR
allowed_size = STAGE_FOUR
/obj/singularity/wizard/process()
move()
eat()
return
/////////////////////////////////////////Scrying///////////////////
/obj/item/scrying
name = "scrying orb"
desc = "An incandescent orb of otherworldly energy, staring into it gives you vision beyond mortal means."
icon = 'icons/obj/projectiles.dmi'
icon_state ="bluespace"
throw_speed = 3
throw_range = 7
throwforce = 15
damtype = BURN
force = 15
hitsound = 'sound/items/welder2.ogg'
var/xray_granted = FALSE
/obj/item/scrying/equipped(mob/user)
if(!xray_granted && ishuman(user))
var/mob/living/carbon/human/H = user
if(!(H.dna.check_mutation(XRAY)))
H.dna.add_mutation(XRAY)
xray_granted = TRUE
. = ..()
/obj/item/scrying/attack_self(mob/user)
to_chat(user, "<span class='notice'>You can see...everything!</span>")
visible_message("<span class='danger'>[user] stares into [src], their eyes glazing over.</span>")
user.ghostize(1)
/////////////////////////////////////////Necromantic Stone///////////////////
/obj/item/device/necromantic_stone
name = "necromantic stone"
desc = "A shard capable of resurrecting humans as skeleton thralls."
icon = 'icons/obj/wizard.dmi'
icon_state = "necrostone"
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_TINY
var/list/spooky_scaries = list()
var/unlimited = 0
/obj/item/device/necromantic_stone/unlimited
unlimited = 1
/obj/item/device/necromantic_stone/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
if(!istype(M))
return ..()
if(!istype(user) || !user.canUseTopic(M,1))
return
if(M.stat != DEAD)
to_chat(user, "<span class='warning'>This artifact can only affect the dead!</span>")
return
if(!M.mind || !M.client)
to_chat(user, "<span class='warning'>There is no soul connected to this body...</span>")
return
check_spooky()//clean out/refresh the list
if(spooky_scaries.len >= 3 && !unlimited)
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.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>")
to_chat(M, "<span class='userdanger'>[user.p_they(TRUE)] [user.p_are()] your master now, assist them even if it costs you your new life!</span>")
equip_roman_skeleton(M)
desc = "A shard capable of resurrecting humans as skeleton thralls[unlimited ? "." : ", [spooky_scaries.len]/3 active thralls."]"
/obj/item/device/necromantic_stone/proc/check_spooky()
if(unlimited) //no point, the list isn't used.
return
for(var/X in spooky_scaries)
if(!ishuman(X))
spooky_scaries.Remove(X)
continue
var/mob/living/carbon/human/H = X
if(H.stat == DEAD)
H.dust(TRUE)
spooky_scaries.Remove(X)
continue
listclearnulls(spooky_scaries)
//Funny gimmick, skeletons always seem to wear roman/ancient armour
/obj/item/device/necromantic_stone/proc/equip_roman_skeleton(mob/living/carbon/human/H)
for(var/obj/item/I in H)
H.dropItemToGround(I)
var/hat = pick(/obj/item/clothing/head/helmet/roman, /obj/item/clothing/head/helmet/roman/legionaire)
H.equip_to_slot_or_del(new hat(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/clothing/under/roman(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/roman(H), slot_shoes)
H.put_in_hands(new /obj/item/shield/riot/roman(H), TRUE)
H.put_in_hands(new /obj/item/claymore(H), TRUE)
H.equip_to_slot_or_del(new /obj/item/twohanded/spear(H), slot_back)
/obj/item/voodoo
name = "wicker doll"
desc = "Something creepy about it."
icon = 'icons/obj/wizard.dmi'
icon_state = "voodoo"
item_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
var/mob/living/carbon/human/target = null
var/list/mob/living/carbon/human/possible = list()
var/obj/item/voodoo_link = null
var/cooldown_time = 30 //3s
var/cooldown = 0
max_integrity = 10
resistance_flags = FLAMMABLE
/obj/item/voodoo/attackby(obj/item/I, mob/user, params)
if(target && cooldown < world.time)
if(I.is_hot())
to_chat(target, "<span class='userdanger'>You suddenly feel very hot</span>")
target.bodytemperature += 50
GiveHint(target)
else if(is_pointed(I))
to_chat(target, "<span class='userdanger'>You feel a stabbing pain in [parse_zone(user.zone_selected)]!</span>")
target.Knockdown(40)
GiveHint(target)
else if(istype(I, /obj/item/bikehorn))
to_chat(target, "<span class='userdanger'>HONK</span>")
SEND_SOUND(target, 'sound/items/airhorn.ogg')
target.adjustEarDamage(0,3)
GiveHint(target)
cooldown = world.time +cooldown_time
return
if(!voodoo_link)
if(I.loc == user && istype(I) && I.w_class <= WEIGHT_CLASS_SMALL)
if (user.transferItemToLoc(I,src))
voodoo_link = I
to_chat(user, "You attach [I] to the doll.")
update_targets()
/obj/item/voodoo/check_eye(mob/user)
if(loc != user)
user.reset_perspective(null)
user.unset_machine()
/obj/item/voodoo/attack_self(mob/user)
if(!target && possible.len)
target = input(user, "Select your victim!", "Voodoo") as null|anything in possible
return
if(user.zone_selected == "chest")
if(voodoo_link)
target = null
voodoo_link.forceMove(drop_location())
to_chat(user, "<span class='notice'>You remove the [voodoo_link] from the doll.</span>")
voodoo_link = null
update_targets()
return
if(target && cooldown < world.time)
switch(user.zone_selected)
if("mouth")
var/wgw = sanitize(input(user, "What would you like the victim to say", "Voodoo", null) as text)
target.say(wgw)
log_game("[user][user.key] made [target][target.key] say [wgw] with a voodoo doll.")
if("eyes")
user.set_machine(src)
user.reset_perspective(target)
spawn(100)
user.reset_perspective(null)
user.unset_machine()
if("r_leg","l_leg")
to_chat(user, "<span class='notice'>You move the doll's legs around.</span>")
var/turf/T = get_step(target,pick(GLOB.cardinals))
target.Move(T)
if("r_arm","l_arm")
target.click_random_mob()
GiveHint(target)
if("head")
to_chat(user, "<span class='notice'>You smack the doll's head with your hand.</span>")
target.Dizzy(10)
to_chat(target, "<span class='warning'>You suddenly feel as if your head was hit with a hammer!</span>")
GiveHint(target,user)
cooldown = world.time + cooldown_time
/obj/item/voodoo/proc/update_targets()
possible = list()
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)])
possible |= H
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)
if(prob(50) || force)
var/way = dir2text(get_dir(victim,get_turf(src)))
to_chat(victim, "<span class='notice'>You feel a dark presence from [way]</span>")
if(prob(20) || force)
var/area/A = get_area(src)
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 themself and sits on it, infinitely crushing themself! 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)
target.adjust_fire_stacks(20)
target.IgniteMob()
GiveHint(target,1)
return ..()
//Provides a decent heal, need to pump every 6 seconds
/obj/item/organ/heart/cursed/wizard
pump_delay = 60
heal_brute = 25
heal_burn = 25
heal_oxy = 25
//Warp Whistle: Provides uncontrolled long distance teleportation.
/obj/item/warpwhistle
name = "warp whistle"
desc = "One toot on this whistle will send you to a far away land!"
icon = 'icons/obj/wizard.dmi'
icon_state = "whistle"
var/on_cooldown = 0 //0: usable, 1: in use, 2: on cooldown
var/mob/living/carbon/last_user
/obj/item/warpwhistle/proc/interrupted(mob/living/carbon/user)
if(!user || QDELETED(src) || user.notransform)
on_cooldown = FALSE
return TRUE
return FALSE
/obj/item/warpwhistle/attack_self(mob/living/carbon/user)
if(!istype(user) || on_cooldown)
return
on_cooldown = TRUE
last_user = user
var/turf/T = get_turf(user)
playsound(T,'sound/magic/warpwhistle.ogg', 200, 1)
user.canmove = 0
new /obj/effect/temp_visual/tornado(T)
sleep(20)
if(interrupted(user))
return
user.invisibility = INVISIBILITY_MAXIMUM
user.status_flags |= GODMODE
sleep(20)
if(interrupted(user))
return
var/breakout = 0
while(breakout < 50)
var/turf/potential_T = find_safe_turf()
if(T.z != potential_T.z || abs(get_dist_euclidian(potential_T,T)) > 50 - breakout)
user.forceMove(potential_T)
user.canmove = 0
T = potential_T
break
breakout += 1
new /obj/effect/temp_visual/tornado(T)
sleep(20)
if(interrupted(user))
return
user.invisibility = initial(user.invisibility)
user.status_flags &= ~GODMODE
user.canmove = 1
on_cooldown = 2
sleep(40)
on_cooldown = 0
/obj/item/warpwhistle/Destroy()
if(on_cooldown == 1 && last_user) //Flute got dunked somewhere in the teleport
last_user.invisibility = initial(last_user.invisibility)
last_user.status_flags &= ~GODMODE
last_user.canmove = 1
return ..()
/obj/effect/temp_visual/tornado
icon = 'icons/obj/wizard.dmi'
icon_state = "tornado"
name = "tornado"
desc = "This thing sucks!"
layer = FLY_LAYER
randomdir = 0
duration = 40
pixel_x = 500
/obj/effect/temp_visual/tornado/Initialize()
. = ..()
animate(src, pixel_x = -500, time = 40)
//Apprenticeship contract - moved to antag_spawner.dm
///////////////////////////Veil Render//////////////////////
/obj/item/veilrender
name = "veil render"
desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast city."
icon = 'icons/obj/wizard.dmi'
icon_state = "render"
item_state = "knife"
lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/kitchen_righthand.dmi'
force = 15
throwforce = 10
w_class = WEIGHT_CLASS_NORMAL
hitsound = 'sound/weapons/bladeslice.ogg'
var/charges = 1
var/spawn_type = /obj/singularity/wizard
var/spawn_amt = 1
var/activate_descriptor = "reality"
var/rend_desc = "You should run now."
var/spawn_fast = 0 //if 1, ignores checking for mobs on loc before spawning
/obj/item/veilrender/attack_self(mob/user)
if(charges > 0)
new /obj/effect/rend(get_turf(user), spawn_type, spawn_amt, rend_desc, spawn_fast)
charges--
user.visible_message("<span class='boldannounce'>[src] hums with power as [user] deals a blow to [activate_descriptor] itself!</span>")
else
to_chat(user, "<span class='danger'>The unearthly energies that powered the blade are now dormant.</span>")
/obj/effect/rend
name = "tear in the fabric of reality"
desc = "You should run now."
icon = 'icons/effects/effects.dmi'
icon_state = "rift"
density = TRUE
anchored = TRUE
var/spawn_path = /mob/living/simple_animal/cow //defaulty cows to prevent unintentional narsies
var/spawn_amt_left = 20
var/spawn_fast = 0
/obj/effect/rend/New(loc, var/spawn_type, var/spawn_amt, var/desc, var/spawn_fast)
src.spawn_path = spawn_type
src.spawn_amt_left = spawn_amt
src.desc = desc
src.spawn_fast = spawn_fast
START_PROCESSING(SSobj, src)
return
/obj/effect/rend/process()
if(!spawn_fast)
if(locate(/mob) in loc)
return
new spawn_path(loc)
spawn_amt_left--
if(spawn_amt_left <= 0)
qdel(src)
/obj/effect/rend/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/nullrod))
user.visible_message("<span class='danger'>[user] seals \the [src] with \the [I].</span>")
qdel(src)
return
else
return ..()
/obj/effect/rend/singularity_pull()
return
/obj/effect/rend/singularity_pull()
return
/obj/item/veilrender/vealrender
name = "veal render"
desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast farm."
spawn_type = /mob/living/simple_animal/cow
spawn_amt = 20
activate_descriptor = "hunger"
rend_desc = "Reverberates with the sound of ten thousand moos."
/obj/item/veilrender/honkrender
name = "honk render"
desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast circus."
spawn_type = /mob/living/simple_animal/hostile/retaliate/clown
spawn_amt = 10
activate_descriptor = "depression"
rend_desc = "Gently wafting with the sounds of endless laughter."
icon_state = "clownrender"
////TEAR IN REALITY
/obj/singularity/wizard
name = "tear in the fabric of reality"
desc = "This isn't right."
icon = 'icons/effects/224x224.dmi'
icon_state = "reality"
pixel_x = -96
pixel_y = -96
grav_pull = 6
consume_range = 3
current_size = STAGE_FOUR
allowed_size = STAGE_FOUR
/obj/singularity/wizard/process()
move()
eat()
return
/////////////////////////////////////////Scrying///////////////////
/obj/item/scrying
name = "scrying orb"
desc = "An incandescent orb of otherworldly energy, staring into it gives you vision beyond mortal means."
icon = 'icons/obj/projectiles.dmi'
icon_state ="bluespace"
throw_speed = 3
throw_range = 7
throwforce = 15
damtype = BURN
force = 15
hitsound = 'sound/items/welder2.ogg'
var/xray_granted = FALSE
/obj/item/scrying/equipped(mob/user)
if(!xray_granted && ishuman(user))
var/mob/living/carbon/human/H = user
if(!(H.dna.check_mutation(XRAY)))
H.dna.add_mutation(XRAY)
xray_granted = TRUE
. = ..()
/obj/item/scrying/attack_self(mob/user)
to_chat(user, "<span class='notice'>You can see...everything!</span>")
visible_message("<span class='danger'>[user] stares into [src], their eyes glazing over.</span>")
user.ghostize(1)
/////////////////////////////////////////Necromantic Stone///////////////////
/obj/item/device/necromantic_stone
name = "necromantic stone"
desc = "A shard capable of resurrecting humans as skeleton thralls."
icon = 'icons/obj/wizard.dmi'
icon_state = "necrostone"
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_TINY
var/list/spooky_scaries = list()
var/unlimited = 0
/obj/item/device/necromantic_stone/unlimited
unlimited = 1
/obj/item/device/necromantic_stone/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
if(!istype(M))
return ..()
if(!istype(user) || !user.canUseTopic(M, BE_CLOSE))
return
if(M.stat != DEAD)
to_chat(user, "<span class='warning'>This artifact can only affect the dead!</span>")
return
if(!M.mind || !M.client)
to_chat(user, "<span class='warning'>There is no soul connected to this body...</span>")
return
check_spooky()//clean out/refresh the list
if(spooky_scaries.len >= 3 && !unlimited)
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.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>")
to_chat(M, "<span class='userdanger'>[user.p_they(TRUE)] [user.p_are()] your master now, assist them even if it costs you your new life!</span>")
equip_roman_skeleton(M)
desc = "A shard capable of resurrecting humans as skeleton thralls[unlimited ? "." : ", [spooky_scaries.len]/3 active thralls."]"
/obj/item/device/necromantic_stone/proc/check_spooky()
if(unlimited) //no point, the list isn't used.
return
for(var/X in spooky_scaries)
if(!ishuman(X))
spooky_scaries.Remove(X)
continue
var/mob/living/carbon/human/H = X
if(H.stat == DEAD)
H.dust(TRUE)
spooky_scaries.Remove(X)
continue
listclearnulls(spooky_scaries)
//Funny gimmick, skeletons always seem to wear roman/ancient armour
/obj/item/device/necromantic_stone/proc/equip_roman_skeleton(mob/living/carbon/human/H)
for(var/obj/item/I in H)
H.dropItemToGround(I)
var/hat = pick(/obj/item/clothing/head/helmet/roman, /obj/item/clothing/head/helmet/roman/legionaire)
H.equip_to_slot_or_del(new hat(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/clothing/under/roman(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/roman(H), slot_shoes)
H.put_in_hands(new /obj/item/shield/riot/roman(H), TRUE)
H.put_in_hands(new /obj/item/claymore(H), TRUE)
H.equip_to_slot_or_del(new /obj/item/twohanded/spear(H), slot_back)
/obj/item/voodoo
name = "wicker doll"
desc = "Something creepy about it."
icon = 'icons/obj/wizard.dmi'
icon_state = "voodoo"
item_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
var/mob/living/carbon/human/target = null
var/list/mob/living/carbon/human/possible = list()
var/obj/item/voodoo_link = null
var/cooldown_time = 30 //3s
var/cooldown = 0
max_integrity = 10
resistance_flags = FLAMMABLE
/obj/item/voodoo/attackby(obj/item/I, mob/user, params)
if(target && cooldown < world.time)
if(I.is_hot())
to_chat(target, "<span class='userdanger'>You suddenly feel very hot</span>")
target.bodytemperature += 50
GiveHint(target)
else if(is_pointed(I))
to_chat(target, "<span class='userdanger'>You feel a stabbing pain in [parse_zone(user.zone_selected)]!</span>")
target.Knockdown(40)
GiveHint(target)
else if(istype(I, /obj/item/bikehorn))
to_chat(target, "<span class='userdanger'>HONK</span>")
SEND_SOUND(target, 'sound/items/airhorn.ogg')
target.adjustEarDamage(0,3)
GiveHint(target)
cooldown = world.time +cooldown_time
return
if(!voodoo_link)
if(I.loc == user && istype(I) && I.w_class <= WEIGHT_CLASS_SMALL)
if (user.transferItemToLoc(I,src))
voodoo_link = I
to_chat(user, "You attach [I] to the doll.")
update_targets()
/obj/item/voodoo/check_eye(mob/user)
if(loc != user)
user.reset_perspective(null)
user.unset_machine()
/obj/item/voodoo/attack_self(mob/user)
if(!target && possible.len)
target = input(user, "Select your victim!", "Voodoo") as null|anything in possible
return
if(user.zone_selected == "chest")
if(voodoo_link)
target = null
voodoo_link.forceMove(drop_location())
to_chat(user, "<span class='notice'>You remove the [voodoo_link] from the doll.</span>")
voodoo_link = null
update_targets()
return
if(target && cooldown < world.time)
switch(user.zone_selected)
if("mouth")
var/wgw = sanitize(input(user, "What would you like the victim to say", "Voodoo", null) as text)
target.say(wgw)
log_game("[user][user.key] made [target][target.key] say [wgw] with a voodoo doll.")
if("eyes")
user.set_machine(src)
user.reset_perspective(target)
spawn(100)
user.reset_perspective(null)
user.unset_machine()
if("r_leg","l_leg")
to_chat(user, "<span class='notice'>You move the doll's legs around.</span>")
var/turf/T = get_step(target,pick(GLOB.cardinals))
target.Move(T)
if("r_arm","l_arm")
target.click_random_mob()
GiveHint(target)
if("head")
to_chat(user, "<span class='notice'>You smack the doll's head with your hand.</span>")
target.Dizzy(10)
to_chat(target, "<span class='warning'>You suddenly feel as if your head was hit with a hammer!</span>")
GiveHint(target,user)
cooldown = world.time + cooldown_time
/obj/item/voodoo/proc/update_targets()
possible = list()
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)])
possible |= H
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)
if(prob(50) || force)
var/way = dir2text(get_dir(victim,get_turf(src)))
to_chat(victim, "<span class='notice'>You feel a dark presence from [way]</span>")
if(prob(20) || force)
var/area/A = get_area(src)
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 themself and sits on it, infinitely crushing themself! 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)
target.adjust_fire_stacks(20)
target.IgniteMob()
GiveHint(target,1)
return ..()
//Provides a decent heal, need to pump every 6 seconds
/obj/item/organ/heart/cursed/wizard
pump_delay = 60
heal_brute = 25
heal_burn = 25
heal_oxy = 25
//Warp Whistle: Provides uncontrolled long distance teleportation.
/obj/item/warpwhistle
name = "warp whistle"
desc = "One toot on this whistle will send you to a far away land!"
icon = 'icons/obj/wizard.dmi'
icon_state = "whistle"
var/on_cooldown = 0 //0: usable, 1: in use, 2: on cooldown
var/mob/living/carbon/last_user
/obj/item/warpwhistle/proc/interrupted(mob/living/carbon/user)
if(!user || QDELETED(src) || user.notransform)
on_cooldown = FALSE
return TRUE
return FALSE
/obj/item/warpwhistle/attack_self(mob/living/carbon/user)
if(!istype(user) || on_cooldown)
return
on_cooldown = TRUE
last_user = user
var/turf/T = get_turf(user)
playsound(T,'sound/magic/warpwhistle.ogg', 200, 1)
user.canmove = 0
new /obj/effect/temp_visual/tornado(T)
sleep(20)
if(interrupted(user))
return
user.invisibility = INVISIBILITY_MAXIMUM
user.status_flags |= GODMODE
sleep(20)
if(interrupted(user))
return
var/breakout = 0
while(breakout < 50)
var/turf/potential_T = find_safe_turf()
if(T.z != potential_T.z || abs(get_dist_euclidian(potential_T,T)) > 50 - breakout)
user.forceMove(potential_T)
user.canmove = 0
T = potential_T
break
breakout += 1
new /obj/effect/temp_visual/tornado(T)
sleep(20)
if(interrupted(user))
return
user.invisibility = initial(user.invisibility)
user.status_flags &= ~GODMODE
user.canmove = 1
on_cooldown = 2
sleep(40)
on_cooldown = 0
/obj/item/warpwhistle/Destroy()
if(on_cooldown == 1 && last_user) //Flute got dunked somewhere in the teleport
last_user.invisibility = initial(last_user.invisibility)
last_user.status_flags &= ~GODMODE
last_user.canmove = 1
return ..()
/obj/effect/temp_visual/tornado
icon = 'icons/obj/wizard.dmi'
icon_state = "tornado"
name = "tornado"
desc = "This thing sucks!"
layer = FLY_LAYER
randomdir = 0
duration = 40
pixel_x = 500
/obj/effect/temp_visual/tornado/Initialize()
. = ..()
animate(src, pixel_x = -500, time = 40)
+2 -2
View File
@@ -156,12 +156,12 @@
/datum/antagonist/wizard/apply_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_wiz_icons_added(M, wiz_team ? TRUE : FALSE) //Don't bother showing the icon if you're solo wizard
M.faction |= "wizard"
M.faction |= ROLE_WIZARD
/datum/antagonist/wizard/remove_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_wiz_icons_removed(M)
M.faction -= "wizard"
M.faction -= ROLE_WIZARD
/datum/antagonist/wizard/get_admin_commands()
+2 -5
View File
@@ -161,17 +161,14 @@
set category = "Object"
set src in usr
if(usr.incapacitated())
if(!usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
return
setDir(turn(dir, -90))
/obj/item/device/assembly/infra/AltClick(mob/user)
..()
if(user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user))
if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
return
else
rotate()
@@ -6,12 +6,14 @@
#define PLASMA_MINIMUM_OXYGEN_PLASMA_RATIO 30
#define PLASMA_OXYGEN_FULLBURN 10
#define FIRE_CARBON_ENERGY_RELEASED 100000 //Amount of heat released per mole of burnt carbon into the tile
#define FIRE_HYDROGEN_ENERGY_RELEASED 280000 // Amount of heat released per mole of burnt hydrogen and/or tritium(hydrogen isotope)
#define FIRE_PLASMA_ENERGY_RELEASED 3000000 //Amount of heat released per mole of burnt plasma into the tile
//General assmos defines.
#define WATER_VAPOR_FREEZE 200
#define NITRYL_FORMATION_ENERGY 100000
#define TRITIUM_BURN_OXY_FACTOR 100
#define TRITIUM_BURN_TRIT_FACTOR 10
#define TRITIUM_BURN_RADIOACTIVITY_FACTOR 1000000 //The neutrons gotta go somewhere. Completely arbitrary number.
#define SUPER_SATURATION_THRESHOLD 96
#define STIMULUM_HEAT_SCALE 100000
#define STIMULUM_FIRST_RISE 0.65
@@ -120,10 +122,10 @@
cached_gases[/datum/gas/oxygen][MOLES] -= cached_gases[/datum/gas/tritium][MOLES]
if(burned_fuel)
energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel
energy_released += FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel
ASSERT_GAS(/datum/gas/carbon_dioxide, air)
cached_gases[/datum/gas/carbon_dioxide][MOLES] += burned_fuel/TRITIUM_BURN_OXY_FACTOR
ASSERT_GAS(/datum/gas/water_vapor, air) //oxygen+more-or-less hydrogen=H2O
cached_gases[/datum/gas/water_vapor][MOLES] += burned_fuel/TRITIUM_BURN_OXY_FACTOR
cached_results[id] += burned_fuel
@@ -152,6 +154,7 @@
if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY)
ASSERT_GAS(/datum/gas/carbon_dioxide, air) //don't need to assert o2, since if it isn't present we'll never reach this point anyway
plasma_burn_rate = min(plasma_burn_rate,cached_gases[/datum/gas/plasma][MOLES],cached_gases[/datum/gas/oxygen][MOLES]/oxygen_burn_rate) //Ensures matter is conserved properly
cached_gases[/datum/gas/plasma][MOLES] = QUANTIZE(cached_gases[/datum/gas/plasma][MOLES] - plasma_burn_rate)
cached_gases[/datum/gas/oxygen][MOLES] = QUANTIZE(cached_gases[/datum/gas/oxygen][MOLES] - (plasma_burn_rate * oxygen_burn_rate))
if (super_saturation)
@@ -207,13 +210,13 @@
var/old_heat_capacity = air.heat_capacity()
var/catalyst_efficency = max(min(cached_gases[/datum/gas/plasma][MOLES]/cached_gases[/datum/gas/tritium][MOLES],MAX_CATALYST_EFFICENCY)-(temperature/FUSION_HEAT_DROPOFF),1)
var/reaction_energy = THERMAL_ENERGY(air)
var/moles_impurities = air.total_moles()-(cached_gases[/datum/gas/plasma][MOLES]+cached_gases[/datum/gas/tritium][MOLES])
var/moles_impurities = max(air.total_moles()-(cached_gases[/datum/gas/plasma][MOLES]+cached_gases[/datum/gas/tritium][MOLES]),1) //This makes it assume a minimum of 1 mol impurities so the reaction energy doesn't divide by 0
var/plasma_fused = (PLASMA_FUSED_COEFFICENT*catalyst_efficency)*(temperature/PLASMA_BINDING_ENERGY)/10
var/tritium_catalyzed = (CATALYST_COEFFICENT*catalyst_efficency)*(temperature/PLASMA_BINDING_ENERGY)/40
var/plasma_fused = min((PLASMA_FUSED_COEFFICENT*catalyst_efficency)*(temperature/PLASMA_BINDING_ENERGY)/10,cached_gases[/datum/gas/plasma][MOLES]) //Preserve matter
var/tritium_catalyzed = min((CATALYST_COEFFICENT*catalyst_efficency)*(temperature/PLASMA_BINDING_ENERGY)/40,cached_gases[/datum/gas/tritium][MOLES]) //Ditto
var/oxygen_added = tritium_catalyzed
var/waste_added = max((plasma_fused-oxygen_added)-((air.total_moles()*air.heat_capacity())/PLASMA_BINDING_ENERGY),0)
reaction_energy = max(reaction_energy+((catalyst_efficency*cached_gases[/datum/gas/plasma][MOLES])/((moles_impurities/catalyst_efficency)+2)*10)+((plasma_fused/((moles_impurities/catalyst_efficency)))*PLASMA_BINDING_ENERGY),0)
reaction_energy = max(reaction_energy+((catalyst_efficency*cached_gases[/datum/gas/plasma][MOLES])/((moles_impurities/catalyst_efficency)+2)*10)+((plasma_fused/(moles_impurities/catalyst_efficency))*PLASMA_BINDING_ENERGY),0)
air.assert_gases(/datum/gas/oxygen, /datum/gas/carbon_dioxide, /datum/gas/water_vapor, /datum/gas/nitrous_oxide, /datum/gas/nitryl)
//Fusion produces an absurd amount of waste products now, requiring active filtration.
@@ -251,7 +254,7 @@
var/temperature = air.temperature
var/old_heat_capacity = air.heat_capacity()
var/heat_efficency = temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100)
var/heat_efficency = min(temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100),cached_gases[/datum/gas/oxygen][MOLES],cached_gases[/datum/gas/nitrogen][MOLES])
var/energy_used = heat_efficency*NITRYL_FORMATION_ENERGY
ASSERT_GAS(/datum/gas/nitryl,air)
@@ -283,7 +286,7 @@
var/pressure = air.return_pressure()
var/old_heat_capacity = air.heat_capacity()
var/reaction_efficency = 1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(cached_gases[/datum/gas/plasma][MOLES]/cached_gases[/datum/gas/tritium][MOLES],1)))
var/reaction_efficency = min(1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(cached_gases[/datum/gas/plasma][MOLES]/cached_gases[/datum/gas/tritium][MOLES],1))),cached_gases[/datum/gas/tritium][MOLES],cached_gases[/datum/gas/plasma][MOLES]/2)
var/energy_released = 2*reaction_efficency*FIRE_CARBON_ENERGY_RELEASED
ASSERT_GAS(/datum/gas/bz,air)
@@ -314,9 +317,8 @@
var/list/cached_gases = air.gases
var/old_heat_capacity = air.heat_capacity()
var/heat_scale = air.temperature/STIMULUM_HEAT_SCALE
var/stim_energy_change
stim_energy_change =heat_scale + (STIMULUM_FIRST_RISE(heat_scale**2)) - (STIMULUM_FIRST_DROP(heat_scale**3)) + (STIMULUM_SECOND_RISE(heat_scale**4)) - (STIMULUM_ABSOLUTE_DROP(heat_scale**5))
var/heat_scale = min(air.temperature/STIMULUM_HEAT_SCALE,cached_gases[/datum/gas/tritium][MOLES],cached_gases[/datum/gas/plasma][MOLES],cached_gases[/datum/gas/nitryl][MOLES])
var/stim_energy_change = heat_scale + STIMULUM_FIRST_RISE*(heat_scale**2) - STIMULUM_FIRST_DROP*(heat_scale**3) + STIMULUM_SECOND_RISE*(heat_scale**4) - STIMULUM_ABSOLUTE_DROP*(heat_scale**5)
ASSERT_GAS(/datum/gas/stimulum,air)
cached_gases[/datum/gas/stimulum][MOLES]+= heat_scale/10
@@ -345,7 +347,7 @@
var/list/cached_gases = air.gases
air.assert_gases(/datum/gas/hypernoblium,/datum/gas/bz)
var/old_heat_capacity = air.heat_capacity()
var/nob_formed = (cached_gases[/datum/gas/nitrogen][MOLES]*cached_gases[/datum/gas/tritium][MOLES])/100
var/nob_formed = min((cached_gases[/datum/gas/nitrogen][MOLES]+cached_gases[/datum/gas/tritium][MOLES])/100,cached_gases[/datum/gas/tritium][MOLES]/10,cached_gases[/datum/gas/nitrogen][MOLES]/20)
var/energy_taken = nob_formed*(NOBLIUM_FORMATION_ENERGY/(max(cached_gases[/datum/gas/bz][MOLES],1)))
cached_gases[/datum/gas/tritium][MOLES] = max(cached_gases[/datum/gas/tritium][MOLES]- 10*nob_formed,0)
cached_gases[/datum/gas/nitrogen][MOLES] = max(cached_gases[/datum/gas/nitrogen][MOLES]- 20*nob_formed,0)
@@ -653,14 +653,14 @@
switch(buildstage)
if(2)
if(istype(W, /obj/item/wirecutters) && panel_open && wires.is_all_cut())
playsound(src.loc, W.usesound, 50, 1)
W.play_tool_sound(src)
to_chat(user, "<span class='notice'>You cut the final wires.</span>")
new /obj/item/stack/cable_coil(loc, 5)
buildstage = 1
update_icon()
return
else if(istype(W, /obj/item/screwdriver)) // Opening that Air Alarm up.
playsound(src.loc, W.usesound, 50, 1)
W.play_tool_sound(src)
panel_open = !panel_open
to_chat(user, "<span class='notice'>The wires have been [panel_open ? "exposed" : "unexposed"].</span>")
update_icon()
@@ -674,8 +674,8 @@
if(istype(W, /obj/item/crowbar))
user.visible_message("[user.name] removes the electronics from [src.name].",\
"<span class='notice'>You start prying out the circuit...</span>")
playsound(src.loc, W.usesound, 50, 1)
if (do_after(user, 20*W.toolspeed, target = src))
W.play_tool_sound(src)
if (W.use_tool(src, user, 20))
if (buildstage == 1)
to_chat(user, "<span class='notice'>You remove the air alarm electronics.</span>")
new /obj/item/electronics/airalarm( src.loc )
@@ -725,7 +725,7 @@
if(istype(W, /obj/item/wrench))
to_chat(user, "<span class='notice'>You detach \the [src] from the wall.</span>")
playsound(src.loc, W.usesound, 50, 1)
W.play_tool_sound(src)
new /obj/item/wallframe/airalarm( user.loc )
qdel(src)
return
@@ -734,8 +734,7 @@
/obj/machinery/airalarm/AltClick(mob/user)
..()
if(!issilicon(user) && (!user.canUseTopic(src, be_close=TRUE) || !isturf(loc)))
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc))
return
else
togglelock(user)
@@ -183,39 +183,44 @@ Pipelines + Other Objects -> Pipe network
if(user.dropItemToGround(pipe))
pipe.setPipingLayer(piping_layer) //align it with us
return TRUE
if(istype(W, /obj/item/wrench))
if(can_unwrench(user))
var/turf/T = get_turf(src)
if (level==1 && isturf(T) && T.intact)
to_chat(user, "<span class='warning'>You must remove the plating first!</span>")
return TRUE
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
add_fingerprint(user)
var/unsafe_wrenching = FALSE
var/internal_pressure = int_air.return_pressure()-env_air.return_pressure()
playsound(src, W.usesound, 50, 1)
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
if (internal_pressure > 2*ONE_ATMOSPHERE)
to_chat(user, "<span class='warning'>As you begin unwrenching \the [src] a gush of air blows in your face... maybe you should reconsider?</span>")
unsafe_wrenching = TRUE //Oh dear oh dear
if (do_after(user, 20*W.toolspeed, target = src) && !QDELETED(src))
user.visible_message( \
"[user] unfastens \the [src].", \
"<span class='notice'>You unfasten \the [src].</span>", \
"<span class='italics'>You hear ratchet.</span>")
investigate_log("was <span class='warning'>REMOVED</span> by [key_name(usr)]", INVESTIGATE_ATMOS)
//You unwrenched a pipe full of pressure? Let's splat you into the wall, silly.
if(unsafe_wrenching)
unsafe_pressure_release(user, internal_pressure)
deconstruct(TRUE)
else
return ..()
/obj/machinery/atmospherics/wrench_act(mob/living/user, obj/item/I)
if(!can_unwrench(user))
return TRUE
var/turf/T = get_turf(src)
if (level==1 && isturf(T) && T.intact)
to_chat(user, "<span class='warning'>You must remove the plating first!</span>")
return TRUE
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
add_fingerprint(user)
var/unsafe_wrenching = FALSE
var/internal_pressure = int_air.return_pressure()-env_air.return_pressure()
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
if (internal_pressure > 2*ONE_ATMOSPHERE)
to_chat(user, "<span class='warning'>As you begin unwrenching \the [src] a gush of air blows in your face... maybe you should reconsider?</span>")
unsafe_wrenching = TRUE //Oh dear oh dear
if(I.use_tool(src, user, 20, volume=50))
user.visible_message( \
"[user] unfastens \the [src].", \
"<span class='notice'>You unfasten \the [src].</span>", \
"<span class='italics'>You hear ratchet.</span>")
investigate_log("was <span class='warning'>REMOVED</span> by [key_name(usr)]", INVESTIGATE_ATMOS)
//You unwrenched a pipe full of pressure? Let's splat you into the wall, silly.
if(unsafe_wrenching)
unsafe_pressure_release(user, internal_pressure)
deconstruct(TRUE)
return TRUE
/obj/machinery/atmospherics/proc/can_unwrench(mob/user)
return can_unwrench
@@ -345,8 +350,6 @@ Pipelines + Other Objects -> Pipe network
return list()
/obj/machinery/atmospherics/update_remote_sight(mob/user)
// if(isborer(user))
// user.sight |= (SEE_PIXELS)
user.sight |= (SEE_TURFS|BLIND)
//Used for certain children of obj/machinery/atmospherics to not show pipe vision when mob is inside it.
@@ -184,7 +184,8 @@
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
beaker.reagents.trans_to(occupant, 1, efficiency * 0.25) // Transfer reagents.
beaker.reagents.reaction(occupant, VAPOR)
air1.gases[/datum/gas/oxygen][MOLES] -= 2 / efficiency //Let's use gas for this
air1.gases[/datum/gas/oxygen][MOLES] -= max(0,air1.gases[/datum/gas/oxygen][MOLES] - 2 / efficiency) //Let's use gas for this
air1.garbage_collect()
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
reagent_transfer = 0
@@ -220,7 +221,8 @@
air1.temperature = max(air1.temperature - heat / air_heat_capacity, TCMB)
mob_occupant.bodytemperature = max(mob_occupant.bodytemperature + heat / heat_capacity, TCMB)
air1.gases[/datum/gas/oxygen][MOLES] -= 0.5 / efficiency // Magically consume gas? Why not, we run on cryo magic.
air1.gases[/datum/gas/oxygen][MOLES] = max(0,air1.gases[/datum/gas/oxygen][MOLES] - 0.5 / efficiency) // Magically consume gas? Why not, we run on cryo magic.
air1.garbage_collect()
/obj/machinery/atmospherics/components/unary/cryo_cell/power_change()
..()
@@ -269,28 +269,21 @@
broadcast_status()
update_icon()
/obj/machinery/atmospherics/components/unary/vent_pump/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool))
var/obj/item/weldingtool/WT = W
if (WT.remove_fuel(0, user))
playsound(loc, WT.usesound, 40, 1)
to_chat(user, "<span class='notice'>You begin welding the vent...</span>")
if(do_after(user, W.toolspeed * 20, target = src))
if(!src || !WT.isOn())
return
playsound(src.loc, 'sound/items/welder2.ogg', 50, 1)
if(!welded)
user.visible_message("[user] welds the vent shut.", "<span class='notice'>You weld the vent shut.</span>", "<span class='italics'>You hear welding.</span>")
welded = TRUE
else
user.visible_message("[user] unwelds the vent.", "<span class='notice'>You unweld the vent.</span>", "<span class='italics'>You hear welding.</span>")
welded = FALSE
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
return 0
else
return ..()
/obj/machinery/atmospherics/components/unary/vent_pump/welder_act(mob/living/user, obj/item/I)
if(!I.tool_start_check(user, amount=0))
return TRUE
to_chat(user, "<span class='notice'>You begin welding the vent...</span>")
if(I.use_tool(src, user, 20, volume=50))
if(!welded)
user.visible_message("[user] welds the vent shut.", "<span class='notice'>You weld the vent shut.</span>", "<span class='italics'>You hear welding.</span>")
welded = TRUE
else
user.visible_message("[user] unwelds the vent.", "<span class='notice'>You unweld the vent.</span>", "<span class='italics'>You hear welding.</span>")
welded = FALSE
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
return TRUE
/obj/machinery/atmospherics/components/unary/vent_pump/can_unwrench(mob/user)
. = ..()
@@ -263,28 +263,21 @@
..()
update_icon_nopipes()
/obj/machinery/atmospherics/components/unary/vent_scrubber/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool))
var/obj/item/weldingtool/WT = W
if(WT.remove_fuel(0,user))
playsound(loc, WT.usesound, 40, 1)
to_chat(user, "<span class='notice'>Now welding the scrubber.</span>")
if(do_after(user, 20*W.toolspeed, target = src))
if(!src || !WT.isOn())
return
playsound(src.loc, 'sound/items/welder2.ogg', 50, 1)
if(!welded)
user.visible_message("[user] welds the scrubber shut.","You weld the scrubber shut.", "You hear welding.")
welded = TRUE
else
user.visible_message("[user] unwelds the scrubber.", "You unweld the scrubber.", "You hear welding.")
welded = FALSE
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
return 0
else
return ..()
/obj/machinery/atmospherics/components/unary/vent_scrubber/welder_act(mob/living/user, obj/item/I)
if(!I.tool_start_check(user, amount=0))
return TRUE
to_chat(user, "<span class='notice'>Now welding the scrubber.</span>")
if(I.use_tool(src, user, 20, volume=50))
if(!welded)
user.visible_message("[user] welds the scrubber shut.","You weld the scrubber shut.", "You hear welding.")
welded = TRUE
else
user.visible_message("[user] unwelds the scrubber.", "You unweld the scrubber.", "You hear welding.")
welded = FALSE
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_unwrench(mob/user)
. = ..()
@@ -100,19 +100,20 @@
to_chat(user, status())
/obj/machinery/meter/attackby(obj/item/W, mob/user, params)
if (istype(W, /obj/item/wrench))
playsound(src, W.usesound, 50, 1)
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
if (do_after(user, 40*W.toolspeed, target = src))
user.visible_message( \
"[user] unfastens \the [src].", \
"<span class='notice'>You unfasten \the [src].</span>", \
"<span class='italics'>You hear ratchet.</span>")
new /obj/item/pipe_meter(loc)
qdel(src)
else
return ..()
/obj/machinery/meter/wrench_act(mob/user, obj/item/I)
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
if (I.use_tool(src, user, 40, volume=50))
user.visible_message(
"[user] unfastens \the [src].",
"<span class='notice'>You unfasten \the [src].</span>",
"<span class='italics'>You hear ratchet.</span>")
deconstruct()
return TRUE
/obj/machinery/meter/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
new /obj/item/pipe_meter(loc)
qdel(src)
/obj/machinery/meter/attack_ai(mob/user)
return attack_hand(user)
@@ -131,8 +132,7 @@
/obj/machinery/meter/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
new /obj/item/pipe_meter(loc)
qdel(src)
deconstruct()
// TURF METER - REPORTS A TILE'S AIR CONTENTS
// why are you yelling?
@@ -278,21 +278,20 @@
new /obj/item/stack/sheet/metal (loc, 5)
qdel(src)
/obj/machinery/portable_atmospherics/canister/attackby(obj/item/W, mob/user, params)
if(user.a_intent != INTENT_HARM && istype(W, /obj/item/weldingtool))
var/obj/item/weldingtool/WT = W
if(stat & BROKEN)
if(!WT.remove_fuel(0, user))
return
playsound(loc, WT.usesound, 40, 1)
to_chat(user, "<span class='notice'>You begin cutting [src] apart...</span>")
if(do_after(user, 30, target = src))
deconstruct(TRUE)
else
to_chat(user, "<span class='notice'>You cannot slice [src] apart when it isn't broken.</span>")
return 1
/obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/item/I)
if(user.a_intent == INTENT_HARM)
return FALSE
if(stat & BROKEN)
if(!I.tool_start_check(user, amount=0))
return TRUE
to_chat(user, "<span class='notice'>You begin cutting [src] apart...</span>")
if(I.use_tool(src, user, 30, volume=50))
deconstruct(TRUE)
else
return ..()
to_chat(user, "<span class='notice'>You cannot slice [src] apart when it isn't broken.</span>")
return TRUE
/obj/machinery/portable_atmospherics/canister/obj_break(damage_flag)
if((stat & BROKEN) || (flags_1 & NODECONSTRUCT_1))
@@ -92,7 +92,7 @@
if(!(stat & BROKEN))
if(connected_port)
disconnect()
playsound(src.loc, W.usesound, 50, 1)
W.play_tool_sound(src)
user.visible_message( \
"[user] disconnects [src].", \
"<span class='notice'>You unfasten [src] from the port.</span>", \
@@ -107,7 +107,7 @@
if(!connect(possible_port))
to_chat(user, "<span class='notice'>[name] failed to connect to the port.</span>")
return
playsound(src.loc, W.usesound, 50, 1)
W.play_tool_sound(src)
user.visible_message( \
"[user] connects [src].", \
"<span class='notice'>You fasten [src] to the port.</span>", \
+1 -1
View File
@@ -222,7 +222,7 @@
var/mob/living/silicon/ai/spawned/M = new(loc) //spawn new AI at landmark as var M
M.name = src.name
M.real_name = src.name
M.aiPDA.toff = 1 //turns the AI's PDA messenger off, stopping it showing up on player PDAs
M.aiPDA.toff = TRUE //turns the AI's PDA messenger off, stopping it showing up on player PDAs
M.death() //call the AI's death proc
qdel(src)
@@ -149,6 +149,16 @@
//liquid plasma!!!!!!//
/turf/open/floor/plasteel/vault/snowdin
initial_gas_mix = "o2=22;n2=82;TEMP=180"
planetary_atmos = 1
temperature = 180
/turf/open/floor/plasteel/dark/snowdin
initial_gas_mix = "o2=22;n2=82;TEMP=180"
planetary_atmos = 1
temperature = 180
/turf/open/lava/plasma
name = "liquid plasma"
desc = "A flowing stream of chilled liquid plasma. You probably shouldn't get in."
@@ -540,6 +550,12 @@
//special items//--
/obj/structure/barricade/wooden/snowed
name = "crude plank barricade"
desc = "This space is blocked off by a wooden barricade. It seems to be covered in a layer of snow."
icon_state = "woodenbarricade-snow"
max_integrity = 125
/obj/item/clothing/under/syndicate/coldres
name = "insulated tactical turtleneck"
desc = "A non-descript and slightly suspicious-looking turtleneck with digital camouflage cargo pants. The interior has been padded with special insulation for both warmth and protection."
@@ -587,7 +603,7 @@
shoes = /obj/item/clothing/shoes/combat/coldres
ears = /obj/item/device/radio/headset/syndicate/alt
r_pocket = /obj/item/gun/ballistic/automatic/pistol
l_pocket = /obj/item/card/id/syndicate
id = /obj/item/card/id/syndicate
implants = list(/obj/item/implant/exile)
/obj/effect/mob_spawn/human/syndicatesoldier/coldres/alive/female
+23
View File
@@ -991,6 +991,29 @@
/obj/item/pizzabox/vegetable,
/obj/item/pizzabox/pineapple)
crate_name = "pizza crate"
var/static/anomalous_box_provided = FALSE
/datum/supply_pack/organic/pizza/fill(obj/structure/closet/crate/C)
. = ..()
if(!anomalous_box_provided)
for(var/obj/item/pizzabox/P in C)
if(prob(1)) //1% chance for each box, so 4% total chance per order
var/obj/item/pizzabox/infinite/fourfiveeight = new(C)
fourfiveeight.boxtag = P.boxtag
qdel(P)
anomalous_box_provided = TRUE
log_game("An anomalous pizza box was provided in a pizza crate at during cargo delivery")
if(prob(50))
addtimer(CALLBACK(src, .proc/anomalous_pizza_report), rand(300, 1800))
else
message_admins("An anomalous pizza box was silently created with no command report in a pizza crate delivery.")
break
/datum/supply_pack/organic/pizza/proc/anomalous_pizza_report()
print_command_report("[station_name()], our anomalous materials divison has reported a missing object that is highly likely to have been sent to your station during a routine cargo \
delivery. Please search all crates and manifests provided with the delivery and return the object if is located. The object resembles a standard <b>\[DATA EXPUNGED\]</b> and is to be \
considered <b>\[REDACTED\]</b> and returned at your leisure. Note that objects the anomaly produces are specifically attuned exactly to the individual opening the anomaly; regardless \
of species, the individual will find the object edible and it will taste great according to their personal definitions, which vary significantly based on person and species.")
/datum/supply_pack/organic/cream_piee
name = "High-yield Clown-grade Cream Pie Crate"
+28 -5
View File
@@ -3,6 +3,12 @@
////////////
#define UPLOAD_LIMIT 1048576 //Restricts client uploads to the server to 1MB //Could probably do with being lower.
GLOBAL_LIST_INIT(blacklisted_builds, list(
"1407" = "bug preventing client display overrides from working leads to clients being able to see things/mobs they shouldn't be able to see",
"1408" = "bug preventing client display overrides from working leads to clients being able to see things/mobs they shouldn't be able to see",
))
#define LIMITER_SIZE 5
#define CURRENT_SECOND 1
#define SECOND_COUNT 2
@@ -228,7 +234,18 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
. = ..() //calls mob.Login()
#if DM_VERSION >= 512
if (num2text(byond_build) in GLOB.blacklisted_builds)
log_access("Failed login: blacklisted byond version")
to_chat(src, "<span class='userdanger'>Your version of byond is blacklisted.</span>")
to_chat(src, "<span class='danger'>Byond build [byond_build] ([byond_version].[byond_build]) has been blacklisted for the following reason: [GLOB.blacklisted_builds[num2text(byond_build)]].</span>")
to_chat(src, "<span class='danger'>Please download a new version of byond. if [byond_build] is the latest, you can go to http://www.byond.com/download/build/ to download other versions.</span>")
if(connecting_admin)
to_chat(src, "As an admin, you are being allowed to continue using this version, but please consider changing byond versions")
else
qdel(src)
return
#endif
if(SSinput.initialized)
set_macros()
@@ -539,10 +556,10 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
tokens[ckey] = cid_check_reconnect()
sleep(15 SECONDS) //Longer sleep here since this would trigger if a client tries to reconnect manually because the inital reconnect failed
//we sleep after telling the client to reconnect, so if we still exist something is up
log_access("Forced disconnect: [key] [computer_id] [address] - CID randomizer check")
qdel(src)
return TRUE
@@ -585,10 +602,10 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
tokens[ckey] = cid_check_reconnect()
sleep(5 SECONDS) //browse is queued, we don't want them to disconnect before getting the browse() command.
//we sleep after telling the client to reconnect, so if we still exist something is up
log_access("Forced disconnect: [key] [computer_id] [address] - CID randomizer check")
qdel(src)
return TRUE
@@ -709,6 +726,12 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
if (isnull(new_size))
CRASH("change_view called without argument.")
//CIT CHANGES START HERE - makes change_view change DEFAULT_VIEW to 15x15 depending on preferences
if(prefs && CONFIG_GET(string/default_view))
if(!prefs.widescreenpref && new_size == CONFIG_GET(string/default_view))
new_size = "15x15"
//END OF CIT CHANGES
view = new_size
apply_clickcatcher()
if (isliving(mob))
+7 -5
View File
@@ -181,14 +181,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/uplink_spawn_loc = UPLINK_PDA
var/list/exp
var/list/exp = list()
var/list/menuoptions
var/action_buttons_screen_locs = list()
var/screenshake = 100
var/damagescreenshake = 2
var/arousable = TRUE
/datum/preferences/New(client/C)
parent = C
@@ -386,6 +383,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "High"
dat += "</a><br>"
dat += "<b>Widescreen:</b> <a href='?_src_=prefs;preference=widescreenpref'>[widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"]</a><br>"
dat += "<b>Screen Shake:</b> <a href='?_src_=prefs;preference=screenshake'>[(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")]</a><br>"
if (!user.client.prefs.screenshake==0)
@@ -1195,7 +1194,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
new_wings = input(user, "Choose your character's wings:", "Character Preference") as null|anything in GLOB.r_wings_list
if(new_wings)
features["wings"] = new_wings
if("moth_wings")
var/new_moth_wings
new_moth_wings = input(user, "Choose your character's wings:", "Character Preference") as null|anything in GLOB.moth_wings_list
@@ -1565,6 +1564,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["exhibitionist"] = TRUE
else
features["exhibitionist"] = FALSE
if("widescreenpref")
widescreenpref = !widescreenpref
user.client.change_view(CONFIG_GET(string/default_view))
if ("screenshake")
var/desiredshake = input(user, "Set the amount of screenshake you want. \n(0 = disabled, 100 = full, 200 = maximum.)", "Character Preference", screenshake) as null|num
if (!isnull(desiredshake))
@@ -172,6 +172,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["hotkeys"] >> hotkeys
S["tgui_fancy"] >> tgui_fancy
S["tgui_lock"] >> tgui_lock
S["buttons_locked"] >> buttons_locked
S["windowflash"] >> windowflashing
S["be_special"] >> be_special
@@ -200,6 +201,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["arousable"] >> arousable
S["screenshake"] >> screenshake
S["damagescreenshake"] >> damagescreenshake
S["widescreenpref"] >> widescreenpref
//try to fix any outdated data if necessary
if(needs_update >= 0)
@@ -213,6 +215,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
hotkeys = sanitize_integer(hotkeys, 0, 1, initial(hotkeys))
tgui_fancy = sanitize_integer(tgui_fancy, 0, 1, initial(tgui_fancy))
tgui_lock = sanitize_integer(tgui_lock, 0, 1, initial(tgui_lock))
buttons_locked = sanitize_integer(buttons_locked, 0, 1, initial(buttons_locked))
windowflashing = sanitize_integer(windowflashing, 0, 1, initial(windowflashing))
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
toggles = sanitize_integer(toggles, 0, 65535, initial(toggles))
@@ -229,6 +232,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
screenshake = sanitize_integer(screenshake, 0, 800, initial(screenshake))
damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake))
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
return 1
@@ -249,6 +253,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["hotkeys"], hotkeys)
WRITE_FILE(S["tgui_fancy"], tgui_fancy)
WRITE_FILE(S["tgui_lock"], tgui_lock)
WRITE_FILE(S["buttons_locked"], buttons_locked)
WRITE_FILE(S["windowflash"], windowflashing)
WRITE_FILE(S["be_special"], be_special)
WRITE_FILE(S["default_slot"], default_slot)
@@ -275,6 +280,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["screenshake"], screenshake)
WRITE_FILE(S["damagescreenshake"], damagescreenshake)
WRITE_FILE(S["arousable"], arousable)
WRITE_FILE(S["widescreenpref"], widescreenpref)
return 1
+1 -1
View File
@@ -579,7 +579,7 @@
/obj/item/storage/belt/chameleon
name = "toolbelt"
desc = "Holds tools."
silent = 1
silent = TRUE
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/storage/belt/chameleon/Initialize()
+2 -3
View File
@@ -90,7 +90,7 @@
return ..()
/obj/item/clothing/AltClick(mob/user)
if(pockets && pockets.quickdraw && pockets.contents.len && !user.incapacitated())
if(istype(user) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)) && pockets && pockets.quickdraw && pockets.contents.len)
var/obj/item/I = pockets.contents[1]
if(!I)
return
@@ -244,8 +244,7 @@ BLIND // can't see anything
if(..())
return 1
if(!user.canUseTopic(src, be_close=TRUE))
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
else
if(attached_accessory)
+4 -4
View File
@@ -49,12 +49,12 @@
/obj/item/clothing/gloves/color/black/ce
item_color = "chief" //Exists for washing machines. Is not different from black gloves in any way.
/obj/item/clothing/gloves/color/black/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/wirecutters))
/obj/item/clothing/gloves/color/black/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wirecutters))
if(can_be_cut && icon_state == initial(icon_state))//only if not dyed
to_chat(user, "<span class='notice'>You snip the fingertips off of [src].</span>")
playsound(user.loc, W.usesound, rand(10,50), 1)
new /obj/item/clothing/gloves/fingerless(user.loc)
I.play_tool_sound(src)
new /obj/item/clothing/gloves/fingerless(drop_location())
qdel(src)
..()
+1 -1
View File
@@ -87,7 +87,7 @@
to_chat(user, "<span class='notice'>Alt-click to take a candy corn.</span>")
/obj/item/clothing/head/fedora/det_hat/AltClick(mob/user)
if(user.canUseTopic(src, be_close=TRUE))
if(user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
..()
if(loc == user)
if(candy_cooldown < world.time)
+131 -132
View File
@@ -1,132 +1,131 @@
/obj/item/clothing/head/soft
name = "cargo cap"
desc = "It's a baseball hat in a tasteless yellow colour."
icon_state = "cargosoft"
item_state = "helmet"
item_color = "cargo"
dog_fashion = /datum/dog_fashion/head/cargo_tech
var/flipped = 0
/obj/item/clothing/head/soft/dropped()
src.icon_state = "[item_color]soft"
src.flipped=0
..()
/obj/item/clothing/head/soft/verb/flipcap()
set category = "Object"
set name = "Flip cap"
flip(usr)
/obj/item/clothing/head/soft/AltClick(mob/user)
..()
if(!user.canUseTopic(src, be_close=TRUE))
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
else
flip(user)
/obj/item/clothing/head/soft/proc/flip(mob/user)
if(user.canmove && !user.stat && !user.restrained())
src.flipped = !src.flipped
if(src.flipped)
icon_state = "[item_color]soft_flipped"
to_chat(user, "<span class='notice'>You flip the hat backwards.</span>")
else
icon_state = "[item_color]soft"
to_chat(user, "<span class='notice'>You flip the hat back in normal position.</span>")
usr.update_inv_head() //so our mob-overlays update
/obj/item/clothing/head/soft/examine(mob/user)
..()
to_chat(user, "<span class='notice'>Alt-click the cap to flip it [flipped ? "forwards" : "backwards"].</span>")
/obj/item/clothing/head/soft/red
name = "red cap"
desc = "It's a baseball hat in a tasteless red colour."
icon_state = "redsoft"
item_color = "red"
dog_fashion = null
/obj/item/clothing/head/soft/blue
name = "blue cap"
desc = "It's a baseball hat in a tasteless blue colour."
icon_state = "bluesoft"
item_color = "blue"
dog_fashion = null
/obj/item/clothing/head/soft/green
name = "green cap"
desc = "It's a baseball hat in a tasteless green colour."
icon_state = "greensoft"
item_color = "green"
dog_fashion = null
/obj/item/clothing/head/soft/yellow
name = "yellow cap"
desc = "It's a baseball hat in a tasteless yellow colour."
icon_state = "yellowsoft"
item_color = "yellow"
dog_fashion = null
/obj/item/clothing/head/soft/grey
name = "grey cap"
desc = "It's a baseball hat in a tasteful grey colour."
icon_state = "greysoft"
item_color = "grey"
dog_fashion = null
/obj/item/clothing/head/soft/orange
name = "orange cap"
desc = "It's a baseball hat in a tasteless orange colour."
icon_state = "orangesoft"
item_color = "orange"
dog_fashion = null
/obj/item/clothing/head/soft/mime
name = "white cap"
desc = "It's a baseball hat in a tasteless white colour."
icon_state = "mimesoft"
item_color = "mime"
dog_fashion = null
/obj/item/clothing/head/soft/purple
name = "purple cap"
desc = "It's a baseball hat in a tasteless purple colour."
icon_state = "purplesoft"
item_color = "purple"
dog_fashion = null
/obj/item/clothing/head/soft/black
name = "black cap"
desc = "It's a baseball hat in a tasteless black colour."
icon_state = "blacksoft"
item_color = "black"
dog_fashion = null
/obj/item/clothing/head/soft/rainbow
name = "rainbow cap"
desc = "It's a baseball hat in a bright rainbow of colors."
icon_state = "rainbowsoft"
item_color = "rainbow"
dog_fashion = null
/obj/item/clothing/head/soft/sec
name = "security cap"
desc = "It's a robust baseball hat in tasteful red colour."
icon_state = "secsoft"
item_color = "sec"
armor = list(melee = 30, bullet = 25, laser = 25, energy = 10, bomb = 25, bio = 0, rad = 0, fire = 20, acid = 50)
strip_delay = 60
dog_fashion = null
/obj/item/clothing/head/soft/emt
name = "EMT cap"
desc = "It's a baseball hat with a dark turquoise color and a reflective cross on the top."
icon_state = "emtsoft"
item_color = "emt"
dog_fashion = null
/obj/item/clothing/head/soft
name = "cargo cap"
desc = "It's a baseball hat in a tasteless yellow colour."
icon_state = "cargosoft"
item_state = "helmet"
item_color = "cargo"
dog_fashion = /datum/dog_fashion/head/cargo_tech
var/flipped = 0
/obj/item/clothing/head/soft/dropped()
src.icon_state = "[item_color]soft"
src.flipped=0
..()
/obj/item/clothing/head/soft/verb/flipcap()
set category = "Object"
set name = "Flip cap"
flip(usr)
/obj/item/clothing/head/soft/AltClick(mob/user)
..()
if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
else
flip(user)
/obj/item/clothing/head/soft/proc/flip(mob/user)
if(!user.incapacitated())
src.flipped = !src.flipped
if(src.flipped)
icon_state = "[item_color]soft_flipped"
to_chat(user, "<span class='notice'>You flip the hat backwards.</span>")
else
icon_state = "[item_color]soft"
to_chat(user, "<span class='notice'>You flip the hat back in normal position.</span>")
usr.update_inv_head() //so our mob-overlays update
/obj/item/clothing/head/soft/examine(mob/user)
..()
to_chat(user, "<span class='notice'>Alt-click the cap to flip it [flipped ? "forwards" : "backwards"].</span>")
/obj/item/clothing/head/soft/red
name = "red cap"
desc = "It's a baseball hat in a tasteless red colour."
icon_state = "redsoft"
item_color = "red"
dog_fashion = null
/obj/item/clothing/head/soft/blue
name = "blue cap"
desc = "It's a baseball hat in a tasteless blue colour."
icon_state = "bluesoft"
item_color = "blue"
dog_fashion = null
/obj/item/clothing/head/soft/green
name = "green cap"
desc = "It's a baseball hat in a tasteless green colour."
icon_state = "greensoft"
item_color = "green"
dog_fashion = null
/obj/item/clothing/head/soft/yellow
name = "yellow cap"
desc = "It's a baseball hat in a tasteless yellow colour."
icon_state = "yellowsoft"
item_color = "yellow"
dog_fashion = null
/obj/item/clothing/head/soft/grey
name = "grey cap"
desc = "It's a baseball hat in a tasteful grey colour."
icon_state = "greysoft"
item_color = "grey"
dog_fashion = null
/obj/item/clothing/head/soft/orange
name = "orange cap"
desc = "It's a baseball hat in a tasteless orange colour."
icon_state = "orangesoft"
item_color = "orange"
dog_fashion = null
/obj/item/clothing/head/soft/mime
name = "white cap"
desc = "It's a baseball hat in a tasteless white colour."
icon_state = "mimesoft"
item_color = "mime"
dog_fashion = null
/obj/item/clothing/head/soft/purple
name = "purple cap"
desc = "It's a baseball hat in a tasteless purple colour."
icon_state = "purplesoft"
item_color = "purple"
dog_fashion = null
/obj/item/clothing/head/soft/black
name = "black cap"
desc = "It's a baseball hat in a tasteless black colour."
icon_state = "blacksoft"
item_color = "black"
dog_fashion = null
/obj/item/clothing/head/soft/rainbow
name = "rainbow cap"
desc = "It's a baseball hat in a bright rainbow of colors."
icon_state = "rainbowsoft"
item_color = "rainbow"
dog_fashion = null
/obj/item/clothing/head/soft/sec
name = "security cap"
desc = "It's a robust baseball hat in tasteful red colour."
icon_state = "secsoft"
item_color = "sec"
armor = list(melee = 30, bullet = 25, laser = 25, energy = 10, bomb = 25, bio = 0, rad = 0, fire = 20, acid = 50)
strip_delay = 60
dog_fashion = null
/obj/item/clothing/head/soft/emt
name = "EMT cap"
desc = "It's a baseball hat with a dark turquoise color and a reflective cross on the top."
icon_state = "emtsoft"
item_color = "emt"
dog_fashion = null
+1 -2
View File
@@ -23,8 +23,7 @@ obj/item/clothing/mask/breath/suicide_act(mob/living/carbon/user)
/obj/item/clothing/mask/breath/AltClick(mob/user)
..()
if(!user.canUseTopic(src, be_close=TRUE))
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
else
adjustmask(user)
@@ -40,6 +40,63 @@
icon_state = "fake-moustache"
flags_inv = HIDEFACE
/obj/item/clothing/mask/fakemoustache/italian
name = "italian moustache"
desc = "Made from authentic Italian moustache hairs. Gives the wearer an irresistable urge to gesticulate wildly."
/obj/item/clothing/mask/fakemoustache/italian/speechModification(message)
if(copytext(message, 1, 2) != "*")
message = " [message] "
message = replacetext(message," mom "," mamma ")
message = replacetext(message," dad "," pappa ")
message = replacetext(message," baby ",pick(" bambino "," little sausage roll "))
message = replacetext(message,"spicy","a-spicy")
message = replacetext(message,"I'm","I'm-a")
message = replacetext(message," friend "," enemy-a ")
message = replacetext(message," enemy "," friend-a ")
message = replacetext(message,"traitor","mafioso")
message = replacetext(message," operative "," greek ")
message = replacetext(message," op "," greek ")
message = replacetext(message," ops "," greeks")
message = replacetext(message," operative "," greek")
message = replacetext(message," operatives "," greeks")
message = replacetext(message," nuke"," spiciest-a meatball")
message = replacetext(message," good"," molto bene")
message = replacetext(message," why"," for-a what reason")
message = replacetext(message," my "," my-a ")
message = replacetext(message,"it's","it's-a")
message = replacetext(message," bad"," molto male")
message = replacetext(message," sing "," sing-a ")
message = replacetext(message," cook "," cook-a ")
message = replacetext(message," want "," want-a ")
message = replacetext(message," what's "," what's-a ")
message = replacetext(message," shitcurity"," carabinieri")
message = replacetext(message," shitsec"," carabinieri")
message = replacetext(message," and "," and-a ")
message = replacetext(message," am "," am-a ")
message = replacetext(message," assistant "," goombah ")
message = replacetext(message," greytide "," curvisti ")
message = replacetext(message," greytider "," curvisti ")
message = replacetext(message," captain "," capitano ")
message = replacetext(message," sec "," polizia ")
message = replacetext(message," security "," polizia ")
message = replacetext(message,"cheese",pick("parmesano","gorgonzola"))
message = replacetext(message," meat",pick(" pepperoni"," prosciutto"))
message = replacetext(message,"who's","who's-a")
message = replacetext(message,"hello",pick("ciao","buongiorno"))
message = replacetext(message," bye ",pick(" ciao "," arrivederci "))
message = replacetext(message,"thing","thing-a")
message = replacetext(message,"whose","whose-a")
message = replacetext(message,"thanks","grazie")
message = replacetext(message," wine"," vino")
message = replacetext(message,"could","could-a")
message = replacetext(message," use"," use-a")
message = replacetext(message," make"," make-a")
message = replacetext(message,"spaghetti", "SPAGHETT")
if(prob(3))
message += pick(" Ravioli, ravioli, give me the formuoli!"," Mamma-mia!"," Mamma-mia! That's a spicy meat-ball!", " La la la la la funiculi funicula!")
return trim(message)
/obj/item/clothing/mask/joy
name = "joy mask"
desc = "Express your happiness or hide your sorrows with this laughing face with crying tears of joy cutout."
@@ -207,7 +207,7 @@
cooldown = world.time + cooldowntime
activating = 0
/obj/item/clothing/suit/space/chronos/proc/deactivate(force = 0, silent = 0)
/obj/item/clothing/suit/space/chronos/proc/deactivate(force = 0, silent = FALSE)
if(activated && (!teleporting || force))
activating = 1
var/mob/living/carbon/human/user = src.loc
+1 -2
View File
@@ -93,8 +93,7 @@
/obj/item/clothing/suit/toggle/AltClick(mob/user)
..()
if(!user.canUseTopic(src, be_close=TRUE))
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
else
suit_toggle(user)
+1 -1
View File
@@ -69,7 +69,7 @@
return
/obj/item/clothing/accessory/AltClick(mob/user)
if(user.canUseTopic(src, be_close=TRUE))
if(istype(user) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
if(initial(above_suit))
above_suit = !above_suit
to_chat(user, "[src] will be worn [above_suit ? "above" : "below"] your suit.")
+18 -8
View File
@@ -105,22 +105,33 @@
/datum/personal_crafting/proc/check_tools(mob/user, datum/crafting_recipe/R, list/contents)
if(!R.tools.len)
return 1
return TRUE
var/list/possible_tools = list()
var/list/present_qualities = list()
for(var/obj/item/I in user.contents)
if(istype(I, /obj/item/storage))
for(var/obj/item/SI in I.contents)
possible_tools += SI.type
if(SI.tool_behaviour)
present_qualities.Add(SI.tool_behaviour)
possible_tools += I.type
if(I.tool_behaviour)
present_qualities.Add(I.tool_behaviour)
possible_tools += contents
main_loop:
for(var/A in R.tools)
for(var/I in possible_tools)
if(ispath(I,A))
continue main_loop
return 0
return 1
if(A in present_qualities)
continue
else
for(var/I in possible_tools)
if(ispath(I, A))
continue main_loop
return FALSE
return TRUE
/datum/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R)
var/list/contents = get_surroundings(user)
@@ -401,8 +412,7 @@
data["catalyst_text"] = catalyst_text
for(var/a in R.tools)
var/atom/A = a //cheat-typecast
tool_text += " [R.tools[A]] [initial(A.name)],"
tool_text += " [a],"
tool_text = replacetext(tool_text,",","",-1)
data["tool_text"] = tool_text
+15 -16
View File
@@ -16,7 +16,7 @@
result = /obj/item/gun
reqs = list(/obj/item/gun = 1)
parts = list(/obj/item/gun = 1)
tools = list(/obj/item/weldingtool, /obj/item/screwdriver, /obj/item/wirecutters)
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
time = 50
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
@@ -134,7 +134,7 @@
/obj/item/gun/energy/e_gun/advtaser = 1,
/obj/item/stock_parts/cell = 1,
/obj/item/device/assembly/prox_sensor = 1)
tools = list(/obj/item/weldingtool, /obj/item/screwdriver)
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER)
time = 60
category = CAT_ROBOT
@@ -146,7 +146,7 @@
/obj/item/melee/baton = 1,
/obj/item/device/assembly/prox_sensor = 1,
/obj/item/bodypart/r_arm/robot = 1)
tools = list(/obj/item/weldingtool)
tools = list(TOOL_WELDER)
time = 60
category = CAT_ROBOT
@@ -192,8 +192,7 @@
/datum/crafting_recipe/improvised_pneumatic_cannon //Pretty easy to obtain but
name = "Pneumatic Cannon"
result = /obj/item/pneumatic_cannon/ghetto
tools = list(/obj/item/weldingtool,
/obj/item/wrench)
tools = list(TOOL_WELDER, TOOL_WRENCH)
reqs = list(/obj/item/stack/sheet/metal = 4,
/obj/item/stack/packageWrap = 8,
/obj/item/pipe = 2)
@@ -209,7 +208,7 @@
/obj/item/stack/rods = 1)
parts = list(/obj/item/device/assembly/igniter = 1,
/obj/item/weldingtool = 1)
tools = list(/obj/item/screwdriver)
tools = list(TOOL_SCREWDRIVER)
time = 10
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
@@ -220,7 +219,7 @@
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
/obj/item/rcd_ammo = 1,
/obj/item/stock_parts/manipulator = 2)
tools = list(/obj/item/screwdriver)
tools = list(TOOL_SCREWDRIVER)
time = 5
category = CAT_WEAPONRY
subcategory = CAT_AMMO
@@ -231,7 +230,7 @@
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
/obj/item/stock_parts/capacitor/adv = 2,
/obj/item/stock_parts/micro_laser/ultra = 1)
tools = list(/obj/item/screwdriver)
tools = list(TOOL_SCREWDRIVER)
time = 5
category = CAT_WEAPONRY
subcategory = CAT_AMMO
@@ -240,7 +239,7 @@
name = "Dragonsbreath Shell"
result = /obj/item/ammo_casing/shotgun/dragonsbreath
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1, /datum/reagent/phosphorus = 5)
tools = list(/obj/item/screwdriver)
tools = list(TOOL_SCREWDRIVER)
time = 5
category = CAT_WEAPONRY
subcategory = CAT_AMMO
@@ -252,7 +251,7 @@
/datum/reagent/glycerol = 5,
/datum/reagent/toxin/acid = 5,
/datum/reagent/toxin/acid/fluacid = 5)
tools = list(/obj/item/screwdriver)
tools = list(TOOL_SCREWDRIVER)
time = 5
category = CAT_WEAPONRY
subcategory = CAT_AMMO
@@ -263,7 +262,7 @@
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
/obj/item/stock_parts/micro_laser/ultra = 1,
/obj/item/stock_parts/subspace/crystal = 1)
tools = list(/obj/item/screwdriver)
tools = list(TOOL_SCREWDRIVER)
time = 5
category = CAT_WEAPONRY
subcategory = CAT_AMMO
@@ -275,7 +274,7 @@
/obj/item/stack/sheet/metal = 1,
/obj/item/stack/cable_coil = 1,
/datum/reagent/fuel = 10)
tools = list(/obj/item/screwdriver)
tools = list(TOOL_SCREWDRIVER)
time = 5
category = CAT_WEAPONRY
subcategory = CAT_AMMO
@@ -286,7 +285,7 @@
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
/obj/item/stock_parts/capacitor/adv = 1,
/obj/item/stock_parts/micro_laser/high = 1)
tools = list(/obj/item/screwdriver)
tools = list(TOOL_SCREWDRIVER)
time = 5
category = CAT_WEAPONRY
subcategory = CAT_AMMO
@@ -298,7 +297,7 @@
/obj/item/pipe = 1,
/obj/item/weaponcrafting/stock = 1,
/obj/item/stack/packageWrap = 5)
tools = list(/obj/item/screwdriver)
tools = list(TOOL_SCREWDRIVER)
time = 100
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
@@ -309,7 +308,7 @@
reqs = list(/obj/item/circular_saw = 1,
/obj/item/stack/cable_coil = 3,
/obj/item/stack/sheet/plasteel = 5)
tools = list(/obj/item/weldingtool)
tools = list(TOOL_WELDER)
time = 50
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
@@ -590,7 +589,7 @@
name = "Makeshift Rapid Cable Layer"
result = /obj/item/twohanded/rcl/ghetto
time = 40
tools = list(/obj/item/weldingtool, /obj/item/screwdriver, /obj/item/wrench)
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WRENCH)
reqs = list(/obj/item/stack/sheet/metal = 15)
category = CAT_MISC
+4 -4
View File
@@ -1,8 +1,10 @@
GLOBAL_VAR_INIT(total_runtimes, 0)
GLOBAL_VAR_INIT(total_runtimes, GLOB.total_runtimes || 0)
GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
#ifdef DEBUG
/world/Error(exception/E, datum/e_src)
GLOB.total_runtimes++
if(!istype(E)) //Something threw an unusual exception
log_world("\[[time_stamp()]] Uncaught exception: [E]")
return ..()
@@ -32,8 +34,6 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
if(!error_last_seen) // A runtime is occurring too early in start-up initialization
return ..()
GLOB.total_runtimes++
var/erroruid = "[E.file][E.line]"
var/last_seen = error_last_seen[erroruid]
var/cooldown = error_cooldown[erroruid] || 0
@@ -54,7 +54,7 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
var/configured_error_cooldown
var/configured_error_limit
var/configured_error_silence_time
if(config)
if(config && config.entries)
configured_error_cooldown = CONFIG_GET(number/error_cooldown)
configured_error_limit = CONFIG_GET(number/error_limit)
configured_error_silence_time = CONFIG_GET(number/error_silence_time)
+23
View File
@@ -0,0 +1,23 @@
/datum/round_event_control/heart_attack
name = "Random Heart Attack"
typepath = /datum/round_event/heart_attack
weight = 20
max_occurrences = 2
earliest_start = 12000
min_players = 40 // To avoid shafting lowpop
/datum/round_event/heart_attack/start()
var/list/heart_attack_contestants = list()
for(var/mob/living/carbon/H in shuffle(GLOB.player_list))
if(!H.client || H.stat == DEAD || H.InCritical() || !H.can_heartattack() || H.has_status_effect(STATUS_EFFECT_EXERCISED) || (/datum/disease/heart_failure in H.viruses) || H.undergoing_cardiac_arrest())
continue
if(H.satiety <= -100)
heart_attack_contestants[H] = 1.15
else
heart_attack_contestants[H] = 1
if(LAZYLEN(heart_attack_contestants))
var/mob/living/carbon/C = pickweight(heart_attack_contestants)
var/datum/disease/D = new /datum/disease/heart_failure
C.ForceContractDisease(D)
notify_ghosts("[C] is beginning to have a heart attack!", enter_link="<a href=?src=[REF(C)];orbit=1>(Click to orbit)</a>", source=C, action=NOTIFY_ORBIT)
+6 -1
View File
@@ -18,7 +18,7 @@
H.put_in_hands(new /obj/item/valentine)
var/obj/item/storage/backpack/b = locate() in H.contents
new /obj/item/reagent_containers/food/snacks/candyheart(b)
new /obj/item/storage/fancy/heart_box(b)
var/list/valentines = list()
for(var/mob/living/M in GLOB.player_list)
@@ -137,8 +137,13 @@
/obj/item/valentine/attackby(obj/item/W, mob/user, params)
..()
if(istype(W, /obj/item/pen) || istype(W, /obj/item/toy/crayon))
if(!user.is_literate())
to_chat(user, "<span class='notice'>You scribble illegibly on [src]!</span>")
return
var/recipient = stripped_input(user, "Who is receiving this valentine?", "To:", null , 20)
var/sender = stripped_input(user, "Who is sending this valentine?", "From:", null , 20)
if(!user.canUseTopic(src, BE_CLOSE))
return
if(recipient && sender)
name = "valentine - To: [recipient] From: [sender]"
+1 -1
View File
@@ -31,7 +31,7 @@
var/list/potential = list()
for(var/mob/living/simple_animal/L in GLOB.alive_mob_list)
var/turf/T = get_turf(L)
if(!is_station_level(T.z))
if(!T || !is_station_level(T.z))
continue
if(!(L in GLOB.player_list) && !L.mind)
potential += L
+3 -1
View File
@@ -21,7 +21,9 @@
/datum/round_event/spider_infestation/start()
var/list/vents = list()
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in world)
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in GLOB.machines)
if(QDELETED(temp_vent))
continue
if(is_station_level(temp_vent.loc.z) && !temp_vent.welded)
var/datum/pipeline/temp_vent_parent = temp_vent.parents[1]
if(temp_vent_parent.other_atmosmch.len > 20)
+1 -1
View File
@@ -2,7 +2,7 @@
name = "Clogged Vents"
typepath = /datum/round_event/vent_clog
weight = 25
max_occurrences = 1
max_occurrences = 0
min_players = 50
/datum/round_event/vent_clog
+14 -11
View File
@@ -28,12 +28,15 @@
var/mob/living/last_holder
var/mob/living/new_holder
var/list/color_altered_mobs = list()
var/datum/callback/roundend_callback
resistance_flags = FIRE_PROOF | ACID_PROOF
var/quiet = FALSE
/obj/item/greentext/New()
..()
/obj/item/greentext/Initialize(mapload)
. = ..()
GLOB.poi_list |= src
roundend_callback = CALLBACK(src,.proc/check_winner)
SSticker.OnRoundend(roundend_callback)
/obj/item/greentext/equipped(mob/living/user as mob)
to_chat(user, "<font color='green'>So long as you leave this place with greentext in hand you know will be happy...</font>")
@@ -57,20 +60,19 @@
STOP_PROCESSING(SSobj, src)
..()
/obj/item/greentext/process()
if(new_holder && is_centcom_level(new_holder.z))//you're winner!
/obj/item/greentext/proc/check_winner()
if(!new_holder)
return
if(is_centcom_level(new_holder.z))//you're winner!
to_chat(new_holder, "<font color='green'>At last it feels like victory is assured!</font>")
new_holder.mind.special_role = "winner"
var/datum/objective/O = new /datum/objective("Succeed")
O.completed = 1 //YES!
O.owner = new_holder.mind
new_holder.mind.objectives += O
new_holder.mind.add_antag_datum(/datum/antagonist/auto_custom)
new_holder.mind.add_antag_datum(/datum/antagonist/greentext)
new_holder.log_message("<font color='green'>Won with greentext!!!</font>", INDIVIDUAL_ATTACK_LOG)
color_altered_mobs -= new_holder
resistance_flags |= ON_FIRE
qdel(src)
/obj/item/greentext/process()
if(last_holder && last_holder != new_holder) //Somehow it was swiped without ever getting dropped
to_chat(last_holder, "<span class='warning'>A sudden wave of failure washes over you...</span>")
last_holder.add_atom_colour("#FF0000", ADMIN_COLOUR_PRIORITY)
@@ -80,7 +82,7 @@
if(!(resistance_flags & ON_FIRE) && !force)
return QDEL_HINT_LETMELIVE
. = ..()
SSticker.round_end_events -= roundend_callback
GLOB.poi_list.Remove(src)
for(var/i in GLOB.player_list)
var/mob/M = i
@@ -93,6 +95,7 @@
// can't skip the mob check as it also does the decolouring
if(!quiet)
to_chat(M, message)
. = ..()
/obj/item/greentext/quiet
quiet = TRUE
+3 -3
View File
@@ -239,10 +239,10 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
xeno = new(pump.loc,target)
sleep(10)
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1)
xeno.throw_at(target,7,1, xeno, FALSE, TRUE)
sleep(10)
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(pump,7,1, spin = 0, diagonals_first = 1)
xeno.throw_at(pump,7,1, xeno, FALSE, TRUE)
sleep(10)
var/xeno_name = xeno.name
to_chat(target, "<span class='notice'>[xeno_name] begins climbing into the ventilation system...</span>")
@@ -1114,7 +1114,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
sleep(rand(70,90))
target.set_screwyhud(SCREWYHUD_NONE)
target.SetKnockdown(0)
target.silent = 0
target.silent = FALSE
qdel(src)
/datum/hallucination/fire
@@ -394,7 +394,6 @@
container_type = NONE
spillable = FALSE
isGlass = FALSE
grind_results = list("aluminum" = 10)
/obj/item/reagent_containers/food/drinks/soda_cans/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] is trying to eat \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -223,6 +223,8 @@
slice.name = "slice of [name]"
if(desc != initial(desc))
slice.desc = "[desc]"
if(foodtype != initial(foodtype))
slice.foodtype = foodtype //if something happens that overrode our food type, make sure the slice carries that over
/obj/item/reagent_containers/food/snacks/proc/generate_trash(atom/location)
if(trash)
+14 -13
View File
@@ -15,12 +15,21 @@
name = "egg"
desc = "An egg!"
icon_state = "egg"
list_reagents = list("nutriment" = 1)
list_reagents = list("eggyolk" = 5)
cooked_type = /obj/item/reagent_containers/food/snacks/boiledegg
filling_color = "#F0E68C"
tastes = list("egg" = 1)
foodtype = MEAT
grind_results = list("eggyolk" = 5)
grind_results = list()
/obj/item/reagent_containers/food/snacks/egg/gland
desc = "An egg! It looks weird..."
/obj/item/reagent_containers/food/snacks/egg/gland/Initialize()
. = ..()
reagents.add_reagent(get_random_reagent_id(), 15)
var/color = mix_color_from_reagents(reagents.reagent_list)
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
/obj/item/reagent_containers/food/snacks/egg/throw_impact(atom/hit_atom)
if(!..()) //was it caught by a mob?
@@ -30,7 +39,7 @@
qdel(src)
/obj/item/reagent_containers/food/snacks/egg/attackby(obj/item/W, mob/user, params)
if(istype( W, /obj/item/toy/crayon ))
if(istype(W, /obj/item/toy/crayon))
var/obj/item/toy/crayon/C = W
var/clr = C.item_color
@@ -38,7 +47,7 @@
to_chat(usr, "<span class='notice'>[src] refuses to take on this colour!</span>")
return
to_chat(usr, "<span class='notice'>You colour [src] [clr].</span>")
to_chat(usr, "<span class='notice'>You colour [src] with [W].</span>")
icon_state = "egg-[clr]"
item_color = clr
else
@@ -47,42 +56,34 @@
/obj/item/reagent_containers/food/snacks/egg/blue
icon_state = "egg-blue"
item_color = "blue"
tastes = list("egg" = 4, "the back of class" = 1)
/obj/item/reagent_containers/food/snacks/egg/green
icon_state = "egg-green"
item_color = "green"
tastes = list("egg" = 4, "the back of class" = 1)
/obj/item/reagent_containers/food/snacks/egg/mime
icon_state = "egg-mime"
item_color = "mime"
tastes = list("egg" = 4, "the back of class" = 1)
/obj/item/reagent_containers/food/snacks/egg/orange
icon_state = "egg-orange"
item_color = "orange"
tastes = list("egg" = 4, "the back of class" = 1)
/obj/item/reagent_containers/food/snacks/egg/purple
icon_state = "egg-purple"
item_color = "purple"
tastes = list("egg" = 4, "the back of class" = 1)
/obj/item/reagent_containers/food/snacks/egg/rainbow
icon_state = "egg-rainbow"
item_color = "rainbow"
tastes = list("egg" = 4, "the back of class" = 1)
/obj/item/reagent_containers/food/snacks/egg/red
icon_state = "egg-red"
item_color = "red"
tastes = list("egg" = 4, "the back of class" = 1)
/obj/item/reagent_containers/food/snacks/egg/yellow
icon_state = "egg-yellow"
item_color = "yellow"
tastes = list("egg" = 4, "the back of class" = 1)
/obj/item/reagent_containers/food/snacks/friedegg
name = "fried egg"
@@ -560,3 +560,12 @@
filling_color = "#F6CB0B"
tastes = list("pineapple" = 1)
foodtype = FRUIT
/obj/item/reagent_containers/food/snacks/tinychocolate
name = "chocolate"
desc = "A tiny and sweet chocolate."
icon_state = "tiny_chocolate"
list_reagents = list("nutriment" = 1, "sugar" = 1, "cocoa" = 1)
filling_color = "#A0522D"
tastes = list("chocolate" = 1)
foodtype = JUNKFOOD | SUGAR
@@ -16,7 +16,7 @@
foodtype = GRAIN | DAIRY | VEGETABLES
/obj/item/reagent_containers/food/snacks/pizza/margherita
name = "margherita"
name = "pizza margherita"
desc = "The most cheezy pizza in galaxy."
icon_state = "pizzamargherita"
slice_path = /obj/item/reagent_containers/food/snacks/pizzaslice/margherita
@@ -62,7 +62,7 @@
"[user] starts to fix part of the microwave.", \
"<span class='notice'>You start to fix part of the microwave...</span>" \
)
if (do_after(user,20*O.toolspeed, target = src))
if (O.use_tool(src, user, 20))
user.visible_message( \
"[user] fixes part of the microwave.", \
"<span class='notice'>You fix part of the microwave.</span>" \
@@ -73,7 +73,7 @@
"[user] starts to fix part of the microwave.", \
"<span class='notice'>You start to fix part of the microwave...</span>" \
)
if (do_after(user,20*O.toolspeed, target = src))
if (O.use_tool(src, user, 20))
user.visible_message( \
"[user] fixes the microwave.", \
"<span class='notice'>You fix the microwave.</span>" \
@@ -169,7 +169,7 @@
interact(user)
/obj/machinery/microwave/AltClick(mob/user)
if(user.canUseTopic(src, be_close=TRUE) && !(operating || broken > 0 || panel_open || !anchored || dirty == 100))
if(user.canUseTopic(src, BE_CLOSE) && !(operating || broken > 0 || panel_open || !anchored || dirty == 100))
cook()
/*******************
+48 -1
View File
@@ -16,6 +16,7 @@
righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
var/open = FALSE
var/can_open_on_fall = TRUE //if FALSE, this pizza box will never open if it falls from a stack
var/boxtag = ""
var/list/boxes = list()
@@ -196,8 +197,13 @@
to_chat(user, "<span class='notice'>[src] already has a bomb in it!</span>")
else if(istype(I, /obj/item/pen))
if(!open)
if(!user.is_literate())
to_chat(user, "<span class='notice'>You scribble illegibly on [src]!</span>")
return
var/obj/item/pizzabox/box = boxes.len ? boxes[boxes.len] : src
box.boxtag += stripped_input(user, "Write on [box]'s tag:", box, "", 30)
if(!user.canUseTopic(src, BE_CLOSE))
return
to_chat(user, "<span class='notice'>You write with [I] on [src].</span>")
update_icon()
return
@@ -239,7 +245,7 @@
var/obj/item/pizzabox/P = V
var/fall_dir = pick(GLOB.alldirs)
step(P, fall_dir)
if(P.pizza && prob(50)) //rip pizza
if(P.pizza && P.can_open_on_fall && prob(50)) //rip pizza
P.open = TRUE
P.pizza.forceMove(get_turf(P))
fall_dir = pick(GLOB.alldirs)
@@ -290,3 +296,44 @@
. = ..()
pizza = new /obj/item/reagent_containers/food/snacks/pizza/pineapple(src)
boxtag = "Honolulu Chew"
//An anomalous pizza box that, when opened, produces the opener's favorite kind of pizza.
/obj/item/pizzabox/infinite
resistance_flags = FIRE_PROOF | LAVA_PROOF | ACID_PROOF //hard to destroy
can_open_on_fall = FALSE
var/list/pizza_types = list(
/obj/item/reagent_containers/food/snacks/pizza/meat = 1,
/obj/item/reagent_containers/food/snacks/pizza/mushroom = 1,
/obj/item/reagent_containers/food/snacks/pizza/margherita = 1,
/obj/item/reagent_containers/food/snacks/pizza/sassysage = 0.8,
/obj/item/reagent_containers/food/snacks/pizza/vegetable = 0.8,
/obj/item/reagent_containers/food/snacks/pizza/pineapple = 0.5,
/obj/item/reagent_containers/food/snacks/pizza/donkpocket = 0.3,
/obj/item/reagent_containers/food/snacks/pizza/dank = 0.1) //pizzas here are weighted by chance to be someone's favorite
var/static/list/pizza_preferences
/obj/item/pizzabox/infinite/Initialize()
. = ..()
if(!pizza_preferences)
pizza_preferences = list()
/obj/item/pizzabox/infinite/examine(mob/user)
..()
if(isobserver(user))
to_chat(user, "<span class='deadsay'>This pizza box is anomalous, and will produce infinite pizza.</span>")
/obj/item/pizzabox/infinite/attack_self(mob/living/user)
QDEL_NULL(pizza)
if(ishuman(user))
attune_pizza(user)
. = ..()
/obj/item/pizzabox/infinite/proc/attune_pizza(mob/living/carbon/human/noms) //tonight on "proc names I never thought I'd type"
if(!pizza_preferences[noms.ckey])
pizza_preferences[noms.ckey] = pickweight(pizza_types)
if(noms.mind && noms.mind.assigned_role == "Botanist")
pizza_preferences[noms.ckey] = /obj/item/reagent_containers/food/snacks/pizza/dank
var/obj/item/pizza_type = pizza_preferences[noms.ckey]
pizza = new pizza_type (src)
pizza.foodtype = noms.dna.species.liked_food //it's our favorite!
@@ -441,7 +441,7 @@
name = "Chocolate Pudding"
id = "chocolatepudding"
results = list("chocolatepudding" = 20)
required_reagents = list("cocoa" = 5, "milk" = 5, "eggyolk" = 5)
required_reagents = list("chocolate_milk" = 10, "eggyolk" = 5)
/datum/chemical_reaction/vanillapudding
name = "Vanilla Pudding"
@@ -178,7 +178,7 @@
/obj/item/reagent_containers/food/snacks/deadmouse = 1
)
result = /obj/item/reagent_containers/food/snacks/kebab/rat
category = CAT_MEAT
subcategory = CAT_MEAT
/datum/crafting_recipe/food/doubleratkebab
name = "Double Rat Kebab"
@@ -187,7 +187,7 @@
/obj/item/reagent_containers/food/snacks/deadmouse = 2
)
result = /obj/item/reagent_containers/food/snacks/kebab/rat/double
category = CAT_MEAT
subcategory = CAT_MEAT
/datum/crafting_recipe/food/ricepork
name = "Rice and pork"
+6 -3
View File
@@ -117,7 +117,7 @@
set name = "Flip Card"
set category = "Object"
set src in range(1)
if(!usr.canUseTopic(src,1))
if(!ishuman(usr) || !usr.canUseTopic(src, BE_CLOSE))
return
if(!flipped)
name = "CAS card"
@@ -127,7 +127,7 @@
update_icon()
/obj/item/toy/cards/singlecard/cas/AltClick(mob/living/user)
if(!user.canUseTopic(src,1))
if(!ishuman(user) || !user.canUseTopic(src, BE_CLOSE))
return
Flip()
@@ -139,11 +139,14 @@
/obj/item/toy/cards/singlecard/cas/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/pen))
if(!user.is_literate())
to_chat(user, "<span class='notice'>You scribble illegibly on [src]!</span>")
return
if(!blank)
to_chat(user, "You cannot write on that card.")
return
var/cardtext = stripped_input(user, "What do you wish to write on the card?", "Card Writing", "", 50)
if(!cardtext)
if(!cardtext || !user.canUseTopic(src, BE_CLOSE))
return
name = cardtext
buffertext = cardtext
+3 -1
View File
@@ -19,7 +19,9 @@
/obj/item/reagent_containers/food/snacks/grown/Initialize(mapload, obj/item/seeds/new_seed)
. = ..()
tastes = list("[name]" = 1) // apples taste of apple, silly.
if(!tastes)
tastes = list("[name]" = 1)
if(new_seed)
seed = new_seed.Copy()
else if(ispath(seed))
@@ -8,6 +8,7 @@
filling_color = "#008000"
bitesize_mod = 2
foodtype = VEGETABLES
tastes = list("ambrosia" = 1)
// Ambrosia Vulgaris
/obj/item/seeds/ambrosia
+1
View File
@@ -25,6 +25,7 @@
bitesize = 100 // Always eat the apple in one bite
foodtype = FRUIT
juice_results = list("applejuice" = 0)
tastes = list("apple" = 1)
// Posioned Apple
/obj/item/seeds/apple/poisoned
+1
View File
@@ -108,6 +108,7 @@
item_state = "bluespace_peel"
trash = /obj/item/grown/bananapeel/bluespace
filling_color = "#0000FF"
tastes = list("banana" = 1)
/obj/item/grown/bananapeel/bluespace
seed = /obj/item/seeds/banana/bluespace
+2
View File
@@ -27,6 +27,7 @@
bitesize_mod = 2
foodtype = VEGETABLES
grind_results = list("soymilk" = 0)
tastes = list("soy" = 1)
// Koibean
/obj/item/seeds/soya/koi
@@ -49,3 +50,4 @@
filling_color = "#F0E68C"
bitesize_mod = 2
foodtype = VEGETABLES
tastes = list("koi" = 1)
+10 -2
View File
@@ -27,6 +27,7 @@
bitesize_mod = 2
foodtype = FRUIT
juice_results = list("berryjuice" = 0)
tastes = list("berry" = 1)
// Poison Berries
/obj/item/seeds/berry/poison
@@ -43,11 +44,12 @@
/obj/item/reagent_containers/food/snacks/grown/berries/poison
seed = /obj/item/seeds/berry/poison
name = "bunch of poison-berries"
desc = "Taste so good, you could die!"
desc = "Taste so good, you might die!"
icon_state = "poisonberrypile"
filling_color = "#C71585"
foodtype = FRUIT | TOXIC
juice_results = list("poisonberryjuice" = 0)
tastes = list("poison-berry" = 1)
// Death Berries
/obj/item/seeds/berry/death
@@ -66,10 +68,11 @@
/obj/item/reagent_containers/food/snacks/grown/berries/death
seed = /obj/item/seeds/berry/death
name = "bunch of death-berries"
desc = "Taste so good, you could die!"
desc = "Taste so good, you will die!"
icon_state = "deathberrypile"
filling_color = "#708090"
foodtype = FRUIT | TOXIC
tastes = list("death-berry" = 1)
// Glow Berries
/obj/item/seeds/berry/glow
@@ -93,6 +96,7 @@
icon_state = "glowberrypile"
filling_color = "#7CFC00"
foodtype = FRUIT
tastes = list("glow-berry" = 1)
// Cherries
/obj/item/seeds/cherry
@@ -124,6 +128,7 @@
bitesize_mod = 2
foodtype = FRUIT
grind_results = list("cherryjelly" = 0)
tastes = list("cherry" = 1)
// Blue Cherries
/obj/item/seeds/cherry/blue
@@ -146,6 +151,7 @@
bitesize_mod = 2
foodtype = FRUIT
grind_results = list("bluecherryjelly" = 0)
tastes = list("blue cherry" = 1)
// Grapes
/obj/item/seeds/grape
@@ -178,6 +184,7 @@
bitesize_mod = 2
foodtype = FRUIT
juice_results = list("grapejuice" = 0)
tastes = list("grape" = 1)
// Green Grapes
/obj/item/seeds/grape/green
@@ -196,3 +203,4 @@
name = "bunch of green grapes"
icon_state = "greengrapes"
filling_color = "#7FFF00"
tastes = list("green grape" = 1)
@@ -91,6 +91,7 @@
filling_color = "#00FF00"
bitesize_mod = 2
foodtype = VEGETABLES //i dont really know what else weed could be to be honest
tastes = list("cannabis" = 1)
/obj/item/reagent_containers/food/snacks/grown/cannabis/rainbow
@@ -23,6 +23,7 @@
bitesize_mod = 2
foodtype = GRAIN
grind_results = list("flour" = 0)
tastes = list("wheat" = 1)
// Oat
/obj/item/seeds/wheat/oat
@@ -44,6 +45,7 @@
bitesize_mod = 2
foodtype = GRAIN
grind_results = list("flour" = 0)
tastes = list("oat" = 1)
// Rice
/obj/item/seeds/wheat/rice
@@ -66,6 +68,7 @@
bitesize_mod = 2
foodtype = GRAIN
grind_results = list("rice" = 0)
tastes = list("rice" = 1)
//Meatwheat - grows into synthetic meat
/obj/item/seeds/wheat/meat
@@ -87,6 +90,7 @@
seed = /obj/item/seeds/wheat/meat
foodtype = MEAT | GRAIN
grind_results = list("flour" = 0, "blood" = 0)
tastes = list("meatwheat" = 1)
/obj/item/reagent_containers/food/snacks/grown/meatwheat/attack_self(mob/living/user)
user.visible_message("<span class='notice'>[user] crushes [src] into meat.</span>", "<span class='notice'>You crush [src] into something that resembles meat.</span>")
@@ -26,6 +26,7 @@
filling_color = "#FFD700"
bitesize_mod = 2
foodtype = FRUIT
tastes = list("cocoa" = 1)
// Vanilla Pod
/obj/item/seeds/cocoapod/vanillapod
@@ -46,3 +47,4 @@
icon_state = "vanillapod"
filling_color = "#FFD700"
foodtype = FRUIT
tastes = list("vanilla" = 1)
+1
View File
@@ -26,6 +26,7 @@
bitesize_mod = 2
foodtype = VEGETABLES
juice_results = list("corn_starch" = 0)
tastes = list("corn" = 1)
/obj/item/grown/corncob
name = "corn cob"
+1 -1
View File
@@ -37,7 +37,7 @@
/obj/item/reagent_containers/food/snacks/grown/shell/eggy
seed = /obj/item/seeds/eggplant/eggy
name = "Egg-plant"
name = "egg-plant"
desc = "There MUST be a chicken inside."
icon_state = "eggyplant"
trash = /obj/item/reagent_containers/food/snacks/egg
+1
View File
@@ -103,3 +103,4 @@
filling_color = "#6B8E23"
bitesize_mod = 2
foodtype = VEGETABLES | GROSS
tastes = list("kudzu" = 1)
+1
View File
@@ -111,6 +111,7 @@
trash = /obj/item/gun/ballistic/revolver
bitesize_mod = 2
foodtype = FRUIT
tastes = list("gunpowder" = 1)
//Cherry Bombs
/obj/item/seeds/cherry/bomb
+3 -1
View File
@@ -277,6 +277,7 @@
icon_state = "glowcap"
filling_color = "#00FA9A"
effect_path = /obj/structure/glowshroom/glowcap
tastes = list("glowcap" = 1)
//Shadowshroom
@@ -300,6 +301,7 @@
desc = "<I>Mycena Umbra</I>: This species of mushroom emits shadow instead of light."
icon_state = "shadowshroom"
effect_path = /obj/structure/glowshroom/shadowshroom
tastes = list("shadow" = 1, "mushroom" = 1)
/obj/item/reagent_containers/food/snacks/grown/mushroom/glowshroom/shadowshroom/attack_self(mob/user)
. = ..()
@@ -368,4 +370,4 @@
plantname = "Embershroom Mushrooms"
product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_stem
genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism, /datum/plant_gene/trait/glow)
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
+1 -1
View File
@@ -69,4 +69,4 @@
desc = "They shine like exceptionally low quality amethyst."
icon_state = "onionslice_red"
filling_color = "#C29ACF"
list_reagents = list("nutriment" = 5, "vitamin" = 2, "tearjuice" = 2.5)
list_reagents = list("nutriment" = 5, "vitamin" = 2, "tearjuice" = 2.5)
+1 -1
View File
@@ -81,7 +81,7 @@
righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi'
flags_1 = CONDUCT_1
force = 12
w_class = WEIGHT_CLASS_TINY
w_class = WEIGHT_CLASS_SMALL
throwforce = 15
throw_speed = 3
throw_range = 4
+16 -20
View File
@@ -801,8 +801,7 @@
if(!anchored && !isinspace())
user.visible_message("[user] begins to wrench [src] into place.", \
"<span class='notice'>You begin to wrench [src] in place...</span>")
playsound(loc, O.usesound, 50, 1)
if (do_after(user, 20*O.toolspeed, target = src))
if (O.use_tool(src, user, 20, volume=50))
if(anchored)
return
anchored = TRUE
@@ -811,8 +810,7 @@
else if(anchored)
user.visible_message("[user] begins to unwrench [src].", \
"<span class='notice'>You begin to unwrench [src]...</span>")
playsound(loc, O.usesound, 50, 1)
if (do_after(user, 20*O.toolspeed, target = src))
if (O.use_tool(src, user, 20, volume=50))
if(!anchored)
return
anchored = FALSE
@@ -821,7 +819,7 @@
else if(istype(O, /obj/item/wirecutters) && unwrenchable)
using_irrigation = !using_irrigation
playsound(src, O.usesound, 50, 1)
O.play_tool_sound(src)
user.visible_message("<span class='notice'>[user] [using_irrigation ? "" : "dis"]connects [src]'s irrigation hoses.</span>", \
"<span class='notice'>You [using_irrigation ? "" : "dis"]connect [src]'s irrigation hoses.</span>")
for(var/obj/machinery/hydroponics/h in range(1,src))
@@ -831,21 +829,19 @@
if(!myseed && !weedlevel)
to_chat(user, "<span class='warning'>[src] doesn't have any plants or weeds!</span>")
return
user.visible_message("<span class='notice'>[user] starts digging out [src]'s plants...</span>", "<span class='notice'>You start digging out [src]'s plants...</span>")
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
if(!do_after(user, 50, target = src) || (!myseed && !weedlevel))
return
user.visible_message("<span class='notice'>[user] digs out the plants in [src]!</span>", "<span class='notice'>You dig out all of [src]'s plants!</span>")
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
if(myseed) //Could be that they're just using it as a de-weeder
age = 0
plant_health = 0
if(harvest)
harvest = FALSE //To make sure they can't just put in another seed and insta-harvest it
qdel(myseed)
myseed = null
weedlevel = 0 //Has a side effect of cleaning up those nasty weeds
update_icon()
user.visible_message("<span class='notice'>[user] starts digging out [src]'s plants...</span>",
"<span class='notice'>You start digging out [src]'s plants...</span>")
if(O.use_tool(src, user, 50, volume=50) || (!myseed && !weedlevel))
user.visible_message("<span class='notice'>[user] digs out the plants in [src]!</span>", "<span class='notice'>You dig out all of [src]'s plants!</span>")
if(myseed) //Could be that they're just using it as a de-weeder
age = 0
plant_health = 0
if(harvest)
harvest = FALSE //To make sure they can't just put in another seed and insta-harvest it
qdel(myseed)
myseed = null
weedlevel = 0 //Has a side effect of cleaning up those nasty weeds
update_icon()
else
return ..()
+13 -7
View File
@@ -157,14 +157,20 @@
/obj/item/seeds/proc/prepare_result(var/obj/item/reagent_containers/food/snacks/grown/T)
if(T.reagents)
for(var/reagent_id in reagents_add)
if(reagent_id == "blood") // Hack to make blood in plants always O-
T.reagents.add_reagent(reagent_id, 1 + round(potency * reagents_add[reagent_id], 1), list("blood_type"="O-"))
continue
if(!T.reagents)
CRASH("[T] has no reagents.")
T.reagents.add_reagent(reagent_id, 1 + round(potency * reagents_add[reagent_id],1))
return 1
for(var/rid in reagents_add)
var/amount = 1 + round(potency * reagents_add[rid], 1)
var/list/data = null
if(rid == "blood") // Hack to make blood in plants always O-
data = list("blood_type" = "O-")
if(rid == "nutriment" || rid == "vitamin")
// apple tastes of apple.
data = T.tastes
T.reagents.add_reagent(rid, amount, data)
/// Setters procs ///
@@ -24,7 +24,7 @@
armor = list(melee = 50, bullet = 70, laser = 70, energy = 100, bomb = 10, bio = 100, rad = 100, fire = 0, acid = 0)
/obj/item/device/electronic_assembly/proc/check_interactivity(mob/user)
return user.canUseTopic(src,be_close = TRUE)
return user.canUseTopic(src, BE_CLOSE)
/obj/item/device/electronic_assembly/Initialize()
@@ -83,7 +83,7 @@
if(!circuit.removable)
builtin_components += "<a href='?src=[REF(circuit)]'>[circuit.displayed_name]</a> | "
builtin_components += "<a href='?src=[REF(circuit)];rename=1;return=1'>\[Rename\]</a> | "
builtin_components += "<a href='?src=[REF(circuit)];scan=1'>\[Scan with Debugger\]</a>"
builtin_components += "<a href='?src=[REF(circuit)];scan=1;return=1'>\[Copy Ref\]</a>"
builtin_components += "<br>"
// Put removable circuits (if any) in separate categories from non-removable
@@ -101,7 +101,7 @@
if(circuit.removable)
HTML += "<a href='?src=[REF(circuit)]'>[circuit.displayed_name]</a> | "
HTML += "<a href='?src=[REF(circuit)];rename=1;return=1'>\[Rename\]</a> | "
HTML += "<a href='?src=[REF(circuit)];scan=1'>\[Scan with Debugger\]</a> | "
HTML += "<a href='?src=[REF(circuit)];scan=1;return=1'>\[Copy Ref\]</a> | "
HTML += "<a href='?src=[REF(src)];component=[REF(circuit)];remove=1'>\[Remove\]</a> | "
HTML += "<a href='?src=[REF(src)];component=[REF(circuit)];up=1' style='text-decoration:none;'>&#8593;</a> "
HTML += "<a href='?src=[REF(src)];component=[REF(circuit)];down=1' style='text-decoration:none;'>&#8595;</a> "
@@ -110,7 +110,7 @@
HTML += "<br>"
HTML += "</body></html>"
user << browse(HTML, "window=assembly-[REF(src)];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1")
user << browse(HTML, "window=assembly-[REF(src)];size=655x350;border=1;can_resize=1;can_close=1;can_minimize=1")
/obj/item/device/electronic_assembly/Topic(href, href_list)
if(..())
@@ -250,19 +250,23 @@
assembly_components |= component
/obj/item/device/electronic_assembly/proc/try_remove_component(obj/item/integrated_circuit/IC, mob/user)
/obj/item/device/electronic_assembly/proc/try_remove_component(obj/item/integrated_circuit/IC, mob/user, silent)
if(!opened)
to_chat(user, "<span class='warning'>[src]'s hatch is closed, so you can't fiddle with the internal components.</span>")
if(!silent)
to_chat(user, "<span class='warning'>[src]'s hatch is closed, so you can't fiddle with the internal components.</span>")
return FALSE
if(!IC.removable)
to_chat(user, "<span class='warning'>[src] is permanently attached to the case.</span>")
if(!silent)
to_chat(user, "<span class='warning'>[src] is permanently attached to the case.</span>")
return FALSE
to_chat(user, "<span class='notice'>You pop \the [src] out of the case, and slide it out.</span>")
playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
remove_component(IC)
if(!silent)
to_chat(user, "<span class='notice'>You pop \the [IC] out of the case, and slide it out.</span>")
playsound(src, 'sound/items/crowbar.ogg', 50, 1)
user.put_in_hands(IC)
return TRUE
// Actually removes the component, doesn't perform any checks.
@@ -279,8 +283,8 @@
visible_message("<span class='notice'> [user] waves [src] around [target].</span>")
/obj/item/device/electronic_assembly/screwdriver_act(mob/living/user, obj/item/S)
playsound(src, S.usesound, 50, 1)
/obj/item/device/electronic_assembly/screwdriver_act(mob/living/user, obj/item/I)
I.play_tool_sound(src)
opened = !opened
to_chat(user, "<span class='notice'>You [opened ? "open" : "close"] the maintenance hatch of [src].</span>")
update_icon()
@@ -491,7 +495,7 @@
name = "electronic drone"
icon_state = "setup_drone"
desc = "It's a case, for building mobile electronics with."
w_class = WEIGHT_CLASS_SMALL
w_class = WEIGHT_CLASS_BULKY
max_components = IC_MAX_SIZE_BASE * 3
max_complexity = IC_COMPLEXITY_BASE * 3

Some files were not shown because too many files have changed in this diff Show More