This commit is contained in:
Putnam
2021-01-29 16:31:01 -08:00
156 changed files with 1939 additions and 686 deletions
@@ -18,7 +18,7 @@
/obj/item/mining_scanner,
/obj/item/flashlight/lantern,
/obj/item/card/id/mining,
/obj/item/gps/mining,
/obj/item/gps/mining/off,
/turf/open/floor/plating,
/area/ruin/powered/golem_ship)
"d" = (
@@ -32,7 +32,7 @@
/obj/item/mining_scanner,
/obj/item/flashlight/lantern,
/obj/item/card/id/mining,
/obj/item/gps/mining,
/obj/item/gps/mining/off,
/turf/open/floor/plating,
/area/ruin/powered/golem_ship)
"e" = (
@@ -71,8 +71,8 @@
/area/ruin/powered/golem_ship)
"k" = (
/obj/machinery/computer/arcade/battle{
icon_state = "arcade";
dir = 4
dir = 4;
icon_state = "arcade"
},
/turf/open/floor/mineral/titanium/purple,
/area/ruin/powered/golem_ship)
@@ -112,8 +112,8 @@
/area/ruin/powered/golem_ship)
"s" = (
/obj/machinery/computer/arcade/orion_trail{
icon_state = "arcade";
dir = 4
dir = 4;
icon_state = "arcade"
},
/turf/open/floor/mineral/titanium/purple,
/area/ruin/powered/golem_ship)
File diff suppressed because it is too large Load Diff
+11 -8
View File
@@ -6004,12 +6004,12 @@
c_tag = "Security Checkpoint";
pixel_x = 22
},
/obj/machinery/newscaster/security_unit{
pixel_y = 32
},
/obj/structure/cable{
icon_state = "4-8"
},
/obj/machinery/airalarm{
pixel_y = 23
},
/turf/open/floor/plasteel,
/area/security/checkpoint)
"aoz" = (
@@ -32290,10 +32290,6 @@
dir = 8;
light_color = "#e8eaff"
},
/obj/machinery/airalarm{
dir = 4;
pixel_x = -22
},
/turf/open/floor/plasteel,
/area/hydroponics)
"bsl" = (
@@ -71184,6 +71180,13 @@
/obj/machinery/atmospherics/pipe/simple/yellow/visible,
/turf/open/floor/plasteel,
/area/engine/atmos)
"pMW" = (
/obj/machinery/airalarm{
dir = 1;
pixel_y = -22
},
/turf/open/floor/plasteel,
/area/hydroponics)
"pZq" = (
/obj/structure/disposalpipe/sorting/mail/flip{
dir = 8;
@@ -121382,7 +121385,7 @@ amV
aqI
aqB
aGO
auy
pMW
aqB
aqI
amV
@@ -49530,7 +49530,7 @@
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/turf_decal/stripes/line{
dir = 10
dir = 8
},
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
@@ -113323,10 +113323,6 @@
/obj/item/clothing/gloves/color/black,
/obj/item/storage/box/evidence,
/obj/item/taperecorder,
/obj/machinery/airalarm{
dir = 8;
pixel_x = 24
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
+3 -35
View File
@@ -30529,9 +30529,6 @@
dir = 8
},
/obj/structure/closet/bombcloset,
/obj/machinery/airalarm{
pixel_y = 24
},
/turf/open/floor/plasteel/dark,
/area/science/mixing)
"aXC" = (
@@ -43701,10 +43698,6 @@
/obj/structure/window/reinforced{
dir = 1
},
/obj/machinery/airalarm{
dir = 4;
pixel_x = -22
},
/mob/living/simple_animal/chicken{
desc = "The arch-nemesis of Kentucky.";
name = "Popeye";
@@ -46363,9 +46356,6 @@
"bwK" = (
/obj/structure/flora/grass/jungle/b,
/obj/structure/flora/ausbushes/sparsegrass,
/obj/machinery/airalarm{
pixel_y = 22
},
/turf/open/floor/grass,
/area/chapel/main)
"bwL" = (
@@ -48132,16 +48122,6 @@
},
/turf/open/floor/plasteel/showroomfloor,
/area/security/brig)
"bzx" = (
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/turf/closed/wall,
/area/crew_quarters/locker)
"bzy" = (
/obj/machinery/light/small{
dir = 8
@@ -58156,10 +58136,6 @@
icon_state = "plant-02";
pixel_y = 3
},
/obj/machinery/airalarm{
dir = 4;
pixel_x = -22
},
/obj/machinery/camera{
c_tag = "Prison Wing Cells";
dir = 4;
@@ -61358,7 +61334,7 @@
dir = 10
},
/turf/open/floor/plasteel,
/area/space)
/area/security/warden)
"bUs" = (
/obj/machinery/door/firedoor,
/obj/machinery/door/airlock/command/glass{
@@ -67210,10 +67186,6 @@
/obj/structure/cable{
icon_state = "1-4"
},
/obj/machinery/airalarm{
dir = 1;
pixel_y = -22
},
/turf/open/floor/plasteel,
/area/security/main)
"cdU" = (
@@ -71327,9 +71299,9 @@
icon_gib = "magicarp_gib";
icon_living = "magicarp";
icon_state = "magicarp";
maxHealth = 200;
max_co2 = 5;
max_tox = 2;
maxHealth = 200;
melee_damage_lower = 15;
melee_damage_upper = 20;
min_oxy = 5;
@@ -83281,10 +83253,6 @@
/obj/machinery/atmospherics/pipe/simple/yellow/visible{
dir = 5
},
/obj/machinery/airalarm{
dir = 4;
pixel_x = -23
},
/obj/machinery/camera{
c_tag = "Atmospherics Port Tanks";
dir = 4;
@@ -108992,7 +108960,7 @@ bss
btV
aEu
bxW
bzx
bIV
bKq
bKq
bKq
+8 -17
View File
@@ -1111,10 +1111,6 @@
/turf/open/floor/plasteel,
/area/security/prison)
"acx" = (
/obj/machinery/airalarm{
dir = 8;
pixel_x = 24
},
/obj/machinery/cryopod{
dir = 8
},
@@ -40497,10 +40493,9 @@
/area/maintenance/port)
"bBr" = (
/obj/machinery/airalarm{
dir = 4;
pixel_x = -23
dir = 1;
pixel_y = -22
},
/obj/structure/displaycase/trophy,
/turf/open/floor/wood,
/area/library)
"bBs" = (
@@ -45866,10 +45861,6 @@
/area/library)
"bML" = (
/obj/machinery/light/small,
/obj/machinery/airalarm{
dir = 1;
pixel_y = -22
},
/turf/open/floor/wood,
/area/library)
"bMM" = (
@@ -59581,6 +59572,10 @@
/obj/structure/chair{
dir = 1
},
/obj/machinery/airalarm{
dir = 4;
pixel_x = -23
},
/turf/open/floor/plasteel/dark,
/area/medical/surgery)
"coz" = (
@@ -61596,10 +61591,6 @@
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"csl" = (
/obj/machinery/airalarm{
dir = 1;
pixel_y = -22
},
/obj/structure/window/reinforced{
dir = 8
},
@@ -102698,7 +102689,7 @@ bue
bwa
bxU
bzD
bBr
dmD
bSx
bEw
bzE
@@ -103733,7 +103724,7 @@ bGs
bHS
bzE
bLk
bzE
bBr
bue
bPS
bPR
@@ -4924,11 +4924,11 @@
/obj/effect/turf_decal/stripes/end{
dir = 1
},
/obj/item/gun/energy/e_gun/hos,
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/item/gun/energy/e_gun/hos,
/turf/open/floor/plasteel/dark,
/area/crew_quarters/heads/captain/private)
"ahI" = (
@@ -40544,6 +40544,9 @@
name = "Starboard Quater Maintenance APC";
pixel_y = -26
},
/obj/structure/cable/white{
icon_state = "0-8"
},
/turf/open/floor/plating{
icon_state = "panelscorched"
},
@@ -16530,6 +16530,9 @@
/obj/structure/cable{
icon_state = "4-8"
},
/obj/machinery/airalarm{
pixel_y = 22
},
/turf/open/floor/plasteel,
/area/quartermaster/warehouse)
"aMr" = (
@@ -47631,6 +47634,9 @@
pixel_x = -25;
specialfunctions = 4
},
/obj/machinery/airalarm{
pixel_y = 22
},
/turf/open/floor/plasteel/grimy,
/area/chapel/main/monastery)
"cgM" = (
@@ -47979,6 +47985,9 @@
pixel_x = -25;
specialfunctions = 4
},
/obj/machinery/airalarm{
pixel_y = 22
},
/turf/open/floor/plasteel/grimy,
/area/chapel/main/monastery)
"cip" = (
@@ -51466,6 +51475,10 @@
name = "Coffin Storage";
req_one_access_txt = "22"
},
/obj/machinery/airalarm{
dir = 8;
pixel_x = 24
},
/turf/open/floor/plasteel/dark,
/area/chapel/main/monastery)
"cvu" = (
@@ -59434,6 +59447,10 @@
/obj/effect/turf_decal/tile/yellow{
dir = 8
},
/obj/machinery/airalarm{
dir = 8;
pixel_x = 23
},
/turf/open/floor/plasteel,
/area/construction/mining/aux_base)
"qXq" = (
+3
View File
@@ -69,6 +69,9 @@
#define LINGBLOOD_EXPLOSION_THRESHOLD (LINGBLOOD_DETECTION_THRESHOLD * LINGBLOOD_EXPLOSION_MULT) //Hey, important to note here: the explosion threshold is explicitly more than, rather than more than or equal to. This stops a single loud ability from triggering the explosion threshold.
///Heretics --
GLOBAL_LIST_EMPTY(living_heart_cache) //A list of all living hearts in existance, for us to iterate through.
#define IS_HERETIC(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic))
#define IS_HERETIC_MONSTER(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic_monster))
+3
View File
@@ -541,6 +541,9 @@
#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt" //from turf AltClickOn(): (/mob)
#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl" //from monkey CtrlClickOn(): (/mob)
// /datum/element/ventcrawling signals
#define COMSIG_HANDLE_VENTCRAWL "handle_ventcrawl" //when atom with ventcrawling element attempts to ventcrawl
#define COMSIG_CHECK_VENTCRAWL "check_ventcrawl" //to check an atom's ventcrawling element tier (if applicable)
// twitch plays
/// Returns direction: (wipe_votes)
#define COMSIG_TWITCH_PLAYS_MOVEMENT_DATA "twitch_plays_movement_data"
+5 -3
View File
@@ -72,9 +72,11 @@
#define LOADOUT_LIMBS list(LOADOUT_LIMB_NORMAL,LOADOUT_LIMB_PROSTHETIC,LOADOUT_LIMB_AMPUTATED) //you can amputate your legs/arms though
//loadout saving/loading specific defines
#define MAXIMUM_LOADOUT_SAVES 5
#define LOADOUT_ITEM "loadout_item"
#define LOADOUT_COLOR "loadout_color"
#define MAXIMUM_LOADOUT_SAVES 5
#define LOADOUT_ITEM "loadout_item"
#define LOADOUT_COLOR "loadout_color"
#define LOADOUT_CUSTOM_NAME "loadout_custom_name"
#define LOADOUT_CUSTOM_DESCRIPTION "loadout_custom_description"
//loadout item flags
#define LOADOUT_CAN_NAME (1<<0) //renaming items
+1
View File
@@ -253,6 +253,7 @@
// item traits
#define TRAIT_NODROP "nodrop"
#define TRAIT_SPOOKY_THROW "spooky_throw"
// common trait sources
#define TRAIT_GENERIC "generic"
+17 -16
View File
@@ -67,24 +67,25 @@
//Returns a list in plain english as a string
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
var/total = input.len
if (!total)
return nothing_text
else if (total == 1)
return "[input[1]]"
else if (total == 2)
return "[input[1]][and_text][input[2]]"
else
var/output = ""
var/index = 1
while (index < total)
if (index == total - 1)
comma_text = final_comma_text
var/total = length(input)
switch(total)
if (0)
return "[nothing_text]"
if (1)
return "[input[1]]"
if (2)
return "[input[1]][and_text][input[2]]"
else
var/output = ""
var/index = 1
while (index < total)
if (index == total - 1)
comma_text = final_comma_text
output += "[input[index]][comma_text]"
index++
output += "[input[index]][comma_text]"
index++
return "[output][and_text][input[index]]"
return "[output][and_text][input[index]]"
//Returns list element or null. Should prevent "index out of bounds" error.
/proc/listgetindex(list/L, index)
-27
View File
@@ -19,22 +19,6 @@
/proc/arachnid_name()
return "[pick(GLOB.arachnid_first)] [pick(GLOB.arachnid_last)]"
/proc/church_name()
var/static/church_name
if (church_name)
return church_name
var/name = ""
name += pick("Holy", "United", "First", "Second", "Last")
if (prob(20))
name += " Space"
name += " " + pick("Church", "Cathedral", "Body", "Worshippers", "Movement", "Witnesses")
name += " of [religion_name()]"
return name
GLOBAL_VAR(command_name)
/proc/command_name()
@@ -52,17 +36,6 @@ GLOBAL_VAR(command_name)
return name
/proc/religion_name()
var/static/religion_name
if (religion_name)
return religion_name
var/name = ""
name += pick("bee", "science", "edu", "captain", "assistant", "monkey", "alien", "space", "unit", "sprocket", "gadget", "bomb", "revolution", "beyond", "station", "goon", "robot", "ivor", "hobnob")
name += pick("ism", "ia", "ology", "istism", "ites", "ick", "ian", "ity")
return capitalize(name)
/proc/station_name()
if(!GLOB.station_name)
+16 -16
View File
@@ -78,21 +78,21 @@
//Turns a direction into text
/proc/dir2text(direction)
switch(direction)
if(1)
if(NORTH)
return "north"
if(2)
if(SOUTH)
return "south"
if(4)
if(EAST)
return "east"
if(8)
if(WEST)
return "west"
if(5)
if(NORTHEAST)
return "northeast"
if(6)
if(SOUTHEAST)
return "southeast"
if(9)
if(NORTHWEST)
return "northwest"
if(10)
if(SOUTHWEST)
return "southwest"
else
return
@@ -101,21 +101,21 @@
/proc/text2dir(direction)
switch(uppertext(direction))
if("NORTH")
return 1
return NORTH
if("SOUTH")
return 2
return SOUTH
if("EAST")
return 4
return EAST
if("WEST")
return 8
return WEST
if("NORTHEAST")
return 5
return NORTHEAST
if("NORTHWEST")
return 9
return NORTHWEST
if("SOUTHEAST")
return 6
return SOUTHEAST
if("SOUTHWEST")
return 10
return SOUTHWEST
else
return
+1 -1
View File
@@ -274,7 +274,7 @@ GLOBAL_LIST_INIT(redacted_strings, list("\[REDACTED\]", "\[CLASSIFIED\]", "\[ARC
GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt"))
//LANGUAGE CHARACTER CUSTOMIZATION
GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "chimpers", "declares", "bellows", "buzzes" ,"beeps", "chirps", "clicks", "hisses" ,"poofs" , "puffs", "rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters", "warbles"))
GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "chimpers", "declares", "bellows", "buzzes" ,"beeps", "chirps", "clicks", "hisses" ,"poofs" , "puffs", "rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters", "warbles", "caws", "gekkers", "clucks"))
GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc, "xeno tongue" = /obj/item/organ/tongue/alien))
//SPECIES BODYPART LISTS
+2 -1
View File
@@ -130,7 +130,8 @@ GLOBAL_LIST_INIT(traits_by_type, list(
),
/obj/item = list(
"TRAIT_NODROP" = TRAIT_NODROP,
"TRAIT_NO_TELEPORT" = TRAIT_NO_TELEPORT
"TRAIT_NO_TELEPORT" = TRAIT_NO_TELEPORT,
"TRAIT_SPOOKY_THROW" = TRAIT_SPOOKY_THROW
)
))
+34 -1
View File
@@ -220,7 +220,7 @@
/obj/screen/alert/shiver
name = "Shivering"
desc = "You're shivering! Get somewhere warmer and take off any insulating clothing like a space suit."
desc = "You're shivering! Get somewhere warmer and take off any insulating clothing like a space suit."
/obj/screen/alert/lowpressure
name = "Low Pressure"
@@ -306,6 +306,39 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
if(CHECK_MOBILITY(L, MOBILITY_MOVE))
return L.resist_fire() //I just want to start a flame in your hearrrrrrtttttt.
/obj/screen/alert/give // information set when the give alert is made
icon_state = "default"
var/mob/living/carbon/giver
var/obj/item/receiving
/**
* Handles assigning most of the variables for the alert that pops up when an item is offered
*
* Handles setting the name, description and icon of the alert and tracking the person giving
* and the item being offered, also registers a signal that removes the alert from anyone who moves away from the giver
* Arguments:
* * taker - The person receiving the alert
* * giver - The person giving the alert and item
* * receiving - The item being given by the giver
*/
/obj/screen/alert/give/proc/setup(mob/living/carbon/taker, mob/living/carbon/giver, obj/item/receiving)
name = "[giver] is offering [receiving]"
desc = "[giver] is offering [receiving]. Click this alert to take it."
icon_state = "template"
cut_overlays()
add_overlay(receiving)
src.receiving = receiving
src.giver = giver
RegisterSignal(taker, COMSIG_MOVABLE_MOVED, .proc/removeAlert)
/obj/screen/alert/give/proc/removeAlert()
to_chat(usr, "<span class='warning'>You moved out of range of [giver]!</span>")
usr.clear_alert("[giver]")
/obj/screen/alert/give/Click(location, control, params)
. = ..()
var/mob/living/carbon/C = usr
C.take(giver, receiving)
//ALIENS
+23 -15
View File
@@ -691,21 +691,29 @@ SUBSYSTEM_DEF(job)
if(!permitted)
continue
var/obj/item/I = new G.path
if(I && length(i[LOADOUT_COLOR])) //handle loadout colors
//handle polychromic items
if((G.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC) && length(G.loadout_initial_colors))
var/datum/element/polychromic/polychromic = I.comp_lookup["item_worn_overlays"] //stupid way to do it but GetElement does not work for this
if(polychromic && istype(polychromic))
var/list/polychromic_entry = polychromic.colors_by_atom[I]
if(polychromic_entry)
if(polychromic.suits_with_helmet_typecache[I.type]) //is this one of those toggleable hood/helmet things?
polychromic.connect_helmet(I,i[LOADOUT_COLOR])
polychromic.colors_by_atom[I] = i[LOADOUT_COLOR]
I.update_icon()
else
//handle non-polychromic items (they only have one color)
I.add_atom_colour(i[LOADOUT_COLOR][1], FIXED_COLOUR_PRIORITY)
I.update_icon()
if(I)
if(length(i[LOADOUT_COLOR])) //handle loadout colors
//handle polychromic items
if((G.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC) && length(G.loadout_initial_colors))
var/datum/element/polychromic/polychromic = I.comp_lookup["item_worn_overlays"] //stupid way to do it but GetElement does not work for this
if(polychromic && istype(polychromic))
var/list/polychromic_entry = polychromic.colors_by_atom[I]
if(polychromic_entry)
if(polychromic.suits_with_helmet_typecache[I.type]) //is this one of those toggleable hood/helmet things?
polychromic.connect_helmet(I,i[LOADOUT_COLOR])
polychromic.colors_by_atom[I] = i[LOADOUT_COLOR]
I.update_icon()
else
//handle non-polychromic items (they only have one color)
I.add_atom_colour(i[LOADOUT_COLOR][1], FIXED_COLOUR_PRIORITY)
I.update_icon()
//when inputting the data it's already sanitized
if(i[LOADOUT_CUSTOM_NAME])
var/custom_name = i[LOADOUT_CUSTOM_NAME]
I.name = custom_name
if(i[LOADOUT_CUSTOM_DESCRIPTION])
var/custom_description = i[LOADOUT_CUSTOM_DESCRIPTION]
I.desc = custom_description
if(!M.equip_to_slot_if_possible(I, G.slot, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // If the job's dresscode compliant, try to put it in its slot, first
if(iscarbon(M))
var/mob/living/carbon/C = M
+2
View File
@@ -84,6 +84,8 @@ SUBSYSTEM_DEF(throwing)
/datum/thrownthing/Destroy()
if(HAS_TRAIT_FROM(thrownthing, TRAIT_SPOOKY_THROW, "revenant"))
REMOVE_TRAIT(thrownthing, TRAIT_SPOOKY_THROW, "revenant")
SSthrowing.processing -= thrownthing
thrownthing.throwing = null
thrownthing = null
+3 -1
View File
@@ -21,7 +21,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
/datum/component/gps/item/Initialize(_gpstag = "COM0", emp_proof = FALSE)
/datum/component/gps/item/Initialize(_gpstag = "COM0", emp_proof = FALSE, starton = TRUE)
. = ..()
if(. == COMPONENT_INCOMPATIBLE || !isitem(parent))
return COMPONENT_INCOMPATIBLE
@@ -33,6 +33,8 @@ GLOBAL_LIST_EMPTY(GPS_list)
RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/on_emp_act)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_AltClick)
if(!starton)
tracking = FALSE
///Called on COMSIG_ITEM_ATTACK_SELF
/datum/component/gps/item/proc/interact(datum/source, mob/user)
@@ -449,6 +449,10 @@
// this must come before the screen objects only block, dunno why it wasn't before
if(over_object == M)
user_show_to_mob(M)
return
if(isrevenant(M))
RevenantThrow(over_object, M, source)
return
if(!M.incapacitated())
if(!istype(over_object, /obj/screen))
dump_content_at(over_object, M)
+1 -1
View File
@@ -121,7 +121,7 @@
add_monkey(affected_mob.mind)
if(ishuman(affected_mob))
var/mob/living/carbon/monkey/M = affected_mob.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
M.ventcrawler = VENTCRAWLER_ALWAYS
M.AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/datum/disease/transformation/jungle_fever/stage_act()
+1 -1
View File
@@ -141,7 +141,7 @@
/obj/item/clothing/head/mob_holder/dropped(mob/user)
. = ..()
if(held_mob && isturf(loc))//don't release on soft-drops
if(held_mob && !ismob(loc))//don't release on soft-drops
release()
/obj/item/clothing/head/mob_holder/proc/release()
+36
View File
@@ -0,0 +1,36 @@
/datum/element/ventcrawling
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 2
var/tier
/datum/element/ventcrawling/Attach(datum/target, duration = 0, given_tier = VENTCRAWLER_NUDE)
. = ..()
var/mob/living/person = target
if(!istype(person))
return FALSE
src.tier = given_tier
RegisterSignal(target, COMSIG_HANDLE_VENTCRAWL, .proc/handle_ventcrawl)
RegisterSignal(target, COMSIG_CHECK_VENTCRAWL, .proc/check_ventcrawl)
to_chat(target, "<span class='notice'>You can ventcrawl! Use alt+click on vents to quickly travel about the station.</span>")
if(duration!=0)
addtimer(CALLBACK(src, .proc/Detach, target), duration)
/datum/element/ventcrawling/Detach(datum/target)
UnregisterSignal(target, list(COMSIG_HANDLE_VENTCRAWL, COMSIG_CHECK_VENTCRAWL))
to_chat(target, "<span class='notice'>You can no longer ventcrawl.</span>")
return ..()
/datum/element/ventcrawling/proc/handle_ventcrawl(datum/target,atom/A)
var/mob/living/person = target
if(!istype(person))
return FALSE
person.handle_ventcrawl(A,tier)
/datum/element/ventcrawling/proc/check_ventcrawl()
return tier
+7 -2
View File
@@ -239,8 +239,13 @@ GLOBAL_LIST_EMPTY(explosions)
atoms += A
for(var/i in atoms)
var/atom/A = i
if(!QDELETED(A))
A.ex_act(dist)
if(QDELETED(A))
continue
A.ex_act(dist, null, src)
if(QDELETED(A) || !ismovable(A))
continue
var/atom/movable/AM = A
LAZYADD(AM.acted_explosions, explosion_id)
if(flame_dist && prob(40) && !isspaceturf(T) && !T.density)
new /obj/effect/hotspot(T) //Mostly for ambience!
+1 -1
View File
@@ -548,7 +548,7 @@
/atom/proc/contents_explosion(severity, target)
return //For handling the effects of explosions on contents that would not normally be effected
/atom/proc/ex_act(severity, target)
/atom/proc/ex_act(severity, target, datum/explosion/E)
set waitfor = FALSE
contents_explosion(severity, target)
SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target)
+2 -2
View File
@@ -574,8 +574,8 @@
return TRUE
//TODO: Better floating
/atom/movable/proc/float(on)
if(throwing)
/atom/movable/proc/float(on, throw_override)
if(throwing || !throw_override)
return
if(on && !(movement_type & FLOATING))
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
+7 -7
View File
@@ -455,7 +455,7 @@ If not set, defaults to check_completion instead. Set it. It's used by cryo.
var/target_real_name // Has to be stored because the target's real_name can change over the course of the round
var/target_missing_id
/datum/objective/escape/escape_with_identity/find_target()
/datum/objective/escape/escape_with_identity/find_target(dupe_search_range, blacklist)
target = ..()
update_explanation_text()
@@ -553,7 +553,7 @@ GLOBAL_LIST_EMPTY(possible_items)
for(var/I in subtypesof(/datum/objective_item/steal))
new I
/datum/objective/steal/find_target()
/datum/objective/steal/find_target(dupe_search_range, blacklist)
var/list/datum/mind/owners = get_owners()
var/approved_targets = list()
check_items:
@@ -631,7 +631,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
for(var/I in subtypesof(/datum/objective_item/special) + subtypesof(/datum/objective_item/stack))
new I
/datum/objective/steal/special/find_target()
/datum/objective/steal/special/find_target(dupe_search_range, blacklist)
return set_target(pick(GLOB.possible_items_special))
/datum/objective/steal/exchange
@@ -844,7 +844,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
name = "destroy AI"
martyr_compatible = 1
/datum/objective/destroy/find_target()
/datum/objective/destroy/find_target(dupe_search_range, blacklist)
var/list/possible_targets = active_ais(1)
var/mob/living/silicon/ai/target_ai = pick(possible_targets)
target = target_ai.mind
@@ -1124,7 +1124,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
/datum/objective/hoard/heirloom
name = "steal heirloom"
/datum/objective/hoard/heirloom/find_target()
/datum/objective/hoard/heirloom/find_target(dupe_search_range, blacklist)
set_target(pick(GLOB.family_heirlooms))
GLOBAL_LIST_EMPTY(traitor_contraband)
@@ -1141,7 +1141,7 @@ GLOBAL_LIST_EMPTY(cult_contraband)
if(!GLOB.cult_contraband.len)
GLOB.cult_contraband = list(/obj/item/clockwork/slab,/obj/item/clockwork/component/belligerent_eye,/obj/item/clockwork/component/belligerent_eye/lens_gem,/obj/item/shuttle_curse,/obj/item/cult_shift)
/datum/objective/hoard/collector/find_target()
/datum/objective/hoard/collector/find_target(dupe_search_range, blacklist)
var/obj/item/I
var/I_type
if(prob(50))
@@ -1172,7 +1172,7 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
for(var/I in subtypesof(/datum/sabotage_objective))
new I
/datum/objective/sabotage/find_target()
/datum/objective/sabotage/find_target(dupe_search_range, blacklist)
var/list/datum/mind/owners = get_owners()
var/approved_targets = list()
check_sabotages:
+27 -1
View File
@@ -6,10 +6,12 @@
density = TRUE
anchored = TRUE
circuit = /obj/item/circuitboard/machine/colormate
var/obj/item/inserted
var/atom/movable/inserted
var/activecolor = "#FFFFFF"
var/list/color_matrix_last
var/matrix_mode = FALSE
/// Allow holder'd mobs
var/allow_mobs = TRUE
/// Minimum lightness for normal mode
var/minimum_normal_lightness = 50
/// Minimum lightness for matrix mode, tested using 4 test colors of full red, green, blue, white.
@@ -57,11 +59,22 @@
return
if(user.a_intent == INTENT_HARM)
return ..()
if(allow_mobs && istype(I, /obj/item/clothing/head/mob_holder))
var/obj/item/clothing/head/mob_holder/H = I
var/mob/victim = H.held_mob
if(!user.transferItemToLoc(I, src))
to_chat(user, "<span class='warning'>[I] is stuck to your hand!</span>")
return
if(!QDELETED(H))
H.release()
insert_mob(victim, user)
if(is_type_in_list(I, allowed_types) && is_operational())
if(!user.transferItemToLoc(I, src))
to_chat(user, "<span class='warning'>[I] is stuck to your hand!</span>")
return
if(QDELETED(I))
return
user.visible_message("<span class='notice'>[user] inserts [I] into [src]'s receptable.</span>")
inserted = I
@@ -69,9 +82,22 @@
else
return ..()
/obj/machinery/gear_painter/proc/insert_mob(mob/victim, mob/user)
if(inserted)
return
if(user)
visible_message("<span class='warning'>[user] stuffs [victim] into [src]!</span>")
inserted = victim
inserted.forceMove(src)
/obj/machinery/gear_painter/AllowDrop()
return FALSE
/obj/machinery/gear_painter/handle_atom_del(atom/movable/AM)
if(AM == inserted)
inserted = null
return ..()
/obj/machinery/gear_painter/AltClick(mob/user)
. = ..()
if(!user.CanReach(src))
+8
View File
@@ -468,6 +468,10 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
melee_attack_chain(usr, over)
usr.FlushCurrentAction()
return TRUE //returning TRUE as a "is this overridden?" flag
if(isrevenant(usr))
if(RevenantThrow(over, usr, src))
return
if(!Adjacent(usr) || !over.Adjacent(usr))
return // should stop you from dragging through windows
@@ -939,6 +943,10 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
/obj/item/proc/get_part_rating()
return 0
//Can this item be given to people?
/obj/item/proc/can_give()
return TRUE
/obj/item/doMove(atom/destination)
if (ismob(loc))
var/mob/M = loc
+4
View File
@@ -82,4 +82,8 @@
/obj/item/candle/infinite/hugbox
heats_space = FALSE
/obj/item/candle/DoRevenantThrowEffects(atom/target)
if(!infinite)
put_out_candle()
#undef CANDLE_LUMINOSITY
+25 -1
View File
@@ -779,16 +779,40 @@
/obj/item/card/id/departmental_budget/update_label()
return
/obj/item/card/id/departmental_budget/civ
department_ID = ACCOUNT_CIV
department_name = ACCOUNT_CIV_NAME
/obj/item/card/id/departmental_budget/eng
department_ID = ACCOUNT_ENG
department_name = ACCOUNT_ENG_NAME
/obj/item/card/id/departmental_budget/sci
department_ID = ACCOUNT_SCI
department_name = ACCOUNT_SCI_NAME
/obj/item/card/id/departmental_budget/med
department_ID = ACCOUNT_MED
department_name = ACCOUNT_MED_NAME
/obj/item/card/id/departmental_budget/srv
department_ID = ACCOUNT_SRV
department_name = ACCOUNT_SRV_NAME
/obj/item/card/id/departmental_budget/car
department_ID = ACCOUNT_CAR
department_name = ACCOUNT_CAR_NAME
/obj/item/card/id/departmental_budget/sec
department_ID = ACCOUNT_SEC
department_name = ACCOUNT_SEC_NAME
//Polychromatic Knight Badge
/obj/item/card/id/knight
name = "knight badge"
icon_state = "knight"
desc = "A badge denoting the owner as a knight! It has a strip for swiping like an ID"
desc = "A badge denoting the owner as a knight! It has a strip for swiping like an ID."
var/id_color = "#00FF00" //defaults to green
var/mutable_appearance/id_overlay
+9
View File
@@ -136,6 +136,12 @@ CIGARETTE PACKETS ARE IN FANCY.DM
STOP_PROCESSING(SSobj, src)
. = ..()
/obj/item/clothing/mask/cigarette/DoRevenantThrowEffects(atom/target)
if(lit)
attackby()
else
light()
/obj/item/clothing/mask/cigarette/attackby(obj/item/W, mob/user, params)
if(!lit && smoketime > 0)
var/lighting_text = W.ignition_effect(src, user)
@@ -517,6 +523,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM
overlay_state = pick(overlay_list)
update_icon()
/obj/item/lighter/DoRevenantThrowEffects(atom/target)
set_lit()
/obj/item/lighter/suicide_act(mob/living/carbon/user)
if (lit)
user.visible_message("<span class='suicide'>[user] begins holding \the [src]'s flame up to [user.p_their()] face! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -37,11 +37,14 @@
/obj/item/flashlight/attack_self(mob/user)
on = !on
update_brightness(user)
playsound(user, on ? 'sound/weapons/magin.ogg' : 'sound/weapons/magout.ogg', 40, 1)
playsound(src, on ? 'sound/weapons/magin.ogg' : 'sound/weapons/magout.ogg', 40, TRUE)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
return 1
return TRUE
/obj/item/flashlight/DoRevenantThrowEffects(atom/target)
attack_self()
/obj/item/flashlight/suicide_act(mob/living/carbon/human/user)
if (user.eye_blind)
+5 -1
View File
@@ -8,10 +8,11 @@
slot_flags = ITEM_SLOT_BELT
obj_flags = UNIQUE_RENAME
var/gpstag = "COM0"
var/starton = TRUE
/obj/item/gps/Initialize()
. = ..()
AddComponent(/datum/component/gps/item, gpstag)
AddComponent(/datum/component/gps/item, gpstag, starton)
/obj/item/gps/science
icon_state = "gps-s"
@@ -26,6 +27,9 @@
gpstag = "MINE0"
desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life."
/obj/item/gps/mining/off
starton = FALSE
/obj/item/gps/cyborg
icon_state = "gps-b"
gpstag = "BORG0"
@@ -283,14 +283,12 @@ GLOBAL_LIST_INIT(channel_tokens, list(
SSradio.remove_object(src, GLOB.radiochannels[ch_name])
secure_radio_connections[ch_name] = null
var/turf/T = user.drop_location()
if(T)
if(keyslot)
keyslot.forceMove(T)
keyslot = null
if(keyslot2)
keyslot2.forceMove(T)
keyslot2 = null
if(keyslot)
user.put_in_hands(keyslot)
keyslot = null
if(keyslot2)
user.put_in_hands(keyslot2)
keyslot2 = null
recalculateChannels()
to_chat(user, "<span class='notice'>You pop out the encryption keys in the headset.</span>")
+3
View File
@@ -46,6 +46,9 @@
if(.)
new /obj/item/toy/eightball/haunted(loc)
/obj/item/toy/eightball/DoRevenantThrowEffects(atom/target)
MakeHaunted()
/obj/item/toy/eightball/attack_self(mob/user)
if(shaking)
return
+12 -5
View File
@@ -63,7 +63,7 @@
name = "advanced fire extinguisher"
desc = "Used to stop thermonuclear fires from spreading inside your engine."
icon_state = "foam_extinguisher0"
//item_state = "foam_extinguisher" needs sprite
item_state = "foam_extinguisher"
dog_fashion = null
chem = /datum/reagent/firefighting_foam
tanktype = /obj/structure/reagent_dispensers/foamtank
@@ -235,16 +235,23 @@
return
EmptyExtinguisher(user)
/obj/item/extinguisher/proc/EmptyExtinguisher(var/mob/user)
if(loc == user && reagents.total_volume)
/obj/item/extinguisher/DoRevenantThrowEffects(atom/target)
EmptyExtinguisher()
/obj/item/extinguisher/proc/EmptyExtinguisher(mob/user)
if(!reagents.total_volume)
return
if(loc == user || !user)
reagents.clear_reagents()
var/turf/T = get_turf(loc)
if(isopenturf(T))
var/turf/open/theturf = T
theturf.MakeSlippery(TURF_WET_WATER, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS)
user.visible_message("[user] empties out \the [src] onto the floor using the release valve.", "<span class='info'>You quietly empty out \the [src] by using its release valve.</span>")
if(user)
user.visible_message("[user] empties out \the [src] onto the floor using the release valve.", "<span class='info'>You quietly empty out \the [src] by using its release valve.</span>")
else
user.visible_message("The release valve of \the [src] suddenly opens and sprays it's contents on the floor!")
//firebot assembly
/obj/item/extinguisher/attackby(obj/O, mob/user, params)
+33 -9
View File
@@ -19,6 +19,8 @@
var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
var/ignore_suit_sensor_level = FALSE // Do we find people even if their suit sensors are turned off
var/alert = FALSE // TRUE to display things more seriously
/// resets target on toggle
var/resets_target = TRUE
/obj/item/pinpointer/Initialize()
. = ..()
@@ -27,17 +29,22 @@
/obj/item/pinpointer/Destroy()
STOP_PROCESSING(SSfastprocess, src)
GLOB.pinpointer_list -= src
target = null
unset_target()
return ..()
/obj/item/pinpointer/DoRevenantThrowEffects(atom/target)
attack_self()
/obj/item/pinpointer/attack_self(mob/living/user)
active = !active
user.visible_message("<span class='notice'>[user] [active ? "" : "de"]activates [user.p_their()] pinpointer.</span>", "<span class='notice'>You [active ? "" : "de"]activate your pinpointer.</span>")
if(user)
user.visible_message("<span class='notice'>[user] [active ? "" : "de"]activates [user.p_their()] pinpointer.</span>", "<span class='notice'>You [active ? "" : "de"]activate your pinpointer.</span>")
playsound(src, 'sound/items/screwdriver2.ogg', 50, 1)
if(active)
START_PROCESSING(SSfastprocess, src)
else
target = null
if(resets_target)
unset_target()
STOP_PROCESSING(SSfastprocess, src)
update_icon()
@@ -50,6 +57,18 @@
/obj/item/pinpointer/proc/scan_for_target()
return
/obj/item/pinpointer/proc/set_target(atom/movable/newtarget)
if(target)
unset_target()
target = newtarget
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/unset_target)
/obj/item/pinpointer/proc/unset_target()
if(!target)
return
UnregisterSignal(target, COMSIG_PARENT_QDELETING)
target = null
/obj/item/pinpointer/update_overlays()
. = ..()
if(!active)
@@ -101,7 +120,8 @@
active = FALSE
user.visible_message("<span class='notice'>[user] deactivates [user.p_their()] pinpointer.</span>", "<span class='notice'>You deactivate your pinpointer.</span>")
playsound(src, 'sound/items/screwdriver2.ogg', 50, 1)
target = null //Restarting the pinpointer forces a target reset
if(resets_target)
unset_target() //Restarting the pinpointer forces a target reset
STOP_PROCESSING(SSfastprocess, src)
update_icon()
return
@@ -137,7 +157,7 @@
if(!A || QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated())
return
target = names[A]
set_target(names[A])
active = TRUE
user.visible_message("<span class='notice'>[user] activates [user.p_their()] pinpointer.</span>", "<span class='notice'>You activate your pinpointer.</span>")
playsound(src, 'sound/items/screwdriver2.ogg', 50, 1)
@@ -149,7 +169,7 @@
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(!trackable(H))
target = null
unset_target()
if(!target) //target can be set to null from above code, or elsewhere
active = FALSE
@@ -163,7 +183,7 @@
. = ..()
/obj/item/pinpointer/pair/scan_for_target()
target = other_pair
set_target(other_pair)
/obj/item/pinpointer/pair/examine(mob/user)
. = ..()
@@ -195,7 +215,7 @@
shuttleport = SSshuttle.getShuttle("huntership")
/obj/item/pinpointer/shuttle/scan_for_target()
target = shuttleport
set_target(shuttleport)
/obj/item/pinpointer/shuttle/Destroy()
shuttleport = null
@@ -207,4 +227,8 @@
icon_state = "pinpointer_ian"
/obj/item/pinpointer/ian/scan_for_target()
target = locate(/mob/living/simple_animal/pet/dog/corgi/Ian) in GLOB.mob_living_list
set_target(locate(/mob/living/simple_animal/pet/dog/corgi/Ian) in GLOB.mob_living_list)
/obj/item/pinpointer/custom
resets_target = FALSE
+4
View File
@@ -45,6 +45,10 @@
return
set_snowflake_from_config(id)
/obj/item/toy/plush/DoRevenantThrowEffects(atom/target)
var/datum/component/squeak/squeaker = GetComponent(/datum/component/squeak)
squeaker.do_play_squeak(TRUE)
/obj/item/toy/plush/Initialize(mapload, set_snowflake_id)
. = ..()
AddComponent(/datum/component/squeak, squeak_override)
+30 -12
View File
@@ -43,6 +43,13 @@
/obj/item/pneumatic_cannon/proc/init_charge() //wrapper so it can be vv'd easier
START_PROCESSING(SSobj, src)
/obj/item/pneumatic_cannon/DoRevenantThrowEffects(atom/target)
var/picked_target
var/list/possible_targets = range(3,src)
picked_target = pick(possible_targets)
if(target)
Fire(null, picked_target)
/obj/item/pneumatic_cannon/process()
if(++charge_tick >= charge_ticks && charge_type)
fill_with_type(charge_type, charge_amount)
@@ -134,21 +141,29 @@
Fire(user, target)
/obj/item/pneumatic_cannon/proc/Fire(mob/living/user, var/atom/target)
if(!istype(user) && !target)
if(!target)
return
if(user)
if(!isliving(user))
return
var/discharge = 0
if(!can_trigger_gun(user))
if(user && !can_trigger_gun(user))
return
if(!loadedItems || !loadedWeightClass)
to_chat(user, "<span class='warning'>\The [src] has nothing loaded.</span>")
if(user)
to_chat(user, "<span class='warning'>\The [src] has nothing loaded.</span>")
return
if(!tank && checktank)
to_chat(user, "<span class='warning'>\The [src] can't fire without a source of gas.</span>")
if(user)
to_chat(user, "<span class='warning'>\The [src] can't fire without a source of gas.</span>")
return
if(tank && !tank.air_contents.remove(gasPerThrow * pressureSetting))
to_chat(user, "<span class='warning'>\The [src] lets out a weak hiss and doesn't react!</span>")
if(user)
to_chat(user, "<span class='warning'>\The [src] lets out a weak hiss and doesn't react!</span>")
else
visible_message(src, "<span class='warning'>\The [src] lets out a weak hiss and doesn't react!</span>")
return
if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(75) && clumsyCheck && iscarbon(user))
if(user && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(75) && clumsyCheck && iscarbon(user))
var/mob/living/carbon/C = user
C.visible_message("<span class='warning'>[C] loses [C.p_their()] grip on [src], causing it to go off!</span>", "<span class='userdanger'>[src] slips out of your hands and goes off!</span>")
C.dropItemToGround(src, TRUE)
@@ -157,15 +172,18 @@
else
var/list/possible_targets = range(3,src)
target = pick(possible_targets)
discharge = 1
if(!discharge)
discharge = TRUE
if(!discharge && user)
user.visible_message("<span class='danger'>[user] fires \the [src]!</span>", \
"<span class='danger'>You fire \the [src]!</span>")
log_combat(user, target, "fired at", src)
var/turf/T = get_target(target, get_turf(src))
playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, 1)
fire_items(T, user)
if(pressureSetting >= 3 && iscarbon(user))
playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, TRUE)
if(user)
log_combat(user, target, "fired at", src)
fire_items(T, user)
else
fire_items(T)
if(user && pressureSetting >= 3 && iscarbon(user))
var/mob/living/carbon/C = user
C.visible_message("<span class='warning'>[C] is thrown down by the force of the cannon!</span>", "<span class='userdanger'>[src] slams into your shoulder, knocking you down!")
C.DefaultCombatKnockdown(60)
+9
View File
@@ -47,6 +47,9 @@
cell = new preload_cell_type(src)
update_icon()
/obj/item/melee/baton/DoRevenantThrowEffects(atom/target)
switch_status()
/obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
..()
//Only mob/living types have stun handling
@@ -236,6 +239,12 @@
if(!iscyborg(loc))
deductcharge(severity*10, TRUE, FALSE)
/obj/item/melee/baton/can_give()
if(turned_on)
return FALSE
else
..()
/obj/item/melee/baton/stunsword
name = "stunsword"
desc = "Not actually sharp, this sword is functionally identical to its baton counterpart."
+9
View File
@@ -73,6 +73,15 @@
/obj/item/tank/proc/populate_gas()
return
/obj/item/tank/DoRevenantThrowEffects(atom/target)
if(air_contents)
var/turf/open/location = get_turf(src)
if(istype(location))
location.assume_air(air_contents)
air_contents.clear()
SSair.add_to_active(location)
visible_message("<span class='warning'[src] leaks gas!")
/obj/item/tank/Destroy()
if(air_contents)
qdel(air_contents)
+7 -2
View File
@@ -57,6 +57,9 @@
else
item_state = "[initial(item_state)]"
/obj/item/weldingtool/DoRevenantThrowEffects(atom/target)
attack_self()
/obj/item/weldingtool/update_overlays()
. = ..()
if(change_icons)
@@ -208,12 +211,14 @@
//Switches the welder on
/obj/item/weldingtool/proc/switched_on(mob/user)
if(!status)
to_chat(user, "<span class='warning'>[src] can't be turned on while unsecured!</span>")
if(user)
to_chat(user, "<span class='warning'>[src] can't be turned on while unsecured!</span>")
return
welding = !welding
if(welding)
if(get_fuel() >= 1)
to_chat(user, "<span class='notice'>You switch [src] on.</span>")
if(user)
to_chat(user, "<span class='notice'>You switch [src] on.</span>")
playsound(loc, acti_sound, 50, 1)
force = 15
damtype = "fire"
+2 -2
View File
@@ -62,7 +62,7 @@
return 1
var/mob/living/M = caller
if(!M.ventcrawler && M.mob_size != MOB_SIZE_TINY)
if(!(SEND_SIGNAL(M, COMSIG_CHECK_VENTCRAWL)) && M.mob_size != MOB_SIZE_TINY)
return 0
var/atom/movable/M = caller
if(M && M.pulling)
@@ -91,7 +91,7 @@
return 1
if(M.buckled && istype(M.buckled, /mob/living/simple_animal/bot/mulebot)) // mulebot passenger gets a free pass.
return 1
if(!M.lying && !M.ventcrawler && M.mob_size != MOB_SIZE_TINY) //If your not laying down, or a ventcrawler or a small creature, no pass.
if(!M.lying && !(SEND_SIGNAL(M, COMSIG_CHECK_VENTCRAWL)) && M.mob_size != MOB_SIZE_TINY) //If your not laying down, or a ventcrawler or a small creature, no pass.
return 0
return ..()
+3 -3
View File
@@ -174,7 +174,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
//is_bwoink is TRUE if this ticket was started by an admin PM
/datum/admin_help/New(msg, client/C, is_bwoink)
//clean the input msg
msg = sanitize(copytext_char(msg,1,MAX_MESSAGE_LEN))
msg = copytext_char(msg,1,MAX_MESSAGE_LEN)
if(!msg || !C || !C.mob)
qdel(src)
return
@@ -263,7 +263,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
//message from the initiator without a target, all admins will see this
//won't bug irc
/datum/admin_help/proc/MessageNoRecipient(msg)
msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN))
msg = copytext_char(msg, 1, MAX_MESSAGE_LEN)
var/ref_src = "[REF(src)]"
//Message to be sent to all admins
var/admin_msg = "<span class='adminnotice'><span class='adminhelp'>Ticket [TicketHref("#[id]", ref_src)]</span><b>: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]:</b> <span class='linkify'>[keywords_lookup(msg)]</span></span>"
@@ -523,7 +523,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(handle_spam_prevention(msg,MUTE_ADMINHELP))
return
msg = trim(msg)
msg = sanitize(trim(msg))
if(!msg)
return
+7 -3
View File
@@ -113,7 +113,6 @@
to_chat(src, "<span class='danger'>Error: Use the admin IRC/Discord channel, nerd.</span>", confidential = TRUE)
return
else
//get message text, limit it's length.and clean/escape html
if(!msg)
@@ -128,11 +127,16 @@
else
if(holder)
to_chat(src, "<span class='danger'>Error: Admin-PM: Client not found.</span>", confidential = TRUE)
to_chat(src, "<span class='danger'><b>Message not sent:</b></span><br>[msg]", confidential = TRUE)
to_chat(src, "<span class='danger'><b>Message not sent:</b></span><br>[sanitize(msg)]", confidential = TRUE)
if(recipient_ticket)
recipient_ticket.AddInteraction("<b>No client found, message not sent:</b><br>[msg]")
return
else
//clean the message if it's not sent by a high-rank admin
if(!check_rights(R_SERVER|R_DEBUG,0)||external)//no sending html to the poor bots
msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN))
if(!msg)
return
current_ticket.MessageNoRecipient(msg)
return
@@ -141,7 +145,7 @@
to_chat(src, "<span class='danger'>Error: Admin-PM: You are unable to use admin PM-s (muted).</span>", confidential = TRUE)
return
if (src.handle_spam_prevention(msg,MUTE_ADMINHELP))
if(src.handle_spam_prevention(msg,MUTE_ADMINHELP))
return
//clean the message if it's not sent by a high-rank admin
@@ -9,4 +9,4 @@
/obj/item/organ/heart/gland/ventcrawling/activate()
to_chat(owner, "<span class='notice'>You feel very stretchy.</span>")
owner.ventcrawler = VENTCRAWLER_ALWAYS
owner.AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
@@ -277,3 +277,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
var/datum/antagonist/blob/B = mind.has_antag_datum(/datum/antagonist/blob)
if(!B)
mind.add_antag_datum(/datum/antagonist/blob)
//the same but it's forced to be allowed by default as cameras usually don't allow emoting
/mob/camera/blob/emote(act, m_type=1, message = null, intentional = FALSE, forced = TRUE)
. = ..()
@@ -165,14 +165,16 @@
/datum/clockwork_rite/treat_wounds/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target)
if(!target)
return FALSE
if(!target.all_wounds.len)
if(!target.all_wounds || !target.all_wounds.len)
to_chat(invoker, "<span class='inathneq_small'>This one does not require mending.</span>")
return FALSE
.= ..()
if(!.)
return FALSE
target.adjustToxLoss(10 * target.all_wounds.len)
QDEL_LIST(target.all_wounds)
for(var/i in target.all_wounds)
var/datum/wound/mended = i
mended.remove_wound()
to_chat(target, "<span class='warning'>You feel your wounds heal, but are overcome with deep nausea.</span>")
new /obj/effect/temp_visual/ratvar/sigil/vitality(T)
@@ -203,10 +203,10 @@
to_chat(user, "<span class='warning'>You need to hold the slab in your active hand to recite scripture!</span>")
return FALSE
var/initial_tier = initial(scripture.tier)
if(initial_tier == SCRIPTURE_PERIPHERAL)
if(initial_tier == SCRIPTURE_PERIPHERAL && !issilicon(user)) //Silicons use peripheral scripture & cannot open the slab.
to_chat(user, "<span class='warning'>Nice try using href exploits</span>")
return
if(!GLOB.ratvar_awakens && !no_cost && !SSticker.scripture_states[initial_tier])
if(!GLOB.ratvar_awakens && !no_cost && !SSticker.scripture_states[initial_tier] &&!issilicon(user)) //silicons can't choose their spells, so lets allow them to always cast their assigned ones.
to_chat(user, "<span class='warning'>That scripture is not unlocked, and cannot be recited!</span>")
return FALSE
var/datum/clockwork_scripture/scripture_to_recite = new scripture
@@ -11,7 +11,6 @@
gender = NEUTER
health = 350
maxHealth = 350
ventcrawler = VENTCRAWLER_NONE
density = TRUE
pass_flags = 0
sight = (SEE_TURFS | SEE_OBJS)
@@ -10,6 +10,8 @@
var/give_equipment = TRUE
var/list/researched_knowledge = list()
var/total_sacrifices = 0
var/list/sac_targetted = list() //Which targets did living hearts give them, but they did not sac?
var/list/actually_sacced = list() //Which targets did they actually sac?
var/ascended = FALSE
/datum/antagonist/heretic/admin_add(datum/mind/new_owner,mob/admin)
@@ -175,6 +177,17 @@
knowledge_message += "[EK.name]"
parts += knowledge_message.Join(", ")
parts += "<b>Targets assigned by living hearts, but not sacrificed:</b>"
if(!sac_targetted.len)
parts += "None."
else
parts += sac_targetted.Join(",")
parts += "<b>Sacrifices performed:</b>"
if(!actually_sacced.len)
parts += "<span class='redtext'>None!</span>"
else
parts += actually_sacced.Join(",")
return parts.Join("<br>")
////////////////
// Knowledge //
@@ -213,6 +226,23 @@
if(ascended)
. += 20
/datum/antagonist/heretic/antag_panel()
var/list/parts = list()
parts += ..()
parts += "<b>Targets currently assigned by living hearts (Can give a false negative if they stole someone elses living heart):</b>"
if(!sac_targetted.len)
parts += "None."
else
parts += sac_targetted.Join(",")
parts += "<b>Targets actually sacrificed:</b>"
if(!actually_sacced.len)
parts += "None."
else
parts += actually_sacced.Join(",")
return (parts.Join("<br>") + "<br>")
////////////////
// Objectives //
////////////////
@@ -6,6 +6,17 @@
w_class = WEIGHT_CLASS_SMALL
///Target
var/mob/living/carbon/human/target
var/datum/antagonist/heretic/sac_targetter //The heretic who used this to acquire the current target - gets cleared when target gets sacrificed.
/obj/item/living_heart/Initialize()
. = ..()
GLOB.living_heart_cache.Add(src) //Add is better than +=.
/obj/item/living_heart/Destroy()
GLOB.living_heart_cache.Remove(src)
if(sac_targetter && target)
sac_targetter.sac_targetted.Remove(target.real_name)
return ..()
/obj/item/living_heart/attack_self(mob/user)
. = ..()
@@ -1,6 +1,6 @@
/**
* #Eldritch Knwoledge
* #Eldritch Knowledge
*
* Datum that makes eldritch cultist interesting.
*
@@ -252,6 +252,10 @@
LH.target = null
var/datum/antagonist/heretic/EC = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
EC.actually_sacced.Add(H.real_name)
if(LH.sac_targetter)
LH.sac_targetter.sac_targetted.Remove(H.real_name)
LH.sac_targetter = null
EC.total_sacrifices++
for(var/X in carbon_user.get_all_gear())
if(!istype(X,/obj/item/forbidden_book))
@@ -265,8 +269,14 @@
var/datum/objective/A = new
A.owner = user.mind
var/list/targets = list()
var/list/target_blacklist = list()
for(var/obj/item/living_heart/CLH in GLOB.living_heart_cache)
if(!CLH || !CLH.target || !CLH.target.mind)
continue
target_blacklist.Add(CLH.target.mind)
for(var/i in 0 to 3)
var/datum/mind/targeted = A.find_target()//easy way, i dont feel like copy pasting that entire block of code
var/datum/mind/targeted = A.find_target(blacklist = target_blacklist)//easy way, i dont feel like copy pasting that entire block of code
if(!targeted)
break
targets[targeted.current.real_name] = targeted.current
@@ -274,9 +284,24 @@
if(!LH.target && targets.len)
LH.target = pick(targets) //Tsk tsk, you can and will get another target if you want it or not.
if(LH.target)
target_blacklist = list()
for(var/obj/item/living_heart/CLH in (GLOB.living_heart_cache - LH)) //Recreate blacklist, excluding ourselves.
if(!CLH || !CLH.target || !CLH.target.mind)
continue
target_blacklist.Add(CLH.target.mind)
if(LH.target.mind in target_blacklist) //Someone was faster, or you tried to cheese the system.
to_chat(user, "<span class='warning'>It seems you were too slow, and your target of choice has already been selected by another living heart!</span>")
LH.target = null
qdel(A)
if(LH.target)
to_chat(user,"<span class='warning'>Your new target has been selected, go and sacrifice [LH.target.real_name]!</span>")
var/datum/antagonist/heretic/EC = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
LH.sac_targetter = EC
EC.sac_targetted.Add(LH.target.real_name)
else
to_chat(user,"<span class='warning'>target could not be found for living heart.</span>")
+4 -1
View File
@@ -15,7 +15,6 @@
stop_automated_movement = 1
status_flags = CANPUSH
pass_flags = PASSTABLE
ventcrawler = VENTCRAWLER_ALWAYS
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxHealth = 150
@@ -53,6 +52,10 @@
You can attack any item or dead creature to consume it - creatures will fully restore your health. \
Finally, you can restore yourself to your original form while morphed by shift-clicking yourself.</b>"
/mob/living/simple_animal/hostile/morph/Initialize()
. = ..()
src.AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/mob/living/simple_animal/hostile/morph/examine(mob/user)
if(morphed)
. = form.examine(user)
+49 -7
View File
@@ -72,6 +72,7 @@
var/list/drained_mobs = list() //Cannot harvest the same mob twice
var/perfectsouls = 0 //How many perfect, regen-cap increasing souls the revenant has. //TODO, add objective for getting a perfect soul(s?)
var/generated_objectives_and_spells = FALSE
var/telekinesis_cooldown
/mob/living/simple_animal/revenant/Initialize(mapload)
. = ..()
@@ -93,13 +94,16 @@
/mob/living/simple_animal/revenant/Login()
..()
to_chat(src, "<span class='deadsay'><span class='big bold'>You are a revenant.</span></span>")
to_chat(src, "<b>Your formerly mundane spirit has been infused with alien energies and empowered into a revenant.</b>")
to_chat(src, "<b>You are not dead, not alive, but somewhere in between. You are capable of limited interaction with both worlds.</b>")
to_chat(src, "<b>You are invincible and invisible to everyone but other ghosts. Most abilities will reveal you, rendering you vulnerable.</b>")
to_chat(src, "<b>To function, you are to drain the life essence from humans. This essence is a resource, as well as your health, and will power all of your abilities.</b>")
to_chat(src, "<b><i>You do not remember anything of your past lives, nor will you remember anything about this one after your death.</i></b>")
to_chat(src, "<b>Be sure to read <a href=\"https://tgstation13.org/wiki/Revenant\">the wiki page</a> to learn more.</b>")
var/revenant_greet
revenant_greet += "<span class='deadsay'><span class='big bold'>You are a revenant.</span></span>"
revenant_greet += "<b>Your formerly mundane spirit has been infused with alien energies and empowered into a revenant.</b>"
revenant_greet += "<b>You are not dead, not alive, but somewhere in between. You are capable of limited interaction with both worlds.</b>"
revenant_greet += "<b>You are invincible and invisible to everyone but other ghosts. Most abilities will reveal you, rendering you vulnerable.</b>"
revenant_greet += "<b>To function, you are to drain the life essence from humans. This essence is a resource, as well as your health, and will power all of your abilities.</b>"
revenant_greet += "<b><i>You do not remember anything of your past lives, nor will you remember anything about this one after your death.</i></b>"
revenant_greet += "<b>Be sure to read <a href=\"https://tgstation13.org/wiki/Revenant\">the wiki page</a> to learn more.</b>"
revenant_greet += "<b>You are also able to telekinetically throw objects by clickdragging them.</b>"
to_chat(src, revenant_greet)
if(!generated_objectives_and_spells)
generated_objectives_and_spells = TRUE
mind.assigned_role = ROLE_REVENANT
@@ -317,6 +321,12 @@
to_chat(src, "<span class='revenminor'>Lost [essence_amt]E[source ? " from [source]":""].</span>")
return 1
/mob/living/simple_animal/revenant/proc/telekinesis_cooldown_end()
if(!telekinesis_cooldown)
CRASH("telekinesis_cooldown_end ran when telekinesis_cooldown on [src] was false")
else
telekinesis_cooldown = FALSE
/mob/living/simple_animal/revenant/proc/death_reset()
revealed = FALSE
unreveal_time = 0
@@ -431,6 +441,38 @@
qdel(revenant)
..()
/proc/RevenantThrow(over, mob/user, obj/item/throwable)
var/mob/living/simple_animal/revenant/spooker = user
if(!istype(throwable))
return
if(!throwable.anchored && !spooker.telekinesis_cooldown && spooker.essence > 20)
if(7 < get_dist(throwable, spooker))
return
if(3 >= get_dist(throwable, spooker))
spooker.stun(10)
spooker.reveal(25)
else
spooker.stun(20)
spooker.reveal(50)
spooker.change_essence_amount(-20, FALSE, "telekinesis")
spooker.telekinesis_cooldown = TRUE
throwable.float(TRUE, TRUE)
sleep(20)
throwable.DoRevenantThrowEffects(over)
throwable.throw_at(over, 10, 2)
ADD_TRAIT(throwable, TRAIT_SPOOKY_THROW, "revenant")
log_combat(throwable, over, "spooky telekinesised at", throwable)
var/obj/effect/temp_visual/telekinesis/T = new(get_turf(throwable))
T.color = "#8715b4"
addtimer(CALLBACK(spooker, /mob/living/simple_animal/revenant.proc/telekinesis_cooldown_end), 50)
sleep(5)
throwable.float(FALSE, TRUE)
//Use this for effects you want to happen when a revenant throws stuff, check the TRAIT_SPOOKY_THROW if you want to know if its still being thrown
/obj/item/proc/DoRevenantThrowEffects(atom/target)
return TRUE
//objectives
/datum/objective/revenant
var/targetAmount = 100
+1 -1
View File
@@ -93,7 +93,6 @@
AIStatus = AI_OFF
pass_flags = PASSTABLE
mob_size = MOB_SIZE_TINY
ventcrawler = VENTCRAWLER_ALWAYS
ranged = 1
projectiletype = /obj/item/projectile/beam/disabler
ranged_cooldown_time = 20
@@ -112,6 +111,7 @@
remove_verb(src, /mob/living/verb/pulled)
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_to_hud(src)
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/mob/living/simple_animal/hostile/swarmer/med_hud_set_health()
var/image/holder = hud_list[DIAG_HUD]
@@ -43,7 +43,7 @@
var/list/to_generate = list(
CONTRACT_PAYOUT_LARGE,
CONTRACT_PAYOUT_MEDIUM,
CONTRACT_PAYOUT_SMALL,
CONTRACT_PAYOUT_MEDIUM,
CONTRACT_PAYOUT_SMALL,
CONTRACT_PAYOUT_SMALL,
CONTRACT_PAYOUT_SMALL
+3
View File
@@ -30,6 +30,9 @@
attack(user,user)
return FIRELOSS
/obj/item/assembly/flash/DoRevenantThrowEffects(atom/target)
AOE_flash()
/obj/item/assembly/flash/update_icon(flash = FALSE)
cut_overlays()
attached_overlays = list()
@@ -45,7 +45,7 @@
. = ..()
if(is_type_in_list(src, GLOB.ventcrawl_machinery) && isliving(user))
var/mob/living/L = user
if(L.ventcrawler)
if(SEND_SIGNAL(L, COMSIG_CHECK_VENTCRAWL))
. += "<span class='notice'>Alt-click to crawl through it.</span>"
/obj/machinery/atmospherics/New(loc, process = TRUE, setdir)
@@ -323,7 +323,7 @@
/obj/machinery/atmospherics/AltClick(mob/living/L)
if(is_type_in_typecache(src, GLOB.ventcrawl_machinery))
return L.handle_ventcrawl(src)
return SEND_SIGNAL(L, COMSIG_HANDLE_VENTCRAWL, src)
return ..()
+54 -32
View File
@@ -895,19 +895,23 @@ GLOBAL_LIST_EMPTY(preferences_datums)
continue
var/class_link = ""
var/list/loadout_item = has_loadout_gear(loadout_slot, "[gear.type]")
var/extra_color_data = ""
var/extra_loadout_data = ""
if(loadout_item)
class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=0'"
if(gear.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC)
extra_color_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_color_polychromic=1;loadout_gear_name=[html_encode(gear.name)];'>Color</a>"
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_color_polychromic=1;loadout_gear_name=[html_encode(gear.name)];'>Color</a>"
for(var/loadout_color in loadout_item[LOADOUT_COLOR])
extra_color_data += "<span style='border: 1px solid #161616; background-color: [loadout_color];'>&nbsp;&nbsp;&nbsp;</span>"
extra_loadout_data += "<span style='border: 1px solid #161616; background-color: [loadout_color];'>&nbsp;&nbsp;&nbsp;</span>"
else
var/loadout_color_non_poly = "#FFFFFF"
if(length(loadout_item[LOADOUT_COLOR]))
loadout_color_non_poly = loadout_item[LOADOUT_COLOR][1]
extra_color_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_color=1;loadout_gear_name=[html_encode(gear.name)];'>Color</a>"
extra_color_data += "<span style='border: 1px solid #161616; background-color: [loadout_color_non_poly];'>&nbsp;&nbsp;&nbsp;</span>"
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_color=1;loadout_gear_name=[html_encode(gear.name)];'>Color</a>"
extra_loadout_data += "<span style='border: 1px solid #161616; background-color: [loadout_color_non_poly];'>&nbsp;&nbsp;&nbsp;</span>"
if(gear.loadout_flags & LOADOUT_CAN_NAME)
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_rename=1;loadout_gear_name=[html_encode(gear.name)];'>Name</a> [loadout_item[LOADOUT_CUSTOM_NAME] ? loadout_item[LOADOUT_CUSTOM_NAME] : "N/A"]"
if(gear.loadout_flags & LOADOUT_CAN_DESCRIPTION)
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_redescribe=1;loadout_gear_name=[html_encode(gear.name)];'>Description</a>"
else if((gear_points - gear.cost) < 0)
class_link = "style='white-space:normal;' class='linkOff'"
else if(donoritem)
@@ -916,7 +920,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'"
else
class_link = "style='white-space:normal;background:#eb2e2e;' class='linkOff'"
dat += "<tr style='vertical-align:top;'><td width=15%><a [class_link]>[name]</a>[extra_color_data]</td>"
dat += "<tr style='vertical-align:top;'><td width=15%><a [class_link]>[name]</a>[extra_loadout_data]</td>"
dat += "<td width = 5% style='vertical-align:top'>[gear.cost]</td><td>"
if(islist(gear.restricted_roles))
if(gear.restricted_roles.len)
@@ -929,14 +933,15 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += gear.restricted_roles.Join(";")
dat += "</font>"
if(!istype(gear, /datum/gear/unlockable))
dat += "</td><td><font size=2><i>[gear.description]</i></font></td></tr>"
// the below line essentially means "if the loadout item is picked by the user and has a custom description, give it the custom description, otherwise give it the default description"
dat += "</td><td><font size=2><i>[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description]</i></font></td></tr>"
else
//we add the user's progress to the description assuming they have progress
var/datum/gear/unlockable/unlockable = gear
var/progress_made = unlockable_loadout_data[unlockable.progress_key]
if(!progress_made)
progress_made = 0
dat += "</td><td><font size=2><i>[gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]</i></font></td></tr>"
dat += "</td><td><font size=2><i>[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]</i></font></td></tr>"
dat += "</table>"
if(4) // Content preferences
@@ -2700,7 +2705,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
loadout_data["SAVE_[loadout_slot]"] += list(new_loadout_data) //double packed because it does the union of the CONTENTS of the lists
else
loadout_data["SAVE_[loadout_slot]"] = list(new_loadout_data) //double packed because you somehow had no save slot in your loadout?
if(href_list["loadout_color"])
if(href_list["loadout_color"] || href_list["loadout_color_polychromic"] || href_list["loadout_rename"] || href_list["loadout_redescribe"])
//if the gear doesn't exist, or they don't have it, ignore the request
var/name = html_decode(href_list["loadout_gear_name"])
var/datum/gear/G = GLOB.loadout_items[gear_category][gear_subcategory][name]
if(!G)
@@ -2708,29 +2715,44 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/user_gear = has_loadout_gear(loadout_slot, "[G.type]")
if(!user_gear)
return
if(!length(user_gear[LOADOUT_COLOR]))
user_gear[LOADOUT_COLOR] = list("#FFFFFF")
var/current_color = user_gear[LOADOUT_COLOR][1]
var/new_color = input(user, "Polychromic options", "Choose Color", current_color) as color|null
user_gear[LOADOUT_COLOR][1] = sanitize_hexcolor(new_color, 6, TRUE, current_color)
if(href_list["loadout_color_polychromic"])
var/name = html_decode(href_list["loadout_gear_name"])
var/datum/gear/G = GLOB.loadout_items[gear_category][gear_subcategory][name]
if(!G)
return
var/user_gear = has_loadout_gear(loadout_slot, "[G.type]")
if(!user_gear)
return
var/list/color_options = list()
for(var/i=1, i<=length(G.loadout_initial_colors), i++)
color_options += "Color [i]"
var/color_to_change = input(user, "Polychromic options", "Recolor [name]") as null|anything in color_options
if(color_to_change)
var/color_index = text2num(copytext(color_to_change, 7))
var/current_color = user_gear[LOADOUT_COLOR][color_index]
var/new_color = input(user, "Polychromic options", "Choose [color_to_change] Color", current_color) as color|null
if(new_color)
user_gear[LOADOUT_COLOR][color_index] = sanitize_hexcolor(new_color, 6, TRUE, current_color)
//possible requests: recolor, recolor (polychromic), rename, redescribe
//always make sure the gear allows said request before proceeding
//non-poly coloring can only be done by non-poly items
if(href_list["loadout_color"] && !(G.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC))
if(!length(user_gear[LOADOUT_COLOR]))
user_gear[LOADOUT_COLOR] = list("#FFFFFF")
var/current_color = user_gear[LOADOUT_COLOR][1]
var/new_color = input(user, "Polychromic options", "Choose Color", current_color) as color|null
user_gear[LOADOUT_COLOR][1] = sanitize_hexcolor(new_color, 6, TRUE, current_color)
//poly coloring can only be done by poly items
if(href_list["loadout_color_polychromic"] && (G.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC))
var/list/color_options = list()
for(var/i=1, i<=length(G.loadout_initial_colors), i++)
color_options += "Color [i]"
var/color_to_change = input(user, "Polychromic options", "Recolor [name]") as null|anything in color_options
if(color_to_change)
var/color_index = text2num(copytext(color_to_change, 7))
var/current_color = user_gear[LOADOUT_COLOR][color_index]
var/new_color = input(user, "Polychromic options", "Choose [color_to_change] Color", current_color) as color|null
if(new_color)
user_gear[LOADOUT_COLOR][color_index] = sanitize_hexcolor(new_color, 6, TRUE, current_color)
//both renaming and redescribing strip the input to stop html injection
//renaming is only allowed if it has the flag for it
if(href_list["loadout_rename"] && (G.loadout_flags & LOADOUT_CAN_NAME))
var/new_name = stripped_input(user, "Enter new name for item. Maximum [MAX_NAME_LEN] characters.", "Loadout Item Naming", null, MAX_NAME_LEN)
if(new_name)
user_gear[LOADOUT_CUSTOM_NAME] = new_name
//redescribing is only allowed if it has the flag for it
if(href_list["loadout_redescribe"] && (G.loadout_flags & LOADOUT_CAN_DESCRIPTION)) //redescribe isnt a real word but i can't think of the right term to use
var/new_description = stripped_input(user, "Enter new description for item. Maximum 500 characters.", "Loadout Item Redescribing", null, 500)
if(new_description)
user_gear[LOADOUT_CUSTOM_DESCRIPTION] = new_description
ShowChoices(user)
return 1
@@ -33,6 +33,16 @@
actions_types = list(/datum/action/item_action/adjust)
mutantrace_variation = STYLE_MUZZLE
/obj/item/clothing/mask/surgical/aesthetic
name = "aesthetic sterile mask"
desc = "A sterile mask designed to help prevent the spread of diseases. This one doesn't seem like it does a whole lot, somehow."
flags_inv = HIDEFACE
flags_cover = null
visor_flags_inv = null
visor_flags_cover = null
permeability_coefficient = 1
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
/obj/item/clothing/mask/surgical/attack_self(mob/user)
adjustmask(user)
+6
View File
@@ -237,6 +237,12 @@
icon_state = "choker"
poly_colors = list("#222222")
/obj/item/clothing/neck/necklace/cowbell
name = "cowbell collar"
desc = "Who would wear this? Take this off, you aren't a cow, you're just an awful degenerate."
icon = 'icons/obj/clothing/neck.dmi'
icon_state = "cowbell"
/obj/item/key/collar
name = "Collar Key"
desc = "A key for a tiny lock on a collar or bag."
+163 -1
View File
@@ -79,13 +79,175 @@
if(initial(above_suit))
. += "<span class='notice'>\The [src] can be worn above or below your suit. Alt-click to toggle.</span>"
//////////////
//Waistcoats//
//////////////
/obj/item/clothing/accessory/waistcoat
name = "waistcoat"
name = "black waistcoat"
desc = "For some classy, murderous fun."
icon_state = "waistcoat"
item_state = "waistcoat"
minimize_when_attached = FALSE
/obj/item/clothing/accessory/waistcoat/red
name = "red waistcoat"
icon_state = "waistcoat_red"
item_state = "waistcoat_red"
/obj/item/clothing/accessory/waistcoat/grey
name = "grey waistcoat"
icon_state = "waistcoat_grey"
item_state = "waistcoat_grey"
/obj/item/clothing/accessory/waistcoat/brown
name = "red waistcoat"
icon_state = "waistcoat_brown"
item_state = "waistcoat_brown"
/obj/item/clothing/accessory/waistcoat/sweatervest
name = "black sweatervest"
icon_state = "sweatervest"
item_state = "sweatervest"
/obj/item/clothing/accessory/waistcoat/sweatervest/blue
name = "blue sweatervest"
icon_state = "sweatervest_blue"
item_state = "sweatervest_blue"
/obj/item/clothing/accessory/waistcoat/sweatervest/red
name = "red sweatervest"
icon_state = "sweatervest_red"
item_state = "sweatervest_red"
////////////
//Sweaters//
////////////
/obj/item/clothing/accessory/sweater
name = "grey sweater"
desc = "Nicely comfy and warm!"
icon_state = "sweater"
item_state = "sweater"
minimize_when_attached = FALSE
/obj/item/clothing/accessory/sweater/pink
name = "pink sweater"
icon_state = "sweater_pink"
item_state = "sweater_pink"
/obj/item/clothing/accessory/sweater/heart
name = "heart sweater"
icon_state = "sweater_heart"
item_state = "sweater_heart"
/obj/item/clothing/accessory/sweater/blue
name = "blue sweater"
icon_state = "sweater_blue"
item_state = "sweater_blue"
/obj/item/clothing/accessory/sweater/nt
name = "nanotrasen sweater"
icon_state = "sweater_nt"
item_state = "sweater_nt"
/obj/item/clothing/accessory/sweater/mint
name = "mint sweater"
icon_state = "sweater_mint"
item_state = "sweater_mint"
/obj/item/clothing/accessory/sweater/shoulderless
name = "shoulderless sweater"
icon_state = "sweater_shoulderless"
item_state = "sweater_shoulderless"
/obj/item/clothing/accessory/sweater/uglyxmas
name = "ugly xmas sweater"
icon_state = "sweater_uglyxmas"
item_state = "sweater_uglyxmas"
/obj/item/clothing/accessory/sweater/flower
name = "flower sweater"
icon_state = "sweater_flower"
item_state = "sweater_flower"
////////////////
//Suit Jackets//
////////////////
/obj/item/clothing/accessory/suitjacket
name = "tan suit jacket"
desc = "For those times when you have to attend a fancy business meeting without wearing your pants."
icon_state = "jacket_tan"
item_state = "jacket_tan"
minimize_when_attached = FALSE
/obj/item/clothing/accessory/suitjacket/charcoal
name = "charcoal suit jacket"
icon_state = "jacket_charcoal"
item_state = "jacket_charcoal"
/obj/item/clothing/accessory/suitjacket/navy
name = "navy suit jacket"
icon_state = "jacket_navy"
item_state = "jacket_navy"
/obj/item/clothing/accessory/suitjacket/burgundy
name = "burgundy suit jacket"
icon_state = "jacket_burgundy"
item_state = "jacket_burgundy"
/obj/item/clothing/accessory/suitjacket/checkered
name = "checkered suit jacket"
icon_state = "jacket_checkered"
item_state = "jacket_checkered"
///////////////////////
//Tactical Turtlnecks//
///////////////////////
/obj/item/clothing/accessory/turtleneck
name = "black turtleneck"
desc = "Extra cool. Extra fool."
icon_state = "turtleneck"
item_state = "turtleneck"
minimize_when_attached = FALSE
/obj/item/clothing/accessory/turtleneck/red
name = "red turtleneck"
icon_state = "turtleneck_red"
item_state = "turtleneck_red"
/obj/item/clothing/accessory/turtleneck/comfy
name = "comfy turtleneck"
icon_state = "turtleneck_comfy"
item_state = "turtleneck_comfy"
/obj/item/clothing/accessory/turtleneck/tactifool
name = "black sweaterneck"
desc = "Extra fool. Extra cool."
icon_state = "tactifool"
item_state = "tactifool"
/obj/item/clothing/accessory/turtleneck/tactifool/green
name = "green sweaterneck"
icon_state = "tactifool_green"
item_state = "tactifool_green"
/obj/item/clothing/accessory/turtleneck/tactifool/blue
name = "blue sweaterneck"
icon_state = "tactifool_blue"
item_state = "tactifool_blue"
/obj/item/clothing/accessory/turtleneck/tactifool/syndicate
name = "tactifool sweaterneck"
icon_state = "tactifool_syndicate"
item_state = "tactifool_syndicate"
/////////////////
//Miscellaneous//
/////////////////
/obj/item/clothing/accessory/maidapron
name = "maid apron"
desc = "The best part of a maid costume."
@@ -17,10 +17,7 @@
var/isGlass = TRUE //Whether the 'bottle' is made of glass or not so that milk cartons dont shatter when someone gets hit by it
/obj/item/reagent_containers/food/drinks/on_reagent_change(changetype)
if (gulp_size < 5)
gulp_size = 5
else
gulp_size = max(round(reagents.total_volume / 5), 5)
gulp_size = max(round(reagents.total_volume / 5), 5)
/obj/item/reagent_containers/food/drinks/attack(mob/living/M, mob/user, def_zone)
if(!reagents || !reagents.total_volume)
@@ -52,10 +52,7 @@
/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass/on_reagent_change(changetype)
cut_overlays()
if (gulp_size < 15)
gulp_size = 15
else
gulp_size = max(round(reagents.total_volume / 15), 15)
gulp_size = max(round(reagents.total_volume / 15), 15)
if (reagents.reagent_list.len > 0)
var/datum/reagent/largest_reagent = reagents.get_master_reagent()
@@ -151,10 +151,13 @@
to_chat(user, "<span class='warning'>You need more space cleaner!</span>")
return TRUE
if(istype(O, /obj/item/soap))
var/obj/item/soap/P = O
if(istype(O, /obj/item/soap) || istype(O, /obj/item/reagent_containers/rag))
var/cleanspeed = 50
if(istype(O, /obj/item/soap))
var/obj/item/soap/used_soap = O
cleanspeed = used_soap.cleanspeed
user.visible_message("[user] starts to clean \the [src].", "<span class='notice'>You start to clean \the [src]...</span>")
if(do_after(user, P.cleanspeed, target = src))
if(do_after(user, cleanspeed, target = src))
user.visible_message("[user] has cleaned \the [src].", "<span class='notice'>You clean \the [src].</span>")
dirty = 0
update_icon()
+33 -2
View File
@@ -92,6 +92,11 @@
return BULLET_ACT_HIT
else if(istype(Proj , /obj/item/projectile/energy/florayield))
return myseed.bullet_act(Proj)
else if(istype(Proj , /obj/item/projectile/energy/florarevolution))
if(myseed)
if(myseed.mutatelist.len > 0)
myseed.instability = (myseed.instability/2)
mutatespecie()
else
return ..()
@@ -384,7 +389,6 @@
/obj/machinery/hydroponics/proc/hardmutate()
mutate(4, 10, 2, 4, 50, 4, 10, 3)
/obj/machinery/hydroponics/proc/mutatespecie() // Mutagent produced a new plant!
if(!myseed || dead)
return
@@ -600,7 +604,34 @@
desc = initial(desc)
weedlevel = 0 //Has a side effect of cleaning up those nasty weeds
update_icon()
else if(istype(O, /obj/item/gun/energy/floragun))
var/obj/item/gun/energy/floragun/flowergun = O
if(flowergun.cell.charge < flowergun.cell.maxcharge)
to_chat(user, "<span class='notice'>[flowergun] must be fully charged to lock in a mutation!</span>")
return
if(!myseed)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return
if(myseed.endurance <= 20)
to_chat(user, "<span class='warning'>[myseed.plantname] isn't hardy enough to sequence its mutation!</span>")
return
if(!myseed.mutatelist)
to_chat(user, "<span class='warning'>[myseed.plantname] has nothing else to mutate into!</span>")
return
else
var/list/fresh_mut_list = list()
for(var/muties in myseed.mutatelist)
var/obj/item/seeds/another_mut = new muties
fresh_mut_list[another_mut.plantname] = muties
var/locked_mutation = (input(user, "Select a mutation to lock.", "Plant Mutation Locks") as null|anything in sortList(fresh_mut_list))
if(!user.canUseTopic(src, BE_CLOSE) || !locked_mutation)
return
myseed.mutatelist = list(fresh_mut_list[locked_mutation])
myseed.endurance = (myseed.endurance/2)
flowergun.cell.use(flowergun.cell.charge)
flowergun.update_icon()
to_chat(user, "<span class='notice'>[myseed.plantname]'s mutation was set to [locked_mutation], depleting [flowergun]'s cell!</span>")
return
else
return ..()
@@ -378,7 +378,7 @@ a creative player the means to solve many problems. Circuits are held inside an
// Checks if the target object is reachable. Useful for various manipulators and manipulator-like objects.
/obj/item/integrated_circuit/proc/check_target(atom/target, exclude_contents = FALSE, exclude_components = FALSE, exclude_self = FALSE)
/obj/item/integrated_circuit/proc/check_target(atom/target, exclude_contents = FALSE, exclude_components = FALSE, exclude_self = FALSE, exclude_outside = FALSE)
if(!target)
return FALSE
@@ -394,7 +394,7 @@ a creative player the means to solve many problems. Circuits are held inside an
if(target == assembly.battery)
return FALSE
if(target.Adjacent(acting_object) && isturf(target.loc))
if(!exclude_outside && target.Adjacent(acting_object) && isturf(target.loc))
return TRUE
if(!exclude_contents && (target in acting_object.GetAllContents()))
@@ -186,6 +186,8 @@
AM.forceMove(src)
/obj/item/integrated_circuit/manipulation/grabber/proc/drop(obj/item/AM, turf/T = drop_location())
if(!check_target(AM, FALSE, TRUE, TRUE, TRUE))
return
var/atom/A = get_object()
A.investigate_log("dropped ([AM]) from [src].", INVESTIGATE_CIRCUIT)
AM.forceMove(T)
@@ -60,3 +60,14 @@
/datum/keybinding/carbon/select_harm_intent/down(client/user)
user.mob?.a_intent_change(INTENT_HARM)
return TRUE
/datum/keybinding/carbon/give
hotkey_keys = list("CtrlG")
name = "Give_Item"
full_name = "Give item"
description = "Give the item you're currently holding"
/datum/keybinding/carbon/give/down(client/user)
var/mob/living/carbon/C = user.mob
C.give()
return TRUE
@@ -250,6 +250,8 @@
if(points)
if(I)
I.mining_points += points
if(usr.client)
usr.client.increment_progress("miner", points)
points = 0
else
to_chat(usr, "<span class='warning'>No ID detected.</span>")
-19
View File
@@ -20,25 +20,6 @@
data["totalPoints"] = points
return data
/obj/machinery/mineral/ore_redemption/ui_act(action, params)
if(..())
return
switch(action)
if("Claim")
var/mob/M = usr
var/obj/item/card/id/I = M.get_idcard(TRUE)
if(points)
if(I)
I.mining_points += points
if(usr.client)
usr.client.increment_progress("miner", points)
points = 0
else
to_chat(usr, "<span class='warning'>No ID detected.</span>")
else
to_chat(usr, "<span class='warning'>No points to claim.</span>")
return TRUE
/obj/machinery/point_bank/power_change()
..()
update_icon()
@@ -13,6 +13,10 @@
name = "Bald"
icon_state = "bald"
/datum/sprite_accessory/hair/adhara
name = "Adhara"
icon_state = "hair_adhara"
/datum/sprite_accessory/hair/afro
name = "Afro"
icon_state = "hair_afro"
@@ -29,6 +33,14 @@
name = "Ahoge"
icon_state = "hair_antenna"
/datum/sprite_accessory/hair/amazon
name = "Amazon"
icon_state = "hair_amazon"
/datum/sprite_accessory/hair/anita
name = "Anita"
icon_state = "hair_anita"
/datum/sprite_accessory/hair/balding
name = "Balding Hair"
icon_state = "hair_e"
@@ -61,6 +73,18 @@
name = "Beehive 2"
icon_state = "hair_beehive2"
/datum/sprite_accessory/hair/belenko
name = "Beleneko"
icon_state = "hair_belenko"
/datum/sprite_accessory/hair/belenkotied
name = "Belenko (Tied)"
icon_state = "hair_belenkotied"
/datum/sprite_accessory/hair/belle
name = "Belle"
icon_state = "hair_belle"
/datum/sprite_accessory/hair/bob
name = "Bob Hair"
icon_state = "hair_bob"
@@ -309,6 +333,10 @@
name = "Flow Hair"
icon_state = "hair_f"
/datum/sprite_accessory/hair/fluffy
name = "Fluffy"
icon_state = "hair_fluffy"
/datum/sprite_accessory/hair/fringetail
name = "Fringe Tail"
icon_state = "hair_fringetail"
@@ -365,6 +393,10 @@
name = "Hitop"
icon_state = "hair_hitop"
/datum/sprite_accessory/hair/inkling
name = "Inkling"
icon_state = "hair_inkling"
/datum/sprite_accessory/hair/jade
name = "Jade"
icon_state = "hair_jade"
@@ -373,6 +405,10 @@
name = "Jensen"
icon_state = "hair_jensen"
/datum/sprite_accessory/hair/jessica
name = "Jessica"
icon_state = "hair_jessica"
/datum/sprite_accessory/hair/joestar
name = "Joestar"
icon_state = "hair_joestar"
@@ -389,6 +425,10 @@
name = "Kusanagi"
icon_state = "hair_kusanagi"
/datum/sprite_accessory/hair/kleeia
name = "Kleeia"
icon_state = "hair_kleeia"
/datum/sprite_accessory/hair/long
name = "Long Hair 1"
icon_state = "hair_long"
@@ -445,6 +485,10 @@
name = "Mohawk"
icon_state = "hair_d"
/datum/sprite_accessory/hair/newyou
name = "New You"
icon_state = "hair_newyou"
/datum/sprite_accessory/hair/reversemohawk
name = "Mohawk (Reverse)"
icon_state = "hair_reversemohawk"
@@ -575,6 +619,10 @@
name = "Ponytail (Side) 4"
icon_state = "hair_sidetail4"
/datum/sprite_accessory/hair/sharptail
name = "Ponytail (Sharp)"
icon_state = "hair_sharptail"
/datum/sprite_accessory/hair/spikytail
name = "Ponytail (Spiky)"
icon_state = "hair_spikyponytail"
@@ -679,6 +727,26 @@
name = "Skinhead"
icon_state = "hair_skinhead"
/datum/sprite_accessory/hair/simple
name = "Simple"
icon_state = "hair_simple"
/datum/sprite_accessory/hair/skrellvshort
name = "Skrell Replicant (Very Short)"
icon_state = "hair_skrellvshort"
/datum/sprite_accessory/hair/skrellshort
name = "Skrell Replicant (Short)"
icon_state = "hair_skrellshort"
/datum/sprite_accessory/hair/skrell
name = "Skrell Replicant (Average)"
icon_state = "hair_skrell"
/datum/sprite_accessory/hair/skrelllong
name = "Skrell Replicant (Long)"
icon_state = "hair_skrelllong"
/datum/sprite_accessory/hair/sleaze
name = "Sleaze"
icon_state = "hair_sleaze"
@@ -699,6 +767,10 @@
name = "Spiky 3"
icon_state = "hair_spiky2"
/datum/sprite_accessory/hair/supernova
name = "Supernova"
icon_state = "hair_supernova"
/datum/sprite_accessory/hair/swept
name = "Swept Back Hair"
icon_state = "hair_swept"
@@ -743,6 +815,10 @@
name = "Trimmed (Flat)"
icon_state = "hair_trimflat"
/datum/sprite_accessory/hair/twincurls
name = "Twincurls"
icon_state = "hair_twincurls"
/datum/sprite_accessory/hair/twintails
name = "Twintails"
icon_state = "hair_twintail"
@@ -787,6 +863,10 @@
name = "Very Short Over Eye (Alt)"
icon_state = "hair_veryshortovereyealternate"
/datum/sprite_accessory/hair/vivi
name = "Vivi"
icon_state = "hair_vivi"
/datum/sprite_accessory/hair/volaju
name = "Volaju"
icon_state = "hair_volaju"
@@ -88,6 +88,10 @@
name = "Pantyhose"
icon_state = "pantyhose"
/datum/sprite_accessory/underwear/socks/pantyhose_ripped
name = "Pantyhose - Ripped"
icon_state = "pantyhose_ripped"
/datum/sprite_accessory/underwear/socks/socks_short
name = "Short"
icon_state = "socks_short"
@@ -343,6 +343,20 @@
icon_state = "fishnet_body"
gender = FEMALE
/datum/sprite_accessory/underwear/top/shibari
name = "Shibari Ropes"
icon_state = "shibari"
gender = FEMALE
has_color = TRUE
covers_chest = FALSE
/datum/sprite_accessory/underwear/top/shibari_sleeved
name = "Shibari Ropes - sleeves"
icon_state = "shibari_sleeves"
gender = FEMALE
has_color = TRUE
covers_chest = FALSE
/datum/sprite_accessory/underwear/top/swimsuit
name = "Swimsuit Top"
icon_state = "bra_swimming"
+1 -1
View File
@@ -1,6 +1,6 @@
//This is the proc for gibbing a mob. Cannot gib ghosts.
//added different sort of gibs and animations. N
/mob/proc/gib()
/mob/proc/gib(no_brain, no_organs, no_bodyparts, datum/explosion/was_explosion)
return
//This is the proc for turning a mob into ash. Mostly a copy of gib code (above).
@@ -4,7 +4,6 @@
gender = FEMALE //All xenos are girls!!
dna = null
faction = list(ROLE_ALIEN)
ventcrawler = VENTCRAWLER_ALWAYS
sight = SEE_MOBS
see_in_dark = 4
verb_say = "hisses"
@@ -19,7 +18,6 @@
/// How much brute damage they do to simple animals
var/meleeSlashSAPower = 35
var/obj/item/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/has_fine_manipulation = 0
var/move_delay_add = 0 // movement delay to add
@@ -40,6 +38,8 @@
create_internal_organs()
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
. = ..()
/mob/living/carbon/alien/create_internal_organs()
@@ -2,7 +2,6 @@
//Common stuffs for Praetorian and Queen
icon = 'icons/mob/alienqueen.dmi'
status_flags = 0
ventcrawler = VENTCRAWLER_NONE //pull over that ass too fat
unique_name = 0
pixel_x = -16
bubble_icon = "alienroyal"
+22
View File
@@ -1229,3 +1229,25 @@
*/
/mob/living/carbon/proc/get_biological_state()
return BIO_FLESH_BONE
/mob/living/carbon/altattackby(obj/item/W, mob/living/carbon/user, params)
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
if(W && user.a_intent == INTENT_HELP && W.can_give())
user.give()
return TRUE
/mob/living/carbon/verb/give_verb()
set src in oview(1)
set category = "IC"
set name = "Give"
if(usr.incapacitated() || !usr.Adjacent(src))
return
if(!usr.get_active_held_item()) // Let me know if this has any problems -Yota
return
var/obj/item/I = usr.get_active_held_item()
var/mob/living/carbon/C = usr
if(I.can_give())
C.give()
+9 -4
View File
@@ -17,7 +17,7 @@
if(SSticker.mode)
SSticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
/mob/living/carbon/gib(no_brain, no_organs, no_bodyparts)
/mob/living/carbon/gib(no_brain, no_organs, no_bodyparts, datum/explosion/was_explosion)
var/atom/Tsec = drop_location()
for(var/mob/M in src)
if(M in stomach_contents)
@@ -27,7 +27,7 @@
"<span class='danger'>You burst out of [src]!</span>")
..()
/mob/living/carbon/spill_organs(no_brain, no_organs, no_bodyparts)
/mob/living/carbon/spill_organs(no_brain, no_organs, no_bodyparts, datum/explosion/was_explosion)
var/atom/Tsec = drop_location()
if(!no_bodyparts)
if(no_organs)//so the organs don't get transfered inside the bodyparts we'll drop.
@@ -41,6 +41,8 @@
qdel(O) //so the brain isn't transfered to the head when the head drops.
continue
if(!(O.organ_flags & ORGAN_NO_DISMEMBERMENT) && check_zone(O.zone) == BODY_ZONE_CHEST)
if(was_explosion)
LAZYADD(O.acted_explosions, was_explosion.explosion_id)
O.Remove()
O.forceMove(Tsec)
O.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
@@ -50,13 +52,16 @@
if(I.organ_flags & ORGAN_NO_DISMEMBERMENT || (no_brain && istype(I, /obj/item/organ/brain)) || (no_organs && !istype(I, /obj/item/organ/brain)))
qdel(I)
continue
if(was_explosion)
LAZYADD(I.acted_explosions, was_explosion.explosion_id)
I.Remove()
I.forceMove(Tsec)
I.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
/mob/living/carbon/spread_bodyparts()
/mob/living/carbon/spread_bodyparts(no_brain, no_organs, datum/explosion/was_explosion)
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(was_explosion)
LAZYADD(BP.acted_explosions, was_explosion.explosion_id)
BP.drop_limb()
BP.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
@@ -1796,12 +1796,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
"<span class='warning'>[M] attempted to touch you!</span>", target = M, \
target_message = "<span class='warning'>You attempted to touch [H]!</span>")
return TRUE
if(M == H)
althelp(M, H, attacker_style)
return TRUE
switch(M.a_intent)
if(INTENT_HELP)
if(M == H)
althelp(M, H, attacker_style)
return TRUE
return FALSE
if(INTENT_DISARM)
altdisarm(M, H, attacker_style)
return TRUE
@@ -1987,6 +1985,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.show_message("<span class='notice'>The radiation beam dissipates harmlessly through your body.</span>")
if(/obj/item/projectile/energy/florayield)
H.show_message("<span class='notice'>The radiation beam dissipates harmlessly through your body.</span>")
if(/obj/item/projectile/energy/florarevolution)
H.show_message("<span class='notice'>The radiation beam dissipates harmlessly through your body.</span>")
/datum/species/proc/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
// called before a projectile hit
@@ -801,11 +801,11 @@
/datum/species/golem/plastic/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.ventcrawler = VENTCRAWLER_NUDE
C.AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/datum/species/golem/plastic/on_species_loss(mob/living/carbon/C)
. = ..()
C.ventcrawler = initial(C.ventcrawler)
C.RemoveElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/datum/species/golem/bronze
name = "Bronze Golem"
@@ -64,6 +64,11 @@
H.show_message("<span class='userdanger'>The radiation beam singes you!</span>")
if(/obj/item/projectile/energy/florayield)
H.adjust_nutrition(30, NUTRITION_LEVEL_FULL)
if(/obj/item/projectile/energy/florarevolution)
H.show_message("<span class='notice'>The radiation beam leaves you feeling disoriented!</span>")
H.Dizzy(15)
H.emote("flip")
H.emote("spin")
/datum/species/pod/pseudo_weak
name = "Anthromorphic Plant"
@@ -169,7 +169,7 @@
if(istype(H, /mob/living/simple_animal))
var/mob/living/simple_animal/SA = H
if((human_caster.blood_volume <= (BLOOD_VOLUME_BAD*human_caster.blood_ratio)) || (ventcrawl_nude_only && length(human_caster.get_equipped_items(include_pockets = TRUE))))
SA.ventcrawler = FALSE
SA.RemoveElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
if(transfer_name)
H.name = human_caster.name
@@ -159,3 +159,57 @@
/mob/living/carbon/proc/get_holding_bodypart_of_item(obj/item/I)
var/index = get_held_index_of_item(I)
return index && hand_bodyparts[index]
/**
* Proc called when giving an item to another player
*
* This handles creating an alert and adding an overlay to it
*/
/mob/living/carbon/proc/give(target)
var/obj/item/receiving = get_active_held_item()
if(!receiving)
to_chat(src, "<span class='warning'>You're not holding anything to give!</span>")
return
visible_message("<span class='notice'>[src] is offering [receiving]</span>", \
"<span class='notice'>You offer [receiving]</span>", null, 2)
var/mob/living/carbon/targets = list()
if(!target)
for(var/mob/living/carbon/C in orange(1, src))
if(!CanReach(C))
return
targets += C
else
targets += target
if(!targets)
return
for(var/mob/living/carbon/C in targets)
var/obj/screen/alert/give/G = C.throw_alert("[src]", /obj/screen/alert/give)
if(!G)
return
G.setup(C, src, receiving)
/**
* Proc called when the player clicks the give alert
*
* Handles checking if the player taking the item has open slots and is in range of the giver
* Also deals with the actual transferring of the item to the players hands
* Arguments:
* * giver - The person giving the original item
* * I - The item being given by the giver
*/
/mob/living/carbon/proc/take(mob/living/carbon/giver, obj/item/I)
clear_alert("[giver]")
if(get_dist(src, giver) > 1)
to_chat(src, "<span class='warning'>[giver] is out of range! </span>")
return
if(!I || giver.get_active_held_item() != I)
to_chat(src, "<span class='warning'>[giver] is no longer holding the item they were offering! </span>")
return
if(!get_empty_held_indexes())
to_chat(src, "<span class='warning'>You have no empty hands!</span>")
return
if(!giver.temporarilyRemoveItemFromInventory(I))
visible_message("<span class='notice'>[src] tries to hand over [I] but it's stuck to them....", \
"<span class'notice'> You make a fool of yourself trying to give away an item stuck to your hands")
return
put_in_hands(I)
@@ -6,7 +6,6 @@
icon_state = ""
gender = NEUTER
pass_flags = PASSTABLE
ventcrawler = VENTCRAWLER_NUDE
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab/monkey
@@ -29,6 +28,8 @@
create_bodyparts()
create_internal_organs()
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_NUDE)
. = ..()
if (cubespawned)
+6 -6
View File
@@ -1,4 +1,4 @@
/mob/living/gib(no_brain, no_organs, no_bodyparts)
/mob/living/gib(no_brain, no_organs, no_bodyparts, datum/explosion/was_explosion)
var/prev_lying = lying
if(stat != DEAD)
death(1)
@@ -6,22 +6,22 @@
if(!prev_lying)
gib_animation()
spill_organs(no_brain, no_organs, no_bodyparts)
spill_organs(no_brain, no_organs, no_bodyparts, was_explosion)
if(!no_bodyparts)
spread_bodyparts(no_brain, no_organs)
spread_bodyparts(no_brain, no_organs, was_explosion)
for(var/X in implants)
var/obj/item/implant/I = X
qdel(I)
spawn_gibs(no_bodyparts)
spawn_gibs(no_bodyparts, null, was_explosion)
qdel(src)
/mob/living/proc/gib_animation()
return
/mob/living/proc/spawn_gibs(with_bodyparts, atom/loc_override)
/mob/living/proc/spawn_gibs(with_bodyparts, atom/loc_override, datum/explosion/was_explosion)
var/location = loc_override ? loc_override.drop_location() : drop_location()
if(mob_biotypes & MOB_ROBOTIC)
new /obj/effect/gibspawner/robot(location, src, get_static_viruses())
@@ -31,7 +31,7 @@
/mob/living/proc/spill_organs()
return
/mob/living/proc/spread_bodyparts()
/mob/living/proc/spread_bodyparts(no_brain, no_organs, datum/explosion/was_explosion)
return
/mob/living/dust(just_ash, drop_items, force)
@@ -81,7 +81,6 @@
var/bloodcrawl = 0 //0 No blood crawling, BLOODCRAWL for bloodcrawling, BLOODCRAWL_EAT for crawling+mob devour
var/holder = null //The holder for blood crawling
var/ventcrawler = 0 //0 No vent crawling, 1 vent crawling in the nude, 2 vent crawling always
var/limb_destroyer = 0 //1 Sets AI behavior that allows mobs to target and dismember limbs with their basic attack.
var/mob_size = MOB_SIZE_HUMAN
-4
View File
@@ -17,10 +17,6 @@
if (isturf(T))
update_z(T.z)
//Vents
if(ventcrawler)
to_chat(src, "<span class='notice'>You can ventcrawl! Use alt+click on vents to quickly travel about the station.</span>")
if(ranged_ability)
ranged_ability.add_ranged_ability(src, "<span class='notice'>You currently have <b>[ranged_ability]</b> active!</span>")
if((vore_flags & VORE_INIT) && !(vore_flags & VOREPREF_INIT)) //Vore's been initialized, voreprefs haven't. If this triggers then that means that voreprefs failed to load due to the client being missing.
+3
View File
@@ -1039,3 +1039,6 @@
if(current && eyeobj)
return eyeobj.emote(act, m_type, message, intentional, forced = TRUE)
return ..()
/mob/living/silicon/ai/zMove(dir, feedback = FALSE)
. = eyeobj.zMove(dir, feedback)
@@ -94,6 +94,25 @@
if(ai.master_multicam)
ai.master_multicam.refresh_view()
//it uses setLoc not forceMove, talks to the sillycone and not the camera mob
/mob/camera/aiEye/zMove(dir, feedback = FALSE)
if(dir != UP && dir != DOWN)
return FALSE
var/turf/target = get_step_multiz(src, dir)
if(!target)
if(feedback)
to_chat(ai, "<span class='warning'>There's nowhere to go in that direction!</span>")
return FALSE
if(!canZMove(dir, target))
if(feedback)
to_chat(ai, "<span class='warning'>You couldn't move there!</span>")
return FALSE
setLoc(target, TRUE)
return TRUE
/mob/camera/aiEye/canZMove(direction, turf/target) //cameras do not respect these FLOORS you speak so much of
return TRUE
/mob/camera/aiEye/Move()
return 0
@@ -335,6 +335,11 @@
/mob/living/simple_animal/bot/floorbot/proc/repair(turf/target_turf)
if(check_bot_working(target_turf))
add_to_ignore(target_turf)
target = null
playsound(src, 'sound/effects/whistlereset.ogg', 50, TRUE)
return
if(isspaceturf(target_turf))
//Must be a hull breach or in line mode to continue.
if(!is_hull_breach(target_turf) && !targetdirection)
@@ -418,3 +423,14 @@
repair(A)
else
..()
/**
* Checks a given turf to see if another floorbot is there, working as well.
*/
/mob/living/simple_animal/bot/floorbot/proc/check_bot_working(turf/active_turf)
if(isturf(active_turf))
for(var/mob/living/simple_animal/bot/floorbot/robot in active_turf)
if(robot.mode == BOT_REPAIRING)
return TRUE
return FALSE
@@ -20,7 +20,6 @@
density = FALSE
movement_type = FLYING
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
mob_biotypes = MOB_ORGANIC|MOB_BEAST
gold_core_spawnable = FRIENDLY_SPAWN
@@ -35,6 +34,7 @@
/mob/living/simple_animal/pet/bumbles/Initialize()
. = ..()
add_verb(src, /mob/living/proc/lay_down)
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/mob/living/simple_animal/pet/bumbles/ComponentInitialize()
. = ..()
@@ -20,7 +20,6 @@
density = FALSE
movement_type = FLYING
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
mob_biotypes = MOB_ORGANIC|MOB_BUG
gold_core_spawnable = FRIENDLY_SPAWN
@@ -33,6 +32,7 @@
. = ..()
var/newcolor = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
add_atom_colour(newcolor, FIXED_COLOUR_PRIORITY)
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/mob/living/simple_animal/butterfly/bee_friendly()
return TRUE //treaty signed at the Beeneeva convention
@@ -14,7 +14,6 @@
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
ventcrawler = VENTCRAWLER_ALWAYS
pass_flags = PASSTABLE
mob_size = MOB_SIZE_SMALL
mob_biotypes = MOB_ORGANIC|MOB_BEAST
@@ -40,6 +39,7 @@
/mob/living/simple_animal/pet/cat/Initialize()
. = ..()
add_verb(src, /mob/living/proc/lay_down)
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/mob/living/simple_animal/pet/cat/ComponentInitialize()
. = ..()
@@ -22,7 +22,6 @@
response_harm_simple = "splat"
speak_emote = list("chitters")
density = FALSE
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
gold_core_spawnable = FRIENDLY_SPAWN
verb_say = "chitters"
@@ -32,6 +31,10 @@
var/squish_chance = 50
del_on_death = 1
/mob/living/simple_animal/cockroach/Initialize()
. = ..()
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/mob/living/simple_animal/cockroach/death(gibbed)
if(SSticker.mode && SSticker.mode.station_was_nuked) //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
return
@@ -21,12 +21,15 @@
stop_automated_movement = 1
friendly_verb_continuous = "pinches"
friendly_verb_simple = "pinch"
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
var/obj/item/inventory_head
var/obj/item/inventory_mask
gold_core_spawnable = FRIENDLY_SPAWN
/mob/living/simple_animal/crab/Initialize()
. = ..()
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/mob/living/simple_animal/crab/BiologicalLife(seconds, times_fired)
if(!(. = ..()))
return

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