Merge branch 'master' into departmentalclothes

This commit is contained in:
faaaay
2021-07-20 17:16:43 +01:00
committed by GitHub
76 changed files with 689 additions and 203 deletions
+1
View File
@@ -80,6 +80,7 @@
#define ADMIN_PUNISHMENT_NUGGET "Nugget"
#define ADMIN_PUNISHMENT_BREADIFY ":b:read"
#define ADMIN_PUNISHMENT_BOOKIFY "Bookify"
#define ADMIN_PUNISHMENT_BONK "Bonk"
#define AHELP_ACTIVE 1
#define AHELP_CLOSED 2
+7 -1
View File
@@ -28,7 +28,9 @@
#define ITEM_SLOT_POCKET (1<<11) // this is to allow items with a w_class of WEIGHT_CLASS_NORMAL or WEIGHT_CLASS_BULKY to fit in pockets.
#define ITEM_SLOT_DENYPOCKET (1<<12) // this is to deny items with a w_class of WEIGHT_CLASS_SMALL or WEIGHT_CLASS_TINY to fit in pockets.
#define ITEM_SLOT_NECK (1<<13)
#define ITEM_SLOT_SUITSTORE (1<<14)
#define ITEM_SLOT_HANDS (1<<14)
#define ITEM_SLOT_BACKPACK (1<<15)
#define ITEM_SLOT_SUITSTORE (1<<16)
//SLOTS
#define SLOT_BACK 1
@@ -86,6 +88,10 @@
. = ITEM_SLOT_ICLOTHING
if(SLOT_L_STORE, SLOT_R_STORE)
. = ITEM_SLOT_POCKET
if(SLOT_HANDS)
. = ITEM_SLOT_HANDS
if(SLOT_IN_BACKPACK)
. = ITEM_SLOT_BACKPACK
if(SLOT_S_STORE)
. = ITEM_SLOT_SUITSTORE
+11
View File
@@ -158,6 +158,17 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
return FALSE
return TRUE
/mob/living/carbon/proc/is_butt_exposed(var/list/L)
if(!L)
L = get_equipped_items()
for(var/obj/item/I in L)
if(I.body_parts_covered & GROIN)
if(!I.do_not_cover_butt)
return FALSE
else
return TRUE
return TRUE
/mob/living/carbon/proc/is_chest_exposed(var/list/L)
if(!L)
L = get_equipped_items()
+2
View File
@@ -183,6 +183,7 @@
"cock_shape" = pick(GLOB.cock_shapes_list),
"cock_length" = 6,
"belly_size" = 1,
"butt_size" = 1,
"cock_girth_ratio" = COCK_GIRTH_RATIO_DEF,
"cock_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
"has_sheath" = FALSE,
@@ -192,6 +193,7 @@
"inflatable_belly" = FALSE,
"belly_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
"has_balls" = FALSE,
"has_anus" = FALSE,
"balls_internal" = FALSE,
"balls_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
"balls_amount" = 2,
+7 -1
View File
@@ -2,12 +2,13 @@
var/magic = FALSE
var/holy = FALSE
var/psychic = FALSE
var/allowed_slots = ~ITEM_SLOT_BACKPACK
var/charges = INFINITY
var/blocks_self = TRUE
var/datum/callback/reaction
var/datum/callback/expire
/datum/component/anti_magic/Initialize(_magic = FALSE, _holy = FALSE, _psychic = FALSE, _charges, _blocks_self = TRUE, datum/callback/_reaction, datum/callback/_expire)
/datum/component/anti_magic/Initialize(_magic = FALSE, _holy = FALSE, _psychic = FALSE, _allowed_slots, _charges, _blocks_self = TRUE, datum/callback/_reaction, datum/callback/_expire)
if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
@@ -19,6 +20,8 @@
magic = _magic
holy = _holy
psychic = _psychic
if(_allowed_slots)
allowed_slots = _allowed_slots
if(!isnull(_charges))
charges = _charges
blocks_self = _blocks_self
@@ -26,6 +29,9 @@
expire = _expire
/datum/component/anti_magic/proc/on_equip(datum/source, mob/equipper, slot)
if(!CHECK_BITFIELD(allowed_slots, slotdefine2slotbit(slot))) //Check that the slot is valid for antimagic
UnregisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC)
return
RegisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC, .proc/protect, TRUE)
/datum/component/anti_magic/proc/on_drop(datum/source, mob/user)
+6 -15
View File
@@ -7,33 +7,24 @@
var/filter_x
var/filter_y
var/filter_size
var/filter_border
var/filter_color
/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _border = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
. = ..()
if(. == COMPONENT_INCOMPATIBLE)
return
filter_x = _x
filter_y = _y
filter_size = _size
filter_border = _border
filter_color = _color
valid_slots = _valid_slots
/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(datum/source, mob/user, combatmodestate)
if(istype(user))
var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
if(!combatmodestate)
user.filters -= thefilter
else
user.filters += thefilter
/datum/component/wearertargeting/phantomthief/proc/stripdesiredfilter(mob/user)
if(istype(user))
var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
user.filters -= thefilter
if(!combatmodestate)
user.remove_filter("phantomthief")
else
user.add_filter("phantomthief", 4, list(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, color = filter_color))
/datum/component/wearertargeting/phantomthief/on_drop(datum/source, mob/user)
. = ..()
stripdesiredfilter(user)
user.remove_filter("phantomthief")
+14 -16
View File
@@ -26,10 +26,10 @@
/datum/proc/vv_get_dropdown()
. = list()
. += "---"
.["Call Proc"] = "?_src_=vars;[HrefToken()];proc_call=[REF(src)]"
.["Mark Object"] = "?_src_=vars;[HrefToken()];mark_object=[REF(src)]"
.["Delete"] = "?_src_=vars;[HrefToken()];delete=[REF(src)]"
.["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=[REF(src)]"
.["Call Proc"] = "?_src_=vars;[HrefToken()];proc_call=\ref[src]"
.["Mark Object"] = "?_src_=vars;[HrefToken()];mark_object=\ref[src]"
.["Delete"] = "?_src_=vars;[HrefToken()];delete=\ref[src]"
.["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=\ref[src]"
/datum/proc/on_reagent_change(changetype)
@@ -54,7 +54,7 @@
return
var/title = ""
var/refid = REF(D)
var/refid = "\ref[D]"
var/icon/sprite
var/hash
@@ -62,8 +62,6 @@
if (!islist)
type = D.type
if(istype(D, /atom))
var/atom/AT = D
if(AT.icon && AT.icon_state)
@@ -411,7 +409,7 @@
/client/proc/vv_update_display(datum/D, span, content)
src << output("[span]:[content]", "variables[REF(D)].browser:replace_span")
src << output("[span]:[content]", "variables\ref[D].browser:replace_span")
#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing )
@@ -424,9 +422,9 @@
name = DA[name] //name is really the index until this line
else
value = DA[name]
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];listedit=[REF(DA)];index=[index]'>E</a>) (<a href='?_src_=vars;[HrefToken()];listchange=[REF(DA)];index=[index]'>C</a>) (<a href='?_src_=vars;[HrefToken()];listremove=[REF(DA)];index=[index]'>-</a>) "
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];listedit=\ref[DA];index=[index]'>E</a>) (<a href='?_src_=vars;[HrefToken()];listchange=\ref[DA];index=[index]'>C</a>) (<a href='?_src_=vars;[HrefToken()];listremove=\ref[DA];index=[index]'>-</a>) "
else
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];datumedit=[REF(DA)];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;[HrefToken()];datumchange=[REF(DA)];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;[HrefToken()];datummass=[REF(DA)];varnamemass=[name]'>M</a>) "
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;[HrefToken()];datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;[HrefToken()];datummass=\ref[DA];varnamemass=[name]'>M</a>) "
else
header = "<li>"
@@ -441,7 +439,7 @@
#ifdef VARSICON
var/icon/I = new/icon(value)
var/rnd = rand(1,10000)
var/rname = "tmp[REF(I)][rnd].png"
var/rname = "tmp\ref[I][rnd].png"
usr << browse_rsc(I, rname)
item = "[VV_HTML_ENCODE(name)] = (<span class='value'>[value]</span>) <img class=icon src=\"[rname]\">"
#else
@@ -454,9 +452,9 @@
else if (istype(value, /datum))
var/datum/D = value
if ("[D]" != "[D.type]") //if the thing as a name var, lets use it.
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D] [D.type]"
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D] [D.type]"
else
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D.type]"
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D.type]"
else if (islist(value))
var/list/L = value
@@ -474,9 +472,9 @@
items += debug_variable(key, val, level + 1, sanitize = sanitize)
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
else
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
else if (name in GLOB.bitfields)
var/list/flags = list()
@@ -588,7 +586,7 @@
var/prompt = alert("Do you want to grant [C] access to view this VV window? (they will not be able to edit or change anything nor open nested vv windows unless they themselves are an admin)", "Confirm", "Yes", "No")
if (prompt != "Yes" || !usr.client)
return
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;[HrefToken(TRUE)];datumrefresh=[REF(thing)]'>VV window</a>")
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;[HrefToken(TRUE)];datumrefresh=\ref[thing]'>VV window</a>")
log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [thing]")
to_chat(C, "[usr.client.holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window")
C.debug_variables(thing)
+28
View File
@@ -0,0 +1,28 @@
#define SHORT 5/7
#define TALL 7/5
/datum/element/squish
element_flags = ELEMENT_DETACH
/datum/element/squish/Attach(datum/target, duration)
. = ..()
if(!iscarbon(target))
return ELEMENT_INCOMPATIBLE
var/mob/living/carbon/C = target
var/was_lying = (C.lying != 0)
addtimer(CALLBACK(src, .proc/Detach, C, was_lying), duration)
C.transform = C.transform.Scale(TALL, SHORT)
/datum/element/squish/Detach(mob/living/carbon/C, was_lying)
. = ..()
if(istype(C))
var/is_lying = (C.lying != 0)
if(was_lying == is_lying)
C.transform = C.transform.Scale(SHORT, TALL)
else
C.transform = C.transform.Scale(TALL, SHORT)
#undef SHORT
#undef TALL
+2 -2
View File
@@ -223,7 +223,7 @@
/datum/status_effect/belligerent/proc/do_movement_toggle(force_damage)
var/number_legs = owner.get_num_legs(FALSE)
if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.anti_magic_check() && number_legs)
if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.anti_magic_check(chargecost = 0) && number_legs)
if(force_damage || owner.m_intent != MOVE_INTENT_WALK)
if(GLOB.ratvar_awakens)
owner.Knockdown(20)
@@ -316,7 +316,7 @@
if(owner.confused)
owner.confused = 0
severity = 0
else if(!owner.anti_magic_check() && owner.stat != DEAD && severity)
else if(!owner.anti_magic_check(chargecost = 0) && owner.stat != DEAD && severity)
var/static/hum = get_sfx('sound/effects/screech.ogg') //same sound for every proc call
if(owner.getToxLoss() > MANIA_DAMAGE_TO_CONVERT)
if(is_eligible_servant(owner))
+3
View File
@@ -78,6 +78,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/strip_delay = 40 //In deciseconds, how long an item takes to remove from another person
var/breakouttime = 0
var/list/materials
var/reskinned = FALSE
var/list/attack_verb //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
var/list/species_exception = null // list() of species types, if a species cannot put items in a certain slot, but species type is in list, it will be able to wear that item
@@ -123,6 +124,8 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
//Hyper economy
var/price = 0
//Hyper, for clothes that reveal your behind! butt stuff, you know how it is.
var/do_not_cover_butt = FALSE
/obj/item/Initialize()
@@ -35,6 +35,24 @@
drop_sound = 'sound/items/handling/multitool_drop.ogg'
pickup_sound = 'sound/items/handling/multitool_pickup.ogg'
/obj/item/multitool/chaplain
name = "\improper hypertool"
desc = "Used for pulsing wires to test which to cut. Also emits microwaves to fry some brains!"
damtype = BRAIN
force = 18
armour_penetration = 35
hitsound = 'sound/effects/sparks4.ogg'
var/chaplain_spawnable = TRUE
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
throw_speed = 3
throw_range = 4
throwforce = 10
obj_flags = UNIQUE_RENAME
/obj/item/multitool/chaplain/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/multitool/examine(mob/user)
. = ..()
if(selected_io)
@@ -547,7 +547,9 @@ GENE SCANNER
var/turf/location = user.loc
if(!istype(location))
return
scan_turf(user, location)
/obj/item/analyzer/proc/scan_turf(mob/user, turf/location)
var/datum/gas_mixture/environment = location.return_air()
var/pressure = environment.return_pressure()
@@ -658,6 +660,20 @@ GENE SCANNER
amount += inaccurate
return DisplayTimeText(max(1,amount))
/obj/item/analyzer/ranged
desc = "A hand-held scanner which uses advanced spectroscopy and infrared readings to analyze gases as a distance. Alt-Click to use the built in barometer function."
name = "long-range analyzer"
icon = 'icons/obj/device.dmi'
icon_state = "ranged_analyzer"
/obj/item/analyzer/ranged/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(target.tool_act(user, src, tool_behaviour))
return
// Tool act didn't scan it, so let's get it's turf.
var/turf/location = get_turf(target)
scan_turf(user, location)
/proc/atmosanalyzer_scan(mixture, mob/living/user, atom/target = src)
var/icon = target
user.visible_message("[user] has used the analyzer on [icon2html(icon, viewers(src))] [target].", "<span class='notice'>You use the analyzer on [icon2html(icon, user)] [target].</span>")
+54 -6
View File
@@ -229,12 +229,12 @@
throwforce = 10
w_class = WEIGHT_CLASS_TINY
obj_flags = UNIQUE_RENAME
var/reskinned = FALSE
var/chaplain_spawnable = TRUE
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
/obj/item/nullrod/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, TRUE)
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/nullrod/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is killing [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to get closer to god!</span>")
@@ -248,7 +248,12 @@
if(GLOB.holy_weapon_type)
return
var/obj/item/holy_weapon
var/list/holy_weapons_list = subtypesof(/obj/item/nullrod)
var/list/holy_weapons_list = subtypesof(/obj/item/nullrod) + list(
/obj/item/twohanded/dualsaber/hypereutactic/chaplain,
/obj/item/gun/energy/laser/redtag/hitscan/chaplain,
/obj/item/multitool/chaplain,
/obj/item/melee/baseball_bat/chaplain
)
var/list/display_names = list()
var/list/nullrod_icons = list()
for(var/V in holy_weapons_list)
@@ -289,6 +294,13 @@
return FALSE
return TRUE
/obj/item/nullrod/proc/jedi_spin(mob/living/user)
for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH))
user.setDir(i)
if(i == WEST)
user.emote("flip")
sleep(1)
/obj/item/nullrod/godhand
icon_state = "disintegrate"
item_state = "disintegrate"
@@ -344,7 +356,6 @@
sharpness = IS_SHARP
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
/obj/item/nullrod/claymore/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(attack_type == PROJECTILE_ATTACK)
@@ -541,7 +552,6 @@
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_HUGE
attack_verb = list("smashed", "bashed", "hammered", "crunched")
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
/obj/item/nullrod/chainsaw
name = "chainsaw hand"
@@ -606,6 +616,7 @@
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
slot_flags = ITEM_SLOT_BELT
force = 12
reach = 2
attack_verb = list("whipped", "lashed")
hitsound = 'sound/weapons/chainhit.ogg'
@@ -682,6 +693,44 @@
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
/obj/item/nullrod/claymore/bostaff/attack(mob/target, mob/living/user)
add_fingerprint(user)
if((HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
to_chat(user, "<span class ='warning'>You club yourself over the head with [src].</span>")
user.Knockdown(60)
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.apply_damage(2*force, BRUTE, BODY_ZONE_HEAD)
else
user.take_bodypart_damage(2*force)
return
if(iscyborg(target))
return ..()
if(!isliving(target))
return ..()
var/mob/living/carbon/C = target
if(C.stat || C.health < 0 || C.staminaloss > 130 )
to_chat(user, "<span class='warning'>It would be dishonorable to attack a foe while they cannot retaliate.</span>")
return
if(user.a_intent == INTENT_DISARM)
if(!ishuman(target))
return ..()
var/mob/living/carbon/human/H = target
var/list/fluffmessages = list("[user] clubs [H] with [src]!", \
"[user] smacks [H] with the butt of [src]!", \
"[user] broadsides [H] with [src]!", \
"[user] smashes [H]'s head with [src]!", \
"[user] beats [H] with front of [src]!", \
"[user] twirls and slams [H] with [src]!")
H.visible_message("<span class='warning'>[pick(fluffmessages)]</span>", \
"<span class='userdanger'>[pick(fluffmessages)]</span>")
playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, 1, -1)
H.adjustStaminaLoss(rand(12,18))
if(prob(25))
(INVOKE_ASYNC(src, .proc/jedi_spin, user))
else
return ..()
/obj/item/nullrod/tribal_knife
icon_state = "crysknife"
item_state = "crysknife"
@@ -695,7 +744,6 @@
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
item_flags = SLOWS_WHILE_IN_HAND
total_mass = TOTAL_MASS_NORMAL_ITEM
/obj/item/nullrod/tribal_knife/Initialize(mapload)
. = ..()
+1 -1
View File
@@ -86,7 +86,7 @@
new /obj/item/multitool(src)
new /obj/item/stack/cable_coil(src,30,pick("red","yellow","orange"))
new /obj/item/extinguisher/mini(src)
new /obj/item/analyzer(src)
new /obj/item/analyzer/ranged(src)
//much roomier now that we've managed to remove two tools
/obj/item/storage/belt/utility/full/PopulateContents()
+13
View File
@@ -517,6 +517,19 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
var/homerun_able = 0
total_mass = 2.7 //a regular wooden major league baseball bat weighs somewhere between 2 to 3.4 pounds, according to google
/obj/item/melee/baseball_bat/chaplain
name = "blessed baseball bat"
desc = "There ain't a cult in the league that can withstand a swatter."
force = 14
throwforce = 14
obj_flags = UNIQUE_RENAME
var/chaplain_spawnable = TRUE
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
/obj/item/melee/baseball_bat/chaplain/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/melee/baseball_bat/homerun
name = "home run bat"
desc = "This thing looks dangerous... Dangerously good at baseball, that is."
+2
View File
@@ -65,6 +65,8 @@
var/mob/M = AM
if(M.mind in immune_minds)
return
if(M.anti_magic_check())
flare()
if(charges <= 0)
return
flare()
+6 -1
View File
@@ -1274,7 +1274,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
ADMIN_PUNISHMENT_FAKEBWOINK,
ADMIN_PUNISHMENT_NUGGET,
ADMIN_PUNISHMENT_BREADIFY,
ADMIN_PUNISHMENT_BOOKIFY)
ADMIN_PUNISHMENT_BOOKIFY,
ADMIN_PUNISHMENT_BONK)
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
@@ -1393,6 +1394,10 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
addtimer(CALLBACK(GLOBAL_PROC, .proc/bookify, target), BOOKIFY_TIME)
playsound(target, 'hyperstation/sound/misc/bookify.ogg', 60, 1)
#undef BOOKIFY_TIME
if(ADMIN_PUNISHMENT_BONK)
playsound(target, 'hyperstation/sound/misc/bonk.ogg', 100, 1)
target.AddElement(/datum/element/squish, 60 SECONDS)
to_chat(target, "<span class='warning big'>Bonk.</span>")
punish_log(target, punishment)
@@ -343,8 +343,8 @@
if(QDELETED(G))
return
if(istype(C.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
to_chat(user, "<span class='warning'>Your target seems to have some sort of protective headgear on, blocking the message from being sent!</span>")
if(C.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='warning'>Your target seems to have some sort of tinfoil protection on, blocking the message from being sent!</span>")
return
G.mind_control(command, user)
@@ -520,10 +520,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/abductor_baton/proc/SleepAttack(mob/living/L,mob/living/user)
if(L.incapacitated(TRUE, TRUE))
if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
to_chat(user, "<span class='warning'>The specimen's protective headgear is interfering with the sleep inducement!</span>")
L.visible_message("<span class='danger'>[user] tried to induced sleep in [L] with [src], but [L.p_their()] headgear protected [L.p_them()]!</span>", \
"<span class='userdanger'>You feel a strange wave of heavy drowsiness wash over you, but your headgear deflects most of it!</span>")
if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='warning'>The specimen's tinfoil protection is interfering with the sleep inducement!</span>")
L.visible_message("<span class='danger'>[user] tried to induced sleep in [L] with [src], but [L.p_their()] tinfoil protected [L.p_them()]!</span>", \
"<span class='userdanger'>You feel a strange wave of heavy drowsiness wash over you, but your tinfoil protection deflects most of it!</span>")
L.drowsyness += 2
return
L.visible_message("<span class='danger'>[user] has induced sleep in [L] with [src]!</span>", \
@@ -532,10 +532,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
L.Sleeping(1200)
log_combat(user, L, "put to sleep")
else
if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
to_chat(user, "<span class='warning'>The specimen's protective headgear is completely blocking our sleep inducement methods!</span>")
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src], but [L.p_their()] headgear completely protected [L.p_them()]!</span>", \
"<span class='userdanger'>Any sense of drowsiness is quickly diminished as your headgear deflects the effects!</span>")
if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='warning'>The specimen's tinfoil protection is completely blocking our sleep inducement methods!</span>")
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src], but [L.p_their()] tinfoil completely protected [L.p_them()]!</span>", \
"<span class='userdanger'>Any sense of drowsiness is quickly diminished as your tinfoil protection deflects the effects!</span>")
return
L.drowsyness += 1
to_chat(user, "<span class='warning'>Sleep inducement works fully only on stunned specimens! </span>")
@@ -178,8 +178,8 @@
c.console = src
/obj/machinery/abductor/console/proc/AddSnapshot(mob/living/carbon/human/target)
if(istype(target.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
say("Subject wearing specialized protective headgear, unable to get a proper scan!")
if(target.anti_magic_check(FALSE, FALSE, TRUE, 0))
say("Subject wearing specialized protective tinfoil gear, unable to get a proper scan!")
return
var/datum/icon_snapshot/entry = new
entry.name = target.name
@@ -35,7 +35,7 @@
/obj/item/clockwork/weapon/ratvarian_spear/attack(mob/living/target, mob/living/carbon/human/user)
. = ..()
if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check() && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check(chargecost = 0) && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
var/bonus_damage = bonus_burn //normally a total of 20 damage, 30 with ratvar
if(issilicon(target))
target.visible_message("<span class='warning'>[target] shudders violently at [src]'s touch!</span>", "<span class='userdanger'>ERROR: Temperature rising!</span>")
@@ -190,8 +190,8 @@
for(var/mob/living/L in range(1, src))
if(is_servant_of_ratvar(L))
continue
if(L.anti_magic_check())
var/atom/I = L.anti_magic_check()
var/atom/I = L.anti_magic_check()
if(I)
if(isitem(I))
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
@@ -60,7 +60,7 @@
else
if(isliving(target))
var/mob/living/L = target
if(!L.anti_magic_check())
if(!L.anti_magic_check(chargecost = 0))
if(isrevenant(L))
var/mob/living/simple_animal/revenant/R = L
if(R.revealed)
@@ -53,7 +53,7 @@
/obj/structure/destructible/clockwork/taunting_trail/proc/affect_mob(mob/living/L)
if(istype(L) && !is_servant_of_ratvar(L))
if(!L.anti_magic_check())
if(!L.anti_magic_check(chargecost = 0))
L.confused = min(L.confused + 15, 50)
L.dizziness = min(L.dizziness + 15, 50)
if(L.confused >= 25)
+5 -5
View File
@@ -62,8 +62,8 @@ Runes can either be invoked by one's self or with many different cultists. Each
if(do_after(user, 15, target = src))
to_chat(user, "<span class='notice'>You carefully erase the [lowertext(cultist_name)] rune.</span>")
qdel(src)
else if(istype(I, /obj/item/nullrod))
user.say("BEGONE FOUL MAGIKS!!", forced = "nullrod")
else if(istype(I, /obj/item/storage/book/bible) || istype(I, /obj/item/nullrod))
user.say("BEGONE FOUL MAGICKS!!", forced = "bible")
to_chat(user, "<span class='danger'>You disrupt the magic of [src] with [I].</span>")
qdel(src)
@@ -238,7 +238,7 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(M, "<span class='warning'>You need at least two invokers to convert [convertee]!</span>")
log_game("Offer rune failed - tried conversion with one invoker")
return 0
if(convertee.anti_magic_check(TRUE, TRUE, FALSE, 0)) //Not chargecost because it can be spammed
if(convertee.anti_magic_check(TRUE, TRUE, chargecost = 0)) //Not major because it can be spammed
for(var/M in invokers)
to_chat(M, "<span class='warning'>Something is shielding [convertee]'s mind!</span>")
log_game("Offer rune failed - convertee had anti-magic")
@@ -772,7 +772,7 @@ structure_check() searches for nearby cultist structures required for the invoca
set_light(6, 1, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume)
var/atom/I = L.anti_magic_check()
var/atom/I = L.anti_magic_check(chargecost = 0)
if(I)
if(isitem(I))
to_chat(L, "<span class='userdanger'>[I] suddenly burns hotly before returning to normal!</span>")
@@ -802,7 +802,7 @@ structure_check() searches for nearby cultist structures required for the invoca
set_light(6, 1, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume)
if(L.anti_magic_check())
if(L.anti_magic_check(chargecost = 0))
continue
L.take_overall_damage(tick_damage*multiplier, tick_damage*multiplier)
if(is_servant_of_ratvar(L))
@@ -65,7 +65,7 @@
if(target.anti_magic_check(FALSE, TRUE))
to_chat(src, "<span class='revenminor'>Something's wrong! [target] seems to be resisting the siphoning, leaving you vulnerable!</span>")
target.visible_message("<span class='warning'>[target] slumps onto the ground.</span>", \
"<span class='revenwarning'>Violets lights, dancing in your vision, receding--</span>")
"<span class='revenwarning'>Violet lights, dancing in your vision, receding--</span>")
draining = FALSE
return
var/datum/beam/B = Beam(target,icon_state="drain_life",time=INFINITY)
@@ -112,7 +112,8 @@
action_background_icon_state = "bg_revenant"
notice = "revennotice"
boldnotice = "revenboldnotice"
holy_check = TRUE
tinfoil_check = FALSE
/obj/effect/proc_holder/spell/aoe_turf/revenant
clothes_req = 0
+1 -1
View File
@@ -208,7 +208,7 @@
/datum/supply_pack/science/hev
name = "Hazard Suit Crate"
desc = "A familiar suit from the times of interdimensional exploring. Research Directors might prefer these due to their superior radioactive protection over the standard RD suit."
cost = 10000
cost = 15000
access = ACCESS_RD
contains = list(/obj/item/clothing/suit/space/hardsuit/rd/hev)
crate_name = "hazard suit crate"
+18
View File
@@ -134,6 +134,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
"cock_shape" = "Human",
"cock_length" = 6,
"belly_size" = 1,
"butt_size" = 1,
"cock_girth_ratio" = COCK_GIRTH_RATIO_DEF,
"cock_color" = "fff",
"has_sheath" = FALSE,
@@ -142,6 +143,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
"hide_belly" = FALSE,
"inflatable_belly" = FALSE,
"belly_color" = "fff",
"has_anus" = FALSE,
"has_balls" = FALSE,
"balls_internal" = FALSE,
"balls_color" = "fff",
@@ -920,6 +922,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Inflation (Climax With):</b><a style='display:block;width:50px' href='?_src_=prefs;preference=inflatable_belly'>[features["inflatable_belly"] == 1 ? "Yes" : "No"]</a>"
dat += "</td>"
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<h3>Butt</h3>"
dat += "<a style='display:block;width:50px' href='?_src_=prefs;preference=has_anus'>[features["has_anus"] == TRUE ? "Yes" : "No"]</a>"
if(features["has_anus"])
dat += "<b>Butt Size:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=butt_size;task=input'>[features["butt_size"]]</a>"
dat += "</td>"
dat += "</td>"
dat += "</tr></table>"
@@ -2340,6 +2350,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(new_bellysize)
features["belly_size"] = clamp(new_bellysize, 1, 3)
if("butt_size")
var/new_buttsize = input(user, "Butt size :\n(0-4)", "Character Preference") as num|null
features["butt_size"] = clamp(new_buttsize, 0, 4)
if("vag_shape")
var/new_shape
new_shape = input(user, "Vagina Type", "Character Preference") as null|anything in GLOB.vagina_shapes_list
@@ -2502,6 +2516,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(features["has_vag"] == FALSE)
features["has_womb"] = FALSE
features["can_get_preg"] = FALSE
if("has_anus")
features["has_anus"] = !features["has_anus"]
if(features["has_anus"] == FALSE)
features["butt_size"] = 0
if("has_womb")
features["has_womb"] = !features["has_womb"]
if("can_get_preg")
+6 -2
View File
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
#define SAVEFILE_VERSION_MAX 23
#define SAVEFILE_VERSION_MAX 24
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -402,6 +402,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_has_sheath"] >> features["sheath_color"]
//belly size
S["feature_belly_size"] >> features["belly_size"]
//belly size
S["feature_butt_size"] >> features["butt_size"]
//balls features
S["feature_has_balls"] >> features["has_balls"]
S["feature_balls_color"] >> features["balls_color"]
@@ -423,11 +425,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
//womb features
S["feature_has_womb"] >> features["has_womb"]
S["feature_can_get_preg"] >> features["can_get_preg"] //hyperstation 13
//balls features
//belly features
S["feature_has_belly"] >> features["has_belly"]
S["feature_belly_color"] >> features["belly_color"]
S["feature_hide_belly"] >> features["hide_belly"]
S["feature_inflatable_belly"] >> features["inflatable_belly"]
//anus features
S["feature_has_anus"] >> features["has_anus"]
//flavor text
//Let's make our players NOT cry desperately as we wipe their savefiles of their special snowflake texts:
+46 -10
View File
@@ -238,26 +238,62 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = -5,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = -5, "fire" = 0, "acid" = 0)
equip_delay_other = 140
var/datum/brain_trauma/mild/phobia/paranoia
var/warped = FALSE
clothing_flags = IGNORE_HAT_TOSS
/obj/item/clothing/head/foilhat/Initialize(mapload)
. = ..()
if(!warped)
AddComponent(/datum/component/anti_magic, FALSE, FALSE, TRUE, ITEM_SLOT_HEAD, 6, TRUE, null, CALLBACK(src, .proc/warp_up))
else
warp_up()
/obj/item/clothing/head/foilhat/equipped(mob/living/carbon/human/user, slot)
..()
if(slot == SLOT_HEAD)
if(paranoia)
QDEL_NULL(paranoia)
paranoia = new()
user.gain_trauma(paranoia, TRAUMA_RESILIENCE_MAGIC, "conspiracies")
to_chat(user, "<span class='warning'>As you don the foiled hat, an entire world of conspiracy theories and seemingly insane ideas suddenly rush into your mind. What you once thought unbelievable suddenly seems.. undeniable. Everything is connected and nothing happens just by accident. You know too much and now they're out to get you. </span>")
. = ..()
if(slot != SLOT_HEAD || warped)
return
if(paranoia)
QDEL_NULL(paranoia)
paranoia = new()
user.gain_trauma(paranoia, TRAUMA_RESILIENCE_MAGIC, "conspiracies")
to_chat(user, "<span class='warning'>As you don the foiled hat, an entire world of conspiracy theories and seemingly insane ideas suddenly rush into your mind. What you once thought unbelievable suddenly seems.. undeniable. Everything is connected and nothing happens just by accident. You know too much and now they're out to get you. </span>")
/obj/item/clothing/head/foilhat/MouseDrop(atom/over_object)
//God Im sorry
if(!warped && iscarbon(usr))
var/mob/living/carbon/C = usr
if(src == C.head)
to_chat(C, "<span class='userdanger'>Why would you want to take this off? Do you want them to get into your mind?!</span>")
return
return ..()
/obj/item/clothing/head/foilhat/dropped(mob/user)
..()
. = ..()
if(paranoia)
QDEL_NULL(paranoia)
/obj/item/clothing/head/foilhat/proc/warp_up()
name = "scorched tinfoil hat"
desc = "A badly warped up hat. Quite unprobable this will still work against any of fictional and contemporary dangers it used to."
warped = TRUE
if(!isliving(loc) || !paranoia)
return
var/mob/living/target = loc
if(target.get_item_by_slot(SLOT_HEAD) != src)
return
QDEL_NULL(paranoia)
if(!target.IsUnconscious())
to_chat(target, "<span class='warning'>Your zealous conspirationism rapidly dissipates as the donned hat warps up into a ruined mess. All those theories starting to sound like nothing but a ridicolous fanfare.</span>")
/obj/item/clothing/head/foilhat/attack_hand(mob/user)
if(iscarbon(user))
if(!warped && iscarbon(user))
var/mob/living/carbon/C = user
if(src == C.head)
to_chat(user, "<span class='userdanger'>Why would you want to take this off? Do you want them to get into your mind?!</span>")
return
..()
return ..()
/obj/item/clothing/head/foilhat/microwave_act(obj/machinery/microwave/M)
. = ..()
if(!warped)
warp_up()
+1 -1
View File
@@ -432,7 +432,7 @@
/obj/item/clothing/suit/space/hardsuit/wizard/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, FALSE)
AddComponent(/datum/component/anti_magic, TRUE, FALSE, FALSE, ITEM_SLOT_OCLOTHING, INFINITY, FALSE)
//Medical hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/medical
@@ -368,6 +368,10 @@ Contains:
resistance_flags = FIRE_PROOF
mutantrace_variation = NO_MUTANTRACE_VARIATION
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, FALSE, FALSE, TRUE, ITEM_SLOT_HEAD)
/obj/item/clothing/suit/space/hardsuit/ert/paranormal
name = "paranormal response team suit"
desc = "Powerful wards are built into this hardsuit, protecting the user from all manner of paranormal threats."
@@ -380,7 +384,7 @@ Contains:
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, TRUE)
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, ITEM_SLOT_OCLOTHING)
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor
name = "inquisitor's hardsuit"
+1
View File
@@ -133,6 +133,7 @@
/datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/L)
if(L.anti_magic_check(check_anti_magic, check_holy))
immune += L
return
L.Stun(20, 1, 1)
frozen_mobs[L] = L.anchored
+3 -3
View File
@@ -64,14 +64,14 @@
var/uses = 1
if(seed)
uses = round(seed.potency / 20)
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, uses, TRUE, CALLBACK(src, .proc/block_magic), CALLBACK(src, .proc/expire)) //deliver us from evil o melon god
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, ITEM_SLOT_HANDS, uses, TRUE, CALLBACK(src, .proc/block_magic), CALLBACK(src, .proc/expire)) //deliver us from evil o melon god
/obj/item/reagent_containers/food/snacks/grown/holymelon/proc/block_magic(mob/user, major)
if(major)
visible_message("<span class='warning'>[src] hums slightly, and seems to decay a bit.</span>")
to_chat(user, "<span class='warning'>[src] hums slightly, and seems to decay a bit.</span>")
/obj/item/reagent_containers/food/snacks/grown/holymelon/proc/expire(mob/user)
visible_message("<span class='warning'>[src] rapidly turns into ash!</span>")
to_chat(user, "<span class='warning'>[src] rapidly turns into ash!</span>")
qdel(src)
new /obj/effect/decal/cleanable/ash(drop_location())
@@ -12,6 +12,7 @@ Chaplain
spawn_positions = 1
supervisors = "the head of personnel"
selection_color = "#dddddd"
custom_spawn_text = "You're playing a job that is essential for when the station deals with paranormal threats. While you have access to weapons, armor and tools such as your nullrod and bible, this does not mean you should hunt those threats unless warranted. If you have any questions, don't hesitate to ask mentors."
outfit = /datum/outfit/job/chaplain
@@ -95,8 +95,14 @@ Doesn't work on other aliens/AI.*/
var/mob/living/M = input("Select who to whisper to:","Whisper to?",null) as null|mob in options
if(!M)
return 0
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='noticealien'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return FALSE
var/msg = sanitize(input("Message:", "Alien Whisper") as text|null)
if(msg)
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='notice'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return
log_directed_talk(user, M, msg, LOG_SAY, tag="alien whisper")
to_chat(M, "<span class='noticealien'>You hear a strange, alien voice in your head...</span>[msg]")
to_chat(user, "<span class='noticealien'>You said: \"[msg]\" to [M]</span>")
@@ -603,6 +603,8 @@
return FALSE
if(HAS_TRAIT(M, TRAIT_MINDSHIELD)) //mindshield implant, no dice
return FALSE
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
return FALSE
if(M in linked_mobs)
return FALSE
linked_mobs.Add(M)
@@ -688,9 +690,14 @@
var/mob/living/M = input("Select who to send your message to:","Send thought to?",null) as null|mob in options
if(!M)
return
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(H, "<span class='notice'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return
var/msg = sanitize(input("Message:", "Telepathy") as text|null)
if(msg)
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(H, "<span class='notice'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return
log_directed_talk(H, M, msg, LOG_SAY, "slime telepathy")
to_chat(M, "<span class='notice'>You hear an alien voice in your head... </span><font color=#008CA2>[msg]</font>")
to_chat(H, "<span class='notice'>You telepathically said: \"[msg]\" to [M]</span>")
@@ -88,7 +88,7 @@
to_chat(H, "<span class='notice'>[victim] doesn't have blood!</span>")
return
V.drain_cooldown = world.time + 30
if(victim.anti_magic_check(FALSE, TRUE))
if(victim.anti_magic_check(FALSE, TRUE, FALSE, 0))
to_chat(victim, "<span class='warning'>[H] tries to bite you, but stops before touching you!</span>")
to_chat(H, "<span class='warning'>[victim] is blessed! You stop just in time to avoid catching fire.</span>")
return
+1 -1
View File
@@ -976,7 +976,7 @@
apply_effect((amount*RAD_MOB_COEFFICIENT)/max(1, (radiation**2)*RAD_OVERDOSE_REDUCTION), EFFECT_IRRADIATE, blocked)
/mob/living/anti_magic_check(magic = TRUE, holy = FALSE)
/mob/living/anti_magic_check(magic = TRUE, holy = FALSE, chargecost = 1, self = FALSE)
. = ..()
if(.)
return
+5 -3
View File
@@ -804,15 +804,17 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
if(client)
client << output(null, "statbrowser:check_spells")
/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE)
if(!magic && !holy)
/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE, tinfoil = FALSE, chargecost = 1, self = FALSE)
if(!magic && !holy && !tinfoil)
return
var/list/protection_sources = list()
if(SEND_SIGNAL(src, COMSIG_MOB_RECEIVE_MAGIC, magic, holy, protection_sources) & COMPONENT_BLOCK_MAGIC)
if(SEND_SIGNAL(src, COMSIG_MOB_RECEIVE_MAGIC, src, magic, holy, tinfoil, chargecost, self, protection_sources) & COMPONENT_BLOCK_MAGIC)
if(protection_sources.len)
return pick(protection_sources)
else
return src
if((magic && HAS_TRAIT(src, TRAIT_ANTIMAGIC)) || (holy && HAS_TRAIT(src, TRAIT_HOLY)))
return src
//You can buckle on mobs if you're next to them since most are dense
/mob/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
@@ -59,6 +59,9 @@
/obj/item/ammo_casing/energy/laser/redtag/hitscan
projectile_type = /obj/item/projectile/beam/lasertag/redtag/hitscan
/obj/item/ammo_casing/energy/laser/redtag/hitscan/holy
projectile_type = /obj/item/projectile/beam/lasertag/redtag/hitscan/holy
/obj/item/ammo_casing/energy/xray
projectile_type = /obj/item/projectile/beam/xray
e_cost = 50
@@ -159,3 +159,65 @@
/obj/item/gun/energy/laser/redtag/hitscan
ammo_type = list(/obj/item/ammo_casing/energy/laser/redtag/hitscan)
/obj/item/gun/energy/laser/redtag/hitscan/chaplain
name = "\improper holy lasrifle"
desc = "A lasrifle from the old Imperium. This one seems to be blessed by techpriests."
icon_state = "LaserAK"
item_state = null
force = 14
pin = /obj/item/firing_pin/holy
icon = 'modular_citadel/icons/obj/guns/VGguns.dmi'
ammo_x_offset = 4
ammo_type = list(/obj/item/ammo_casing/energy/laser/redtag/hitscan/holy)
lefthand_file = 'modular_citadel/icons/mob/citadel/guns_lefthand.dmi'
righthand_file = 'modular_citadel/icons/mob/citadel/guns_righthand.dmi'
var/chaplain_spawnable = TRUE
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
throw_speed = 3
throw_range = 4
throwforce = 10
obj_flags = UNIQUE_RENAME
/obj/item/gun/energy/laser/redtag/hitscan/chaplain/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/gun/energy/laser/redtag/hitscan/chaplain/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params, bypass_timer)
if(!ishuman(user) || !ishuman(target))
return
if(semicd)
return
if(user == target)
target.visible_message("<span class='warning'>[user] sticks [src] in [user.p_their()] mouth, ready to pull the trigger...</span>", \
"<span class='userdanger'>You stick [src] in your mouth, ready to pull the trigger...</span>")
else
target.visible_message("<span class='warning'>[user] points [src] at [target]'s head, ready to pull the trigger...</span>", \
"<span class='userdanger'>[user] points [src] at your head, ready to pull the trigger...</span>")
semicd = TRUE
if(!bypass_timer && (!do_mob(user, target, 120) || user.zone_selected != BODY_ZONE_PRECISE_MOUTH))
if(user)
if(user == target)
user.visible_message("<span class='notice'>[user] decided not to shoot.</span>")
else if(target && target.Adjacent(user))
target.visible_message("<span class='notice'>[user] has decided to spare [target]</span>", "<span class='notice'>[user] has decided to spare your life!</span>")
semicd = FALSE
return
semicd = FALSE
target.visible_message("<span class='warning'>[user] pulls the trigger!</span>", "<span class='userdanger'>[user] pulls the trigger!</span>")
playsound('sound/weapons/dink.ogg', 30, 1)
if((iscultist(target)) || (is_servant_of_ratvar(target)))
chambered.BB.damage *= 1500
else if(chambered && chambered.BB)
chambered.BB.damage *= 5
process_fire(target, user, TRUE, params)
+4
View File
@@ -9,6 +9,7 @@
fire_sound = 'sound/weapons/emitter.ogg'
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_HUGE
var/checks_antimagic = FALSE
var/max_charges = 6
var/charges = 0
var/recharge_rate = 4
@@ -31,6 +32,9 @@
return
else
no_den_usage = 0
if(checks_antimagic && user.anti_magic_check(TRUE, FALSE, FALSE, 0, TRUE))
to_chat(user, "<span class='warning'>Something is interfering with [src].</span>")
return
. = ..()
/obj/item/gun/magic/can_shoot()
+5 -2
View File
@@ -87,14 +87,17 @@
max_charges = 10 //10, 5, 5, 4
/obj/item/gun/magic/wand/resurrection/zap_self(mob/living/user)
..()
charges--
if(user.anti_magic_check())
user.visible_message("<span class='warning'>[src] has no effect on [user]!</span>")
return
user.revive(full_heal = 1)
if(iscarbon(user))
var/mob/living/carbon/C = user
C.regenerate_limbs()
C.regenerate_organs()
to_chat(user, "<span class='notice'>You feel great!</span>")
charges--
..()
/obj/item/gun/magic/wand/resurrection/debug //for testing
name = "debug wand of healing"
+9
View File
@@ -186,6 +186,15 @@
desc = "This is a DNA-locked firing pin which only authorizes one user. Attempt to fire once to DNA-link. It has a small explosive charge on it."
selfdestruct = TRUE
/obj/item/firing_pin/holy
name = "blessed pin"
desc = "A firing pin that only responds to those who are holier than thou."
/obj/item/firing_pin/holy/pin_auth(mob/living/user)
if(user.mind.isholy)
return TRUE
return FALSE
// Laser tag pins
/obj/item/firing_pin/tag
name = "laser tag firing pin"
@@ -151,6 +151,11 @@
/obj/item/projectile/beam/lasertag/redtag/hitscan
hitscan = TRUE
/obj/item/projectile/beam/lasertag/redtag/hitscan/holy
name = "lasrifle beam"
damage = 0.1
damage_type = BURN
/obj/item/projectile/beam/lasertag/bluetag
icon_state = "bluelaser"
suit_types = list(/obj/item/clothing/suit/redtag)
@@ -93,7 +93,7 @@
/datum/design/medkit
name = "Medkit Cabinent"
name = "Medkit Cabinet"
id = "medkit_cabinet"
build_type = AUTOLATHE | PROTOLATHE
materials = list(MAT_METAL = 4000)
@@ -483,6 +483,16 @@
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
/datum/design/ranged_analyzer
name = "Long-range Analyzer"
desc = "A new advanced atmospheric analyzer design, capable of performing scans at long range."
id = "ranged_analyzer"
build_type = PROTOLATHE
materials = list(MAT_METAL = 400, MAT_GLASS = 1000, MAT_URANIUM = 800, MAT_GOLD = 200, MAT_PLASTIC = 200)
build_path = /obj/item/analyzer/ranged
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
/datum/design/rcd_loaded
name = "Rapid Construction Device (RCD)"
desc = "A tool that can construct and deconstruct walls, airlocks and floors on the fly."
+1 -1
View File
@@ -636,7 +636,7 @@
id = "exp_tools"
display_name = "Experimental Tools"
description = "Highly advanced construction tools."
design_ids = list("exwelder", "jawsoflife", "handdrill")
design_ids = list("exwelder", "jawsoflife", "handdrill", "ranged_analyzer")
prereq_ids = list("adv_engi")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750)
export_price = 5000
+26 -13
View File
@@ -115,6 +115,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
var/nonabstract_req = 0 //spell can only be cast by mobs that are physical entities
var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells
var/phase_allowed = 0 // If true, the spell can be cast while phased, eg. blood crawling, ethereal jaunting
var/antimagic_allowed = TRUE // If false, the spell cannot be cast while under the effect of antimagic
var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
var/invocation_emote_self = null
var/invocation_type = "none" //can be none, whisper, emote and shout
@@ -147,27 +148,36 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(player_lock)
if(!user.mind || !(src in user.mind.spell_list) && !(src in user.mob_spell_list))
to_chat(user, "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>")
return 0
return FALSE
else
if(!(src in user.mob_spell_list))
return 0
return FALSE
var/turf/T = get_turf(user)
if(is_centcom_level(T.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
to_chat(user, "<span class='notice'>You can't cast this spell here.</span>")
return 0
return FALSE
if(!skipcharge)
if(!charge_check(user))
return 0
return FALSE
if(user.stat && !stat_allowed)
to_chat(user, "<span class='notice'>Not when you're incapacitated.</span>")
return 0
return FALSE
if(!antimagic_allowed)
var/antimagic = user.anti_magic_check(TRUE, FALSE, chargecost = 0, self = TRUE)
if(antimagic)
if(isitem(antimagic))
to_chat(user, "<span class='notice'>[antimagic] is interfering with your magic.</span>")
else
to_chat(user, "<span class='notice'>Magic seems to flee from you, you can't gather enough power to cast this spell.</span>")
return FALSE
if(!phase_allowed && istype(user.loc, /obj/effect/dummy))
to_chat(user, "<span class='notice'>[name] cannot be cast unless you are completely manifested in the material plane.</span>")
return 0
return FALSE
if(ishuman(user))
@@ -175,7 +185,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if((invocation_type == "whisper" || invocation_type == "shout") && !H.can_speak_vocal())
to_chat(user, "<span class='notice'>You can't get the words out!</span>")
return 0
return FALSE
var/list/casting_clothes = typecacheof(list(/obj/item/clothing/suit/wizrobe,
/obj/item/clothing/suit/space/hardsuit/wizard,
@@ -187,24 +197,24 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(clothes_req) //clothes check
if(!is_type_in_typecache(H.wear_suit, casting_clothes))
to_chat(H, "<span class='notice'>I don't feel strong enough without my robe.</span>")
return 0
return FALSE
if(!is_type_in_typecache(H.head, casting_clothes))
to_chat(H, "<span class='notice'>I don't feel strong enough without my hat.</span>")
return 0
return FALSE
if(cult_req) //CULT_REQ CLOTHES CHECK
if(!istype(H.wear_suit, /obj/item/clothing/suit/magusred) && !istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/cult))
to_chat(H, "<span class='notice'>I don't feel strong enough without my armor.</span>")
return 0
return FALSE
if(!istype(H.head, /obj/item/clothing/head/magus) && !istype(H.head, /obj/item/clothing/head/helmet/space/hardsuit/cult))
to_chat(H, "<span class='notice'>I don't feel strong enough without my helmet.</span>")
return 0
return FALSE
else
if(clothes_req || human_req)
to_chat(user, "<span class='notice'>This spell can only be cast by humans!</span>")
return 0
return FALSE
if(nonabstract_req && (isbrain(user) || ispAI(user)))
to_chat(user, "<span class='notice'>This spell can only be cast by physical beings!</span>")
return 0
return FALSE
if(!skipcharge)
@@ -499,6 +509,9 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(user.stat && !stat_allowed)
return FALSE
if(!antimagic_allowed && user.anti_magic_check(TRUE, FALSE, chargecost = 0, self = TRUE))
return FALSE
if(!ishuman(user))
if(clothes_req || human_req)
return FALSE
+1 -1
View File
@@ -35,6 +35,6 @@
return TRUE
if(ismob(mover))
var/mob/M = mover
if(M.anti_magic_check())
if(M.anti_magic_check(chargecost = 0))
return TRUE
return FALSE
@@ -86,7 +86,7 @@
/obj/effect/cross_action/spacetime_dist/proc/walk_link(atom/movable/AM)
if(ismob(AM))
var/mob/M = AM
if(M.anti_magic_check())
if(M.anti_magic_check(chargecost = 0))
return
if(linked_dist && walks_left > 0)
flick("purplesparkles", src)
+6 -4
View File
@@ -10,9 +10,11 @@
action_background_icon_state = "bg_spell"
var/notice = "notice"
var/boldnotice = "boldnotice"
var/magic_check = TRUE
var/magic_check = FALSE
var/holy_check = FALSE
var/tinfoil_check = TRUE
/obj/effect/proc_holder/spell/targeted/telepathy/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
/obj/effect/proc_holder/spell/targeted/telepathy/cast(list/targets, mob/living/user = usr)
for(var/mob/living/M in targets)
var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "")
if(!msg)
@@ -20,11 +22,11 @@
return
log_directed_talk(user, M, msg, LOG_SAY, "[name]")
to_chat(user, "<span class='[boldnotice]'>You transmit to [M]:</span> <span class='[notice]'>[msg]</span>")
if(!magic_check || !M.anti_magic_check(FALSE, TRUE)) //hear no evil
if(!M.anti_magic_check(magic_check, holy_check, tinfoil_check, 0)) //hear no evil
to_chat(M, "<span class='[boldnotice]'>You hear something behind you talking...</span> <span class='[notice]'>[msg]</span>")
for(var/ded in GLOB.dead_mob_list)
if(!isobserver(ded))
continue
var/follow_rev = FOLLOW_LINK(ded, user)
var/follow_whispee = FOLLOW_LINK(ded, M)
to_chat(ded, "[follow_rev] <span class='[boldnotice]'>[user] [name]:</span> <span class='[notice]'>\"[msg]\" to</span> [follow_whispee] <span class='name'>[M]</span>")
to_chat(ded, "[follow_rev] <span class='[boldnotice]'>[user] [name]:</span> <span class='[notice]'>\"[msg]\" to</span> [follow_whispee] <span class='name'>[M]</span>")