Merge remote-tracking branch 'origin/master' into rustsql

This commit is contained in:
Letter N
2021-02-19 12:38:32 +08:00
737 changed files with 8763 additions and 3732 deletions
+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))
+4 -1
View File
@@ -290,7 +290,7 @@
#define COMSIG_LIVING_ACTIVE_BLOCK_START "active_block_start" //from base of mob/living/keybind_start_active_blocking(): (obj/item/blocking_item, list/backup_items)
#define COMPONENT_PREVENT_BLOCK_START 1
#define COMSIG_LIVING_ACTIVE_PARRY_START "active_parry_start" //from base of mob/living/initiate_parry_sequence(): (parrying_method, datum/parrying_item_mob_or_art, list/backup_items)
#define COMSIG_LIVING_ACTIVE_PARRY_START "active_parry_start" //from base of mob/living/initiate_parry_sequence(): (parrying_method, datum/parrying_item_mob_or_art, list/backup_items, list/override)
#define COMPONENT_PREVENT_PARRY_START 1
//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS!
@@ -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"
+1
View File
@@ -24,3 +24,4 @@
#define LANGUAGE_STONER "stoner"
#define LANGUAGE_VASSAL "vassal"
#define LANGUAGE_VOICECHANGE "voicechange"
#define LANGUAGE_MULTILINGUAL "multilingual"
+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
+5 -5
View File
@@ -69,8 +69,8 @@
//Checks to determine borg availability depending on the server's config. These are defines in the interest of reducing copypasta
#define BORG_SEC_AVAILABLE (!CONFIG_GET(flag/disable_secborg) && GLOB.security_level >= CONFIG_GET(number/minimum_secborg_alert))
//silicon_priviledges flags
#define PRIVILEDGES_SILICON (1<<0)
#define PRIVILEDGES_PAI (1<<1)
#define PRIVILEDGES_BOT (1<<2)
#define PRIVILEDGES_DRONE (1<<3)
//silicon_privileges flags
#define PRIVILEGES_SILICON (1<<0)
#define PRIVILEGES_PAI (1<<1)
#define PRIVILEGES_BOT (1<<2)
#define PRIVILEGES_DRONE (1<<3)
+2 -2
View File
@@ -204,7 +204,7 @@
///Compile all the overlays for an atom from the cache lists
// |= on overlays is not actually guaranteed to not add same appearances but we're optimistically using it anyway.
#define COMPILE_OVERLAYS(A)\
if (TRUE) {\
do {\
var/list/ad = A.add_overlays;\
var/list/rm = A.remove_overlays;\
if(LAZYLEN(rm)){\
@@ -216,7 +216,7 @@
ad.Cut();\
}\
A.flags_1 &= ~OVERLAY_QUEUED_1;\
}
} while(FALSE)
/**
+2
View File
@@ -197,6 +197,7 @@
#define TRAIT_EMPATH "empath"
#define TRAIT_FRIENDLY "friendly"
#define TRAIT_SNOB "snob"
#define TRAIT_MULTILINGUAL "multilingual"
#define TRAIT_CULT_EYES "cult_eyes"
#define TRAIT_AUTO_CATCH_ITEM "auto_catch_item"
#define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman.
@@ -253,6 +254,7 @@
// item traits
#define TRAIT_NODROP "nodrop"
#define TRAIT_SPOOKY_THROW "spooky_throw"
// common trait sources
#define TRAIT_GENERIC "generic"
+46 -17
View File
@@ -66,25 +66,54 @@
} while(FALSE)
//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
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", 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]]"
/**
* English_list but associative supporting. Higher overhead.
*/
/proc/english_list_assoc(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
var/total = length(input)
switch(total)
if (0)
return "[nothing_text]"
if (1)
var/assoc = input[input[1]] == null? "" : " = [input[input[1]]]"
return "[input[1]][assoc]"
if (2)
var/assoc = input[input[1]] == null? "" : " = [input[input[1]]]"
var/assoc2 = input[input[2]] == null? "" : " = [input[input[2]]]"
return "[input[1]][assoc][and_text][input[2]][assoc2]"
else
var/output = ""
var/index = 1
var/assoc
while (index < total)
if (index == total - 1)
comma_text = final_comma_text
assoc = input[input[index]] == null? "" : " = [input[input[index]]]"
output += "[input[index]][assoc][comma_text]"
++index
assoc = input[input[index]] == null? "" : " = [input[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)
+2 -2
View File
@@ -231,10 +231,10 @@
src_object = window.locked_by.src_object
// Insert src_object info
if(src_object)
entry += "\nUsing: [src_object.type] [REF(src_object)]"
entry += "Using: [src_object.type] [REF(src_object)]"
// Insert message
if(message)
entry += "\n[message]"
entry += "[message]"
WRITE_LOG(GLOB.tgui_log, entry)
/* Close open log handles. This should be called as late as possible, and no logging should hapen after. */
-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)
+1 -1
View File
@@ -10,7 +10,7 @@
announcement += "<br><h2 class='alert'>[html_encode(title)]</h2>"
else if(type == "Captain")
announcement += "<h1 class='alert'>Captain Announces</h1>"
GLOB.news_network.SubmitArticle(text, "Captain's Announcement", "Station Announcements", null)
GLOB.news_network.SubmitArticle(html_encode(text), "Captain's Announcement", "Station Announcements", null)
else
if(!sender_override)
+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
+3 -3
View File
@@ -263,7 +263,7 @@ Turf and target are separate in case you want to teleport some distance from a t
return .
//Returns a list of all items of interest with their name
/proc/getpois(mobs_only=0,skip_mindless=0)
/proc/getpois(mobs_only = FALSE, skip_mindless = FALSE, specify_dead_role = TRUE)
var/list/mobs = sortmobs()
var/list/namecounts = list()
var/list/pois = list()
@@ -277,7 +277,7 @@ Turf and target are separate in case you want to teleport some distance from a t
if(M.real_name && M.real_name != M.name)
name += " \[[M.real_name]\]"
if(M.stat == DEAD)
if(M.stat == DEAD && specify_dead_role)
if(isobserver(M))
name += " \[ghost\]"
else
@@ -1070,7 +1070,7 @@ B --><-- A
return closest_atom
proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
/proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
if (value == FALSE) //nothing should be calling us with a number, so this is safe
value = input("Enter type to find (blank for all, cancel to cancel)", "Search for type") as null|text
if (isnull(value))
+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
+46 -21
View File
@@ -118,27 +118,7 @@
action_intent.hud = src
static_inventory += action_intent
using = new /obj/screen/mov_intent
using.icon = tg_ui_icon_to_cit_ui(ui_style) // CIT CHANGE - overrides mov intent icon
using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
//CITADEL CHANGES - sprint button
using = new /obj/screen/sprintbutton
using.icon = tg_ui_icon_to_cit_ui(ui_style)
using.icon_state = ((owner.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) ? "act_sprint_on" : "act_sprint")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
//END OF CITADEL CHANGES
//same as above but buffer.
sprint_buffer = new /obj/screen/sprint_buffer
sprint_buffer.screen_loc = ui_sprintbufferloc
sprint_buffer.hud = src
static_inventory += sprint_buffer
assert_move_intent_ui(owner, TRUE)
// clickdelay
clickdelay = new
@@ -393,6 +373,51 @@
update_locked_slots()
/datum/hud/human/proc/assert_move_intent_ui(mob/living/carbon/human/owner = mymob, on_new = FALSE)
var/obj/screen/using
// delete old ones
var/list/obj/screen/victims = list()
victims += locate(/obj/screen/mov_intent) in static_inventory
victims += locate(/obj/screen/sprintbutton) in static_inventory
victims += locate(/obj/screen/sprint_buffer) in static_inventory
if(victims)
static_inventory -= victims
if(mymob?.client)
mymob.client.screen -= victims
QDEL_LIST(victims)
// make new ones
// walk/run
using = new /obj/screen/mov_intent
using.icon = tg_ui_icon_to_cit_ui(ui_style) // CIT CHANGE - overrides mov intent icon
using.screen_loc = ui_movi
using.hud = src
using.update_icon()
static_inventory += using
if(!on_new)
owner?.client?.screen += using
if(!CONFIG_GET(flag/sprint_enabled))
return
// sprint button
using = new /obj/screen/sprintbutton
using.icon = tg_ui_icon_to_cit_ui(ui_style)
using.icon_state = ((owner.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) ? "act_sprint_on" : "act_sprint")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
if(!on_new)
owner?.client?.screen += using
// same as above but buffer.
sprint_buffer = new /obj/screen/sprint_buffer
sprint_buffer.screen_loc = ui_sprintbufferloc
sprint_buffer.hud = src
static_inventory += sprint_buffer
if(!on_new)
owner?.client?.screen += using
/datum/hud/human/update_locked_slots()
if(!mymob)
return
+5 -1
View File
@@ -351,6 +351,10 @@
icon = 'icons/mob/screen_midnight.dmi'
icon_state = "running"
/obj/screen/mov_intent/Initialize(mapload)
. = ..()
update_icon()
/obj/screen/mov_intent/Click()
toggle(usr)
@@ -359,7 +363,7 @@
if(MOVE_INTENT_WALK)
icon_state = "walking"
if(MOVE_INTENT_RUN)
icon_state = "running"
icon_state = CONFIG_GET(flag/sprint_enabled)? "running" : "running_nosprint"
/obj/screen/mov_intent/proc/toggle(mob/user)
if(isobserver(user))
@@ -290,6 +290,17 @@
var/datum/movespeed_modifier/config_walk_run/M = get_cached_movespeed_modifier(/datum/movespeed_modifier/config_walk_run/walk)
M.sync()
/datum/config_entry/flag/sprint_enabled
config_entry_value = TRUE
/datum/config_entry/flag/sprint_enabled/ValidateAndSet(str_val)
. = ..()
for(var/datum/hud/human/H)
H.assert_move_intent_ui()
if(!config_entry_value) // disabled
for(var/mob/living/L in world)
L.disable_intentional_sprint_mode()
/datum/config_entry/number/movedelay/sprint_speed_increase
config_entry_value = 1
@@ -484,6 +495,8 @@
/datum/config_entry/flag/modetier_voting
/datum/config_entry/flag/must_be_readied_to_vote_gamemode
/datum/config_entry/number/dropped_modes
config_entry_value = 3
@@ -26,50 +26,6 @@
/datum/config_entry/flag/hub // if the game appears on the hub or not
/datum/config_entry/flag/log_ooc // log OOC channel
/datum/config_entry/flag/log_access // log login/logout
/datum/config_entry/flag/log_say // log client say
/datum/config_entry/flag/log_admin // log admin actions
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_prayer // log prayers
/datum/config_entry/flag/log_law // log lawchanges
/datum/config_entry/flag/log_game // log game events
/datum/config_entry/flag/log_virus // log virology data
/datum/config_entry/flag/log_vote // log voting
/datum/config_entry/flag/log_craft // log crafting
/datum/config_entry/flag/log_whisper // log client whisper
/datum/config_entry/flag/log_attack // log attack messages
/datum/config_entry/flag/log_emote // log emotes
/datum/config_entry/flag/log_adminchat // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
/datum/config_entry/flag/log_pda // log pda messages
/datum/config_entry/flag/log_telecomms // log telecomms messages
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
/datum/config_entry/flag/log_job_debug // log roundstart divide occupations debug information to a file
/datum/config_entry/flag/allow_admin_ooccolor // Allows admins with relevant permissions to have their own ooc colour
/datum/config_entry/flag/allow_vote_restart // allow votes to restart
@@ -477,10 +433,6 @@
/datum/config_entry/string/default_view_square
config_entry_value = "15x15"
/datum/config_entry/flag/log_pictures
/datum/config_entry/flag/picture_logging_camera
/datum/config_entry/number/max_bunker_days
config_entry_value = 7
min_val = 1
@@ -0,0 +1,70 @@
/datum/config_entry/flag/log_ooc // log OOC channel
config_entry_value = TRUE
/datum/config_entry/flag/log_access // log login/logout
config_entry_value = TRUE
/datum/config_entry/flag/log_say // log client say
config_entry_value = TRUE
/datum/config_entry/flag/log_admin // log admin actions
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_prayer // log prayers
config_entry_value = TRUE
/datum/config_entry/flag/log_law // log lawchanges
config_entry_value = TRUE
/datum/config_entry/flag/log_game // log game events
config_entry_value = TRUE
/datum/config_entry/flag/log_virus // log virology data
config_entry_value = TRUE
/datum/config_entry/flag/log_vote // log voting
config_entry_value = TRUE
/datum/config_entry/flag/log_craft // log crafting
config_entry_value = TRUE
/datum/config_entry/flag/log_whisper // log client whisper
config_entry_value = TRUE
/datum/config_entry/flag/log_attack // log attack messages
config_entry_value = TRUE
/datum/config_entry/flag/log_emote // log emotes
config_entry_value = TRUE
/datum/config_entry/flag/log_adminchat // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
config_entry_value = TRUE
/datum/config_entry/flag/log_pda // log pda messages
config_entry_value = TRUE
/datum/config_entry/flag/log_telecomms // log telecomms messages
config_entry_value = TRUE
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
config_entry_value = TRUE
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
config_entry_value = TRUE
/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
config_entry_value = TRUE
/datum/config_entry/flag/log_job_debug // log roundstart divide occupations debug information to a file
config_entry_value = TRUE
/datum/config_entry/flag/log_pictures
/datum/config_entry/flag/picture_logging_camera
/// forces log_href for tgui
/datum/config_entry/flag/emergency_tgui_logging
config_entry_value = FALSE
+45 -15
View File
@@ -490,6 +490,28 @@ SUBSYSTEM_DEF(job)
job.after_spawn(H, M, joined_late) // note: this happens before the mob has a key! M will always have a client, H might not.
equip_loadout(N, H, TRUE)//CIT CHANGE - makes players spawn with in-backpack loadout items properly. A little hacky but it works
if(ishuman(H) && H.client && N)
if(H.client && H.client.prefs && length(H.client.prefs.tcg_cards))
var/obj/item/tcgcard_binder/binder = new(get_turf(H))
if(!H.equip_to_slot_if_possible(binder, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE))
qdel(binder)
else
for(var/card_type in H.client.prefs.tcg_cards)
var/obj/item/tcg_card/card = new(get_turf(H), card_type, H.client.prefs.tcg_cards[card_type])
card.forceMove(binder)
binder.cards.Add(card)
binder.check_for_exodia()
else
if(H && N.client.prefs && length(N.client.prefs.tcg_cards))
var/obj/item/tcgcard_binder/binder = new(get_turf(H))
if(!H.equip_to_slot_if_possible(binder, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE))
qdel(binder)
else
for(var/card_type in N.client.prefs.tcg_cards)
var/obj/item/tcg_card/card = new(get_turf(H), card_type, H.client.prefs.tcg_cards[card_type])
card.forceMove(binder)
binder.cards.Add(card)
return H
/*
/datum/controller/subsystem/job/proc/handle_auto_deadmin_roles(client/C, rank)
@@ -691,21 +713,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
@@ -88,6 +88,7 @@ SUBSYSTEM_DEF(persistence)
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
SavePaintings()
SaveScars()
SaveTCGCards()
/**
* Loads persistent data relevant to the current map: Objects, etc.
@@ -349,3 +350,25 @@ SUBSYSTEM_DEF(persistence)
if(!ending_human.client)
return
ending_human.client.prefs.save_character()
/datum/controller/subsystem/persistence/proc/SaveTCGCards()
for(var/i in GLOB.joined_player_list)
var/mob/living/carbon/human/ending_human = get_mob_by_ckey(i)
if(!istype(ending_human) || !ending_human.mind || !ending_human.client || !ending_human.client.prefs || !ending_human.client.prefs.tcg_cards)
continue
var/mob/living/carbon/human/original_human = ending_human.mind.original_character
if(!original_human || original_human.stat == DEAD || !(original_human == ending_human))
continue
var/obj/item/tcgcard_binder/binder = locate() in ending_human
if(!binder || !length(binder.cards))
continue
var/list/card_types = list()
for(var/obj/item/tcg_card/card in binder.cards)
//if(!card.illegal) //Uncomment if you want to block syndie cards from saving
card_types[card.datum_type] = card.illegal
ending_human.client.prefs.tcg_cards = card_types
ending_human.client.prefs.save_character(TRUE)
+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
+12
View File
@@ -68,6 +68,10 @@ SUBSYSTEM_DEF(vote)
//get the highest number of votes
var/greatest_votes = 0
var/total_votes = 0
if(mode == "gamemode" && CONFIG_GET(flag/must_be_readied_to_vote_gamemode))
for(var/mob/dead/new_player/P in GLOB.player_list)
if(P.ready != PLAYER_READY_TO_PLAY && voted[P.ckey])
choices[choices[voted[P.ckey]]]--
for(var/option in choices)
var/votes = choices[option]
total_votes += votes
@@ -101,6 +105,10 @@ SUBSYSTEM_DEF(vote)
/datum/controller/subsystem/vote/proc/calculate_condorcet_votes(var/blackbox_text)
// https://en.wikipedia.org/wiki/Schulze_method#Implementation
if((mode == "gamemode" || mode == "dynamic") && CONFIG_GET(flag/must_be_readied_to_vote_gamemode))
for(var/mob/dead/new_player/P in GLOB.player_list)
if(P.ready != PLAYER_READY_TO_PLAY && voted[P.ckey])
voted -= P.ckey
var/list/d[][] = new/list(choices.len,choices.len) // the basic vote matrix, how many times a beats b
for(var/ckey in voted)
var/list/this_vote = voted[ckey]
@@ -147,6 +155,10 @@ SUBSYSTEM_DEF(vote)
for(var/choice in choices)
scores_by_choice += "[choice]"
scores_by_choice["[choice]"] = list()
if((mode == "gamemode" || mode == "dynamic") && CONFIG_GET(flag/must_be_readied_to_vote_gamemode))
for(var/mob/dead/new_player/P in GLOB.player_list)
if(P.ready != PLAYER_READY_TO_PLAY && voted[P.ckey])
voted -= P.ckey
for(var/ckey in voted)
var/list/this_vote = voted[ckey]
var/list/pretty_vote = list()
+5 -2
View File
@@ -21,12 +21,15 @@ 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
var/atom/A = parent
A.add_overlay("working")
if(starton)
A.add_overlay("working")
else
tracking = FALSE
A.name = "[initial(A.name)] ([gpstag])"
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/interact)
if(!emp_proof)
+2
View File
@@ -146,9 +146,11 @@
if(!istype(A) || !get_turf(A) || A == src)
return
orbit_target = A
return A.AddComponent(/datum/component/orbiter, src, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
/atom/movable/proc/stop_orbit(datum/component/orbiter/orbits)
orbit_target = null
return // We're just a simple hook
/atom/proc/transfer_observers_to(atom/target)
+1 -1
View File
@@ -37,7 +37,7 @@
qdel(src)
/datum/component/riding/proc/vehicle_mob_buckle(datum/source, mob/living/M, force)
handle_vehicle_offsets()
handle_vehicle_offsets(M.buckled?.dir)
/datum/component/riding/proc/handle_vehicle_layer(dir)
var/atom/movable/AM = parent
@@ -0,0 +1,49 @@
/**
*A storage component to be used on card piles, for use as hands/decks/discard piles. Don't use on something that's not a card pile!
*/
/datum/component/storage/concrete/tcg
display_numerical_stacking = FALSE
max_w_class = WEIGHT_CLASS_TINY
max_items = 30
max_combined_w_class = WEIGHT_CLASS_TINY * 30
///The deck that the card pile is using for FAIR PLAY.
/datum/component/storage/concrete/tcg/can_be_inserted(obj/item/I, stop_messages, mob/M)
. = ..()
return istype(I, /obj/item/tcg_card)
/datum/component/storage/concrete/tcg/PostTransfer()
. = ..()
handle_empty_deck()
/datum/component/storage/concrete/tcg/remove_from_storage(atom/movable/AM, atom/new_location)
. = ..()
handle_empty_deck()
/datum/component/storage/concrete/tcg/ui_show(mob/M)
. = ..()
M.visible_message("<span class='notice'>[M] starts to look through the contents of \the [parent]!</span>", \
"<span class='notice'>You begin looking into the contents of \the [parent]!</span>")
/datum/component/storage/concrete/tcg/close(mob/M)
. = ..()
var/list/card_contents = contents()
var/obj/temp_parent = parent
temp_parent.visible_message("<span class='notice'>\the [parent] is shuffled after looking through it.</span>")
card_contents = shuffle(card_contents)
/datum/component/storage/concrete/tcg/mass_remove_from_storage(atom/target, list/things, datum/progressbar/progress, trigger_on_found)
. = ..()
if(!things.len)
qdel(parent)
/datum/component/storage/concrete/tcg/proc/handle_empty_deck()
var/list/contents = contents()
//You can't have a deck of one card!
if(contents.len == 1)
var/obj/item/tcgcard_deck/deck = parent
var/obj/item/tcg_card/card = contents[1]
remove_from_storage(card, card.drop_location())
card.flipped = deck.flipped
card.update_icon_state()
qdel(parent)
@@ -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)
+4
View File
@@ -85,6 +85,10 @@
to_chat(user, "<span class='warning'>You're not ready to tackle!</span>")
return
if(!user.mob_has_gravity() ||!user.loc.has_gravity() || isspaceturf(user.loc))
to_chat(user, "<span class='warning'>You can't find your footing without gravity!</span>")
return
if(user.has_status_effect(STATUS_EFFECT_TASED)) // can't tackle if you just got tased
to_chat(user, "<span class='warning'>You can't tackle while tased!</span>")
return
+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
@@ -887,7 +887,7 @@
L.remove_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
datum/status_effect/pacify
/datum/status_effect/pacify
id = "pacify"
status_type = STATUS_EFFECT_REPLACE
tick_interval = 1
+6 -1
View File
@@ -11,6 +11,8 @@
var/antag_removal_text // Text will be given to the quirk holder if they get an antag that has it blacklisted.
var/mood_quirk = FALSE //if true, this quirk affects mood and is unavailable if moodlets are disabled
var/mob_trait //if applicable, apply and remove this mob trait
/// should we immediately call on_spawn or add a timer to trigger
var/on_spawn_immediate = TRUE
var/mob/living/quirk_holder
/datum/quirk/New(mob/living/quirk_mob, spawn_effects)
@@ -26,7 +28,10 @@
START_PROCESSING(SSquirks, src)
add()
if(spawn_effects)
on_spawn()
if(on_spawn_immediate)
on_spawn()
else
addtimer(CALLBACK(src, .proc/on_spawn), 0)
addtimer(CALLBACK(src, .proc/post_add), 30)
/datum/quirk/Destroy()
+16
View File
@@ -219,3 +219,19 @@
/datum/quirk/night_vision/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
H.update_sight()
/datum/quirk/multilingual
name = "Multi-Lingual"
desc = "You spent a portion of your life learning to understand an additional language. You may or may not be able to speak it based on your anatomy."
value = 1
mob_trait = TRAIT_MULTILINGUAL
gain_text = "You've learned an extra language!"
lose_text = "You've forgotten your extra language."
/datum/quirk/multilingual/post_add()
var/mob/living/carbon/human/H = quirk_holder
H.grant_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MULTILINGUAL)
/datum/quirk/multilingual/remove()
var/mob/living/carbon/human/H = quirk_holder
H.remove_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MULTILINGUAL)
+1
View File
@@ -184,6 +184,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
gain_text = null // Handled by trauma.
lose_text = null
medical_record_text = "Patient has an untreatable impairment in motor function in the lower extremities."
on_spawn_immediate = FALSE
/datum/quirk/paraplegic/add()
var/datum/brain_trauma/severe/paralysis/paraplegic/T = new()
+1 -1
View File
@@ -168,7 +168,7 @@ GLOBAL_LIST_EMPTY(active_alternate_appearances)
return TRUE
return FALSE
datum/atom_hud/alternate_appearance/basic/onePerson
/datum/atom_hud/alternate_appearance/basic/onePerson
var/mob/seer
/datum/atom_hud/alternate_appearance/basic/onePerson/mobShouldSee(mob/M)
+4 -1
View File
@@ -99,6 +99,9 @@
///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy()
var/list/targeted_by
///Reference to atom being orbited
var/atom/orbit_target
/**
* Called when an atom is created in byond (built in engine proc)
*
@@ -548,7 +551,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)
+10 -3
View File
@@ -31,7 +31,14 @@
var/list/client_mobs_in_contents // This contains all the client mobs within this container
var/list/acted_explosions //for explosion dodging
var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm
var/movement_type = GROUND //Incase you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc.
/**
* In case you have multiple types, you automatically use the most useful one.
* IE: Skating on ice, flippers on water, flying over chasm/space, etc.
* I reccomend you use the movetype_handler system and not modify this directly, especially for living mobs.
*/
var/movement_type = GROUND
var/atom/movable/pulling
var/grab_state = 0
var/throwforce = 0
@@ -567,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)
+3 -3
View File
@@ -133,7 +133,7 @@
icon_state = "knuckles"
w_class = 3
datum/gang_item/clothing/shades //Addition: Why not have cool shades on a gang member anyways?
/datum/gang_item/clothing/shades //Addition: Why not have cool shades on a gang member anyways?
name = "Cool Sunglasses"
id = "glasses"
cost = 5
@@ -313,13 +313,13 @@ datum/gang_item/clothing/shades //Addition: Why not have cool shades on a gang m
permeability_coefficient = 0.01
clothing_flags = NOSLIP
datum/gang_item/equipment/shield
/datum/gang_item/equipment/shield
name = "Riot Shield"
id = "riot_shield"
cost = 25
item_path = /obj/item/shield/riot
datum/gang_item/equipment/gangsheild
/datum/gang_item/equipment/gangsheild
name = "Tower Shield"
id = "metal"
cost = 45 //High block of melee and even higher for bullets
+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:
@@ -33,6 +33,7 @@
/datum/sabotage_objective/processing/check_conditions()
return won
/*
/datum/sabotage_objective/processing/power_sink
name = "Drain at least 100 megajoules of power using a power sink."
sabotage_type = "powersink"
@@ -44,6 +45,7 @@
for(var/s in GLOB.power_sinks)
var/obj/item/powersink/sink = s
won = max(won,sink.power_drained/1e8)
*/
/obj/item/paper/guides/antag/supermatter_sabotage
info = "Ways to sabotage a supermatter:<br>\
+11 -9
View File
@@ -10,7 +10,7 @@
circuit = /obj/item/circuitboard/machine/cell_charger
pass_flags = PASSTABLE
var/obj/item/stock_parts/cell/charging = null
var/charge_rate = 500
var/recharge_coeff = 1
/obj/machinery/cell_charger/update_overlays()
. += ..()
@@ -28,9 +28,10 @@
. = ..()
. += "There's [charging ? "a" : "no"] cell in the charger."
if(charging)
. += "Current charge: [round(charging.percent(), 1)]%."
var/obj/item/stock_parts/cell/C = charging.get_cell()
. += "Current charge: [C.percent()]%."
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Charge rate at <b>[charge_rate]J</b> per cycle.</span>"
. += "<span class='notice'>The status display reads: Charge rate at <b>[recharge_coeff*10]J</b> per cycle.</span>"
/obj/machinery/cell_charger/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stock_parts/cell) && !panel_open)
@@ -122,17 +123,18 @@
charging.emp_act(severity)
/obj/machinery/cell_charger/RefreshParts()
charge_rate = 500
for(var/obj/item/stock_parts/capacitor/C in component_parts)
charge_rate *= C.rating
recharge_coeff = C.rating
/obj/machinery/cell_charger/process()
if(!charging || !anchored || (stat & (BROKEN|NOPOWER)))
return
if(charging.percent() >= 100)
return
use_power(charge_rate)
charging.give(charge_rate) //this is 2558, efficient batteries exist
if(charging)
var/obj/item/stock_parts/cell/C = charging.get_cell()
if(C)
if(C.charge < C.maxcharge)
C.give(C.chargerate * recharge_coeff)
use_power(250 * recharge_coeff)
update_icon()
+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 -1
View File
@@ -151,7 +151,14 @@
var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list
if(!target)
return
target.vars[type] = target.setsubsystem(text2num(value))
value = target.setsubsystem(text2num(value))
switch(type) // Sanity check
if("equipment", "lighting", "environ")
target.vars[type] = value
else
message_admins("Warning: possible href exploit by [key_name(usr)] - attempted to set [type] on [target] to [value]")
log_game("Warning: possible href exploit by [key_name(usr)] - attempted to set [type] on [target] to [value]")
return
target.update_icon()
target.update()
var/setTo = ""
+2
View File
@@ -264,6 +264,8 @@ What a mess.*/
active1 = null
if(!( GLOB.data_core.security.Find(active2) ))
active2 = null
if(!authenticated && href_list["choice"] != "Log In") // logging in is the only action you can do if not logged in
return
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
usr.set_machine(src)
switch(href_list["choice"])
@@ -393,6 +393,27 @@
spark_system.start() //creates some sparks because they look cool
qdel(cover) //deletes the cover - no need on keeping it there!
//turret healing
/obj/machinery/porta_turret/examine(mob/user)
. = ..()
if(obj_integrity < max_integrity)
. += "<span class='notice'>[src] is damaged, use a lit welder to fix it.</span>"
/obj/machinery/porta_turret/welder_act(mob/living/user, obj/item/I)
. = TRUE
if(cover && obj_integrity < max_integrity)
if(!I.tool_start_check(user, amount=0))
return
user.visible_message("[user] is welding the turret.", \
"<span class='notice'>You begin repairing the turret...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 40, volume=50))
obj_integrity = max_integrity
user.visible_message("[user.name] has repaired [src].", \
"<span class='notice'>You finish repairing the turret.</span>")
else
to_chat(user, "<span class='notice'>The turret doesn't need repairing.</span>")
/obj/machinery/porta_turret/process()
//the main machinery process
if(cover == null && anchored) //if it has no cover and is anchored
+6 -4
View File
@@ -97,7 +97,7 @@
icon_state = "mecha_ion"
energy_drain = 120
projectile = /obj/item/projectile/ion
fire_sound = 'sound/weapons/laser.ogg'
fire_sound = 'sound/weapons/IonRifle.ogg'
/obj/item/mecha_parts/mecha_equipment/weapon/energy/tesla
equip_cooldown = 35
@@ -195,7 +195,7 @@
//Base ballistic weapon type
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic
name = "general ballistic weapon"
fire_sound = 'sound/weapons/gunshot.ogg'
fire_sound = 'sound/weapons/lmgshot.ogg'
var/projectiles
var/projectiles_cache //ammo to be loaded in, if possible.
var/projectiles_cache_max
@@ -285,6 +285,7 @@
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot
name = "\improper LBX AC 10 \"Scattershot\""
desc = "A weapon for combat exosuits. Shoots a spread of pellets."
fire_sound = 'sound/weapons/gunshotshotgunshot.ogg'
icon_state = "mecha_scatter"
equip_cooldown = 20
projectile = /obj/item/projectile/bullet/scattershot
@@ -299,6 +300,7 @@
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/seedscatter
name = "\improper Melon Seed \"Scattershot\""
desc = "A weapon for combat exosuits. Shoots a spread of pellets, shaped as seed."
fire_sound = 'sound/weapons/gunshotshotgunshot.ogg'
icon_state = "mecha_scatter"
equip_cooldown = 20
projectile = /obj/item/projectile/bullet/seed
@@ -331,7 +333,7 @@
desc = "A weapon for combat exosuits. Launches light explosive missiles."
icon_state = "mecha_missilerack"
projectile = /obj/item/projectile/bullet/a84mm_he
fire_sound = 'sound/weapons/grenadelaunch.ogg'
fire_sound = 'sound/weapons/rocketlaunch.ogg'
projectiles = 8
projectiles_cache = 0
projectiles_cache_max = 0
@@ -345,7 +347,7 @@
desc = "A weapon for combat exosuits. Launches low-explosive breaching missiles designed to explode only when striking a sturdy target."
icon_state = "mecha_missilerack_six"
projectile = /obj/item/projectile/bullet/a84mm_br
fire_sound = 'sound/weapons/grenadelaunch.ogg'
fire_sound = 'sound/weapons/rocketlaunch.ogg'
projectiles = 6
projectiles_cache = 0
projectiles_cache_max = 0
@@ -81,6 +81,7 @@
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
name = "blood"
icon = 'icons/effects/blood.dmi'
icon_state = "ltrails_1"
desc = "Your instincts say you shouldn't be following these."
random_icon_states = null
+39 -3
View File
@@ -49,6 +49,42 @@
/obj/effect/overlay/vis
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
anchored = TRUE
vis_flags = NONE
var/unused = 0 //When detected to be unused it gets set to world.time, after a while it gets removed
var/cache_expiration = 2 MINUTES // overlays which go unused for 2 minutes get cleaned up
vis_flags = VIS_INHERIT_DIR
///When detected to be unused it gets set to world.time, after a while it gets removed
var/unused = 0
///overlays which go unused for this amount of time get cleaned up
var/cache_expiration = 2 MINUTES
// /obj/effect/overlay/atmos_excited
// name = "excited group"
// icon = null
// icon_state = null
// anchored = TRUE // should only appear in vis_contents, but to be safe
// appearance_flags = RESET_TRANSFORM | TILE_BOUND
// invisibility = INVISIBILITY_ABSTRACT
// mouse_opacity = MOUSE_OPACITY_TRANSPARENT
// layer = ATMOS_GROUP_LAYER
// plane = ATMOS_GROUP_PLANE
// /obj/effect/overlay/light_visible
// name = ""
// icon = 'icons/effects/light_overlays/light_32.dmi'
// icon_state = "light"
// layer = O_LIGHTING_VISUAL_LAYER
// plane = O_LIGHTING_VISUAL_PLANE
// appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
// mouse_opacity = MOUSE_OPACITY_TRANSPARENT
// alpha = 0
// vis_flags = NONE
// /obj/effect/overlay/light_cone
// name = ""
// icon = 'icons/effects/light_overlays/light_cone.dmi'
// icon_state = "light"
// layer = O_LIGHTING_VISUAL_LAYER
// plane = O_LIGHTING_VISUAL_PLANE
// appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
// mouse_opacity = MOUSE_OPACITY_TRANSPARENT
// vis_flags = NONE
// alpha = 110
+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
+1 -1
View File
@@ -166,7 +166,7 @@
last = C
break
obj/item/rcl/proc/getMobhook(mob/to_hook)
/obj/item/rcl/proc/getMobhook(mob/to_hook)
if(listeningTo == to_hook)
return
if(listeningTo)
+21 -15
View File
@@ -10,35 +10,41 @@
/obj/item/armorkit/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
// yeah have fun making subtypes and modifying the afterattack if you want to make variants
// idiot
// - hatter
var/used = FALSE
if(isobj(target) && istype(target, /obj/item/clothing/under))
var/obj/item/clothing/under/C = target
if(C.armor.melee < 10)
C.armor.melee = 10
if(C.damaged_clothes)
to_chat(user,"<span class='warning'>You should repair the damage done to [C] first.</span>")
return
if(C.attached_accessory)
to_chat(user,"<span class='warning'>Kind of hard to sew around [C.attached_accessory].</span>")
return
if(C.armor.getRating("melee") < 10)
C.armor = C.armor.setRating("melee" = 10)
used = TRUE
if(C.armor.laser < 10)
C.armor.laser = 10
if(C.armor.getRating("laser") < 10)
C.armor = C.armor.setRating("laser" = 10)
used = TRUE
if(C.armor.fire < 40)
C.armor.fire = 40
if(C.armor.getRating("fire") < 40)
C.armor = C.armor.setRating("fire" = 40)
used = TRUE
if(C.armor.acid < 10)
C.armor.acid = 10
if(C.armor.getRating("acid") < 10)
C.armor = C.armor.setRating("acid" = 10)
used = TRUE
if(C.armor.bomb < 5)
C.armor.bomb = 5
if(C.armor.getRating("bomb") < 5)
C.armor = C.armor.setRating("bomb" = 5)
used = TRUE
if(used)
user.visible_message("<span class = 'notice'>[user] uses [src] on [C], reinforcing it and tossing the empty case away afterwards.</span>", \
"<span class = 'notice'>You reinforce [C] with [src], making it a little more protective! You toss the empty casing away afterwards.</span>")
C.name = "durathread [C.name]" // this disappears if it gets repaired, which is annoying
user.visible_message("<span class = 'notice'>[user] reinforces [C] with [src].</span>", \
"<span class = 'notice'>You reinforce [C] with [src], making it as protective as a durathread jumpsuit.</span>")
C.name = "durathread [C.name]"
C.upgrade_prefix = "durathread" // god i hope this works
qdel(src)
return
else
to_chat(user, "<span class = 'notice'>You stare at [src] and [C], coming to the conclusion that you probably don't need to reinforce it any further.")
to_chat(user, "<span class = 'notice'>You don't need to reinforce [C] any further.")
return
else
return
+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)
+6 -1
View File
@@ -8,10 +8,12 @@
slot_flags = ITEM_SLOT_BELT
obj_flags = UNIQUE_RENAME
var/gpstag = "COM0"
var/emp_proof = FALSE
var/starton = TRUE
/obj/item/gps/Initialize()
. = ..()
AddComponent(/datum/component/gps/item, gpstag)
AddComponent(/datum/component/gps/item, gpstag, emp_proof, starton)
/obj/item/gps/science
icon_state = "gps-s"
@@ -26,6 +28,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"
@@ -69,7 +69,8 @@ GLOBAL_LIST_INIT(channel_tokens, list(
/obj/item/radio/headset/talk_into(mob/living/M, message, channel, list/spans,datum/language/language)
if (!listening)
return ITALICS | REDUCE_RANGE
return ..()
if (language != /datum/language/signlanguage)
return ..()
/obj/item/radio/headset/can_receive(freq, level, AIuser)
if(ishuman(src.loc))
@@ -283,14 +284,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>")
@@ -208,6 +208,8 @@
return
if(!M.IsVocal())
return
if(language == /datum/language/signlanguage)
return
if(use_command)
spans |= commandspan
@@ -306,18 +306,6 @@ GENETICS SCANNER
if(T.name == "fluffy tongue")
temp_message += " <span class='danger'>Subject is suffering from a fluffified tongue. Suggested cure: Yamerol or a tongue transplant.</span>"
//HECK
else if(istype(O, /obj/item/organ/genital/penis))
var/obj/item/organ/genital/penis/P = O
if(P.length>20)
temp_message += " <span class='info'>Subject has a sizeable gentleman's organ at [P.length] inches.</span>"
else if(istype(O, /obj/item/organ/genital/breasts))
var/obj/item/organ/genital/breasts/Br = O
if(Br.cached_size>5)
temp_message += " <span class='info'>Subject has a sizeable bosom with a [Br.size] cup.</span>"
//GENERAL HANDLER
if(!damage_message)
+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)
+8 -1
View File
@@ -245,6 +245,9 @@
slowdown = 7
breakouttime = 300 //Deciseconds = 30s = 0.5 minute
/obj/item/restraints/legcuffs/proc/on_removed()
return
/obj/item/restraints/legcuffs/beartrap
name = "bear trap"
throw_speed = 1
@@ -376,4 +379,8 @@
icon_state = "ebola"
hitsound = 'sound/weapons/taserhit.ogg'
w_class = WEIGHT_CLASS_SMALL
breakouttime = 60
breakouttime = 25
/obj/item/restraints/legcuffs/bola/energy/on_removed()
do_sparks(1, TRUE, src)
qdel(src)
@@ -44,7 +44,7 @@
icon_state = "warp"
uses = -1
var/total_delay = 10 SECONDS
var/cooldown = 10 SECONDS
var/cooldown = 30 SECONDS
var/last_use = 0
var/list/positions = list()
var/next_prune = 0
+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)
+1 -1
View File
@@ -258,7 +258,7 @@
shield_flags = SHIELD_FLAGS_DEFAULT
max_integrity = 300
obj/item/shield/riot/bullet_proof
/obj/item/shield/riot/bullet_proof
name = "bullet resistant shield"
desc = "A far more frail shield made of resistant plastics and kevlar meant to block ballistics."
armor = list("melee" = 30, "bullet" = 80, "laser" = 0, "energy" = 0, "bomb" = -40, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 50)
+1 -1
View File
@@ -20,7 +20,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
custom_materials = list(/datum/material/iron=1000)
max_amount = 50
attack_verb = list("hit", "bludgeoned", "whacked")
hitsound = 'sound/weapons/grenadelaunch.ogg'
hitsound = 'sound/items/trayhit1.ogg'
embedding = list()
novariants = TRUE
@@ -466,6 +466,7 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \
new/datum/stack_recipe("cardboard cutout", /obj/item/cardboard_cutout, 5), \
new/datum/stack_recipe("pizza box", /obj/item/pizzabox), \
new/datum/stack_recipe("folder", /obj/item/folder), \
new/datum/stack_recipe("cardboard card", /obj/item/cardboard_card, 1), \
// holy fuck why are there so many boxes
new/datum/stack_recipe_list("fancy boxes", list ( \
new /datum/stack_recipe("donut box", /obj/item/storage/fancy/donut_box), \
+1 -1
View File
@@ -639,7 +639,7 @@
new /obj/item/bikehorn(src)
new /obj/item/implanter/sad_trombone(src)
obj/item/storage/backpack/duffelbag/syndie/shredderbundle
/obj/item/storage/backpack/duffelbag/syndie/shredderbundle
desc = "A large duffel bag containing two CX Shredders, some magazines, an elite hardsuit, and a chest rig."
/obj/item/storage/backpack/duffelbag/syndie/shredderbundle/PopulateContents()
+1 -1
View File
@@ -857,7 +857,7 @@
icon_state = "2sheath"
item_state = "katana" //this'll do.
w_class = WEIGHT_CLASS_BULKY
fitting_swords = list(/obj/item/melee/smith/wakizashi, /obj/item/melee/smith/twohand/katana, /obj/item/melee/bokken)
fitting_swords = list(/obj/item/melee/smith/wakizashi, /obj/item/melee/smith/twohand/katana, /obj/item/melee/bokken, /obj/item/katana)
starting_sword = null
/obj/item/storage/belt/sabre/twin/ComponentInitialize()
+1 -1
View File
@@ -275,7 +275,7 @@
for(var/i in 1 to 7)
new /obj/item/grenade/flashbang(src)
obj/item/storage/box/stingbangs
/obj/item/storage/box/stingbangs
name = "box of stingbangs (WARNING)"
desc = "<B>WARNING: These devices are extremely dangerous and can cause severe injuries or death in repeated use.</B>"
icon_state = "secbox"
@@ -526,3 +526,8 @@
new /obj/item/book/granter/martial/carp(src)
new /obj/item/clothing/suit/hooded/carp_costume(src)
new /obj/item/staff/bostaff(src)
/obj/item/storage/box/syndie_kit/sleepytime/cardpack/PopulateContents()
. = ..()
new /obj/item/cardpack/syndicate(src)
new /obj/item/cardpack/syndicate(src)
+23 -13
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."
@@ -269,21 +278,22 @@
icon_state = "refill_donksoft"
var/product = /obj/item/melee/baton/stunsword //what it makes
var/list/fromitem = list(/obj/item/melee/baton, /obj/item/melee/baton/loaded) //what it needs
afterattack(obj/O, mob/user as mob)
if(istype(O, product))
to_chat(user,"<span class='warning'>[O] is already modified!")
else if(O.type in fromitem) //makes sure O is the right thing
var/obj/item/melee/baton/B = O
if(!B.cell) //checks for a powercell in the baton. If there isn't one, continue. If there is, warn the user to take it out
new product(usr.loc) //spawns the product
user.visible_message("<span class='warning'>[user] modifies [O]!","<span class='warning'>You modify the [O]!")
qdel(O) //Gets rid of the baton
qdel(src) //gets rid of the kit
else
to_chat(user,"<span class='warning'>Remove the powercell first!</span>") //We make this check because the stunsword starts without a battery.
/obj/item/ssword_kit/afterattack(obj/O, mob/user as mob)
if(istype(O, product))
to_chat(user,"<span class='warning'>[O] is already modified!")
return
if(O.type in fromitem) //makes sure O is the right thing
var/obj/item/melee/baton/B = O
if(!B.cell) //checks for a powercell in the baton. If there isn't one, continue. If there is, warn the user to take it out
new product(usr.loc) //spawns the product
user.visible_message("<span class='warning'>[user] modifies [O]!","<span class='warning'>You modify the [O]!")
qdel(O) //Gets rid of the baton
qdel(src) //gets rid of the kit
else
to_chat(user, "<span class='warning'> You can't modify [O] with this kit!</span>")
to_chat(user,"<span class='warning'>Remove the powercell first!</span>") //We make this check because the stunsword starts without a battery.
else
to_chat(user, "<span class='warning'> You can't modify [O] with this kit!</span>")
//Makeshift stun baton. Replacement for stun gloves.
/obj/item/melee/baton/cattleprod
+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"
+1 -1
View File
@@ -302,7 +302,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
damtype = STAMINA
attack_verb = list("whacked", "smacked", "struck")
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
hitsound = 'sound/weapons/grenadelaunch.ogg' // no good wood thunk sounds
hitsound = 'sound/weapons/woodbonk.ogg'
var/harm = FALSE // TRUE = brute, FALSE = stam
var/reinforced = FALSE
var/burnt = FALSE
+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 ..()
@@ -56,17 +56,17 @@
desc = "A direction sign, pointing out which way the Cafe is."
icon_state = "direction_cafe"
obj/structure/sign/directions/rooms
/obj/structure/sign/directions/rooms
name = "room"
desc = "Room numbers, helps others find you!"
icon_state = "roomnum"
obj/structure/sign/directions/dorms
/obj/structure/sign/directions/dorms
name = "dorm"
desc = "Dorm numbers, help others find you, or you find others."
icon_state = "dormnum"
obj/structure/sign/directions/cells
/obj/structure/sign/directions/cells
name = "room"
desc = "So the less fortunate amongst us know where they'll be staying."
icon_state = "cellnum"
+9 -7
View File
@@ -1,12 +1,5 @@
/turf/open
plane = FLOOR_PLANE
/// Does dirt buildup happen on us?
var/dirt_buildup_allowed = FALSE
/// Dirt level.
var/dirtyness = 0
/// Dirt level to spawn dirt. Null to use config.
var/dirt_spawn_threshold
/// Slowdown applied to mobs on us.
var/slowdown = 0 //negative for faster, positive for slower
var/postdig_icon_change = FALSE
@@ -18,6 +11,15 @@
var/clawfootstep = null
var/heavyfootstep = null
/// Dirtyness system, cit specific.
/// Does dirt buildup happen on us?
var/dirt_buildup_allowed = FALSE
/// Dirt level.
var/dirtyness = 0
/// Dirt level to spawn dirt. Null to use config.
var/dirt_spawn_threshold
/turf/open/ComponentInitialize()
. = ..()
if(wet)
+25 -4
View File
@@ -10,6 +10,8 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
plane = OPENSPACE_BACKDROP_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
layer = SPLASHSCREEN_LAYER
//I don't know why the others are aligned but I shall do the same.
vis_flags = VIS_INHERIT_ID
/turf/open/transparent/openspace
name = "open space"
@@ -17,6 +19,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
icon_state = "transparent"
baseturfs = /turf/open/transparent/openspace
CanAtmosPassVertical = ATMOS_PASS_YES
intact = FALSE //this means wires go on top
//mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/can_cover_up = TRUE
var/can_build_on = TRUE
@@ -32,10 +35,14 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
/turf/open/transparent/openspace/show_bottom_level()
return FALSE
/turf/open/transparent/openspace/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
/turf/open/openspace/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
. = ..()
vis_contents += GLOB.openspace_backdrop_one_for_all //Special grey square for projecting backdrop darkness filter on it.
return INITIALIZE_HINT_LATELOAD
/turf/open/openspace/LateInitialize()
. = ..()
// AddElement(/datum/element/turf_z_transparency, FALSE)
/turf/open/transparent/openspace/can_have_cabling()
if(locate(/obj/structure/lattice/catwalk, src))
@@ -95,6 +102,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
return
if(L)
if(R.use(1))
qdel(L)
to_chat(user, "<span class='notice'>You construct a catwalk.</span>")
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
new/obj/structure/lattice/catwalk(src)
@@ -148,9 +156,22 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
/turf/open/transparent/openspace/icemoon
name = "ice chasm"
baseturfs = /turf/open/transparent/openspace/icemoon
can_cover_up = TRUE
can_build_on = TRUE
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
planetary_atmos = TRUE
var/replacement_turf = /turf/open/floor/plating/asteroid/snow/icemoon
/turf/open/transparent/openspace/icemoon/Initialize()
. = ..()
var/turf/T = below()
// if(T.flags_1 & NO_RUINS_1)
// ChangeTurf(replacement_turf, null, CHANGETURF_IGNORE_AIR)
// return
// if(!ismineralturf(T))
// return
var/turf/closed/mineral/M = T
M.mineralAmt = 0
M.gets_drilled()
baseturfs = /turf/open/transparent/openspace/icemoon //This is to ensure that IF random turf generation produces a openturf, there won't be other turfs assigned other than openspace.
/turf/open/transparent/openspace/icemoon/can_zFall(atom/movable/A, levels = 1, turf/target)
return TRUE
+6 -1
View File
@@ -66,7 +66,12 @@
/turf/open/transparent/glass/Initialize()
icon_state = "" //Prevent the normal icon from appearing behind the smooth overlays
return ..()
..()
return INITIALIZE_HINT_LATELOAD
/turf/open/floor/glass/LateInitialize()
. = ..()
// AddElement(/datum/element/turf_z_transparency, TRUE)
/turf/open/transparent/glass/wrench_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='notice'>You begin removing glass...</span>")
+1
View File
@@ -20,6 +20,7 @@
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
bullet_bounce_sound = null
vis_flags = VIS_INHERIT_ID //when this be added to vis_contents of something it be associated with something on clicking, important for visualisation of turf in openspace and interraction with openspace that show you turf.
/turf/open/space/basic/New() //Do not convert to Initialize
//This is used to optimize the map loader
+8
View File
@@ -197,6 +197,14 @@ GLOBAL_LIST(topic_status_cache)
/world/Topic(T, addr, master, key)
TGS_TOPIC //redirect to server tools if necessary
if(!SSfail2topic)
return "Server not initialized."
if(SSfail2topic.IsRateLimited(addr))
return "Rate limited."
if(length(T) > CONFIG_GET(number/topic_max_size))
return "Payload too large!"
var/static/list/topic_handlers = TopicHandlers()
var/list/input = params2list(T)
+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)
. = ..()
@@ -149,8 +149,6 @@
if(prob(50))
if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len))
add_objective(new/datum/objective/destroy, TRUE)
else if(prob(30))
add_objective(new/datum/objective/maroon, TRUE)
else
add_objective(new/datum/objective/assassinate, TRUE)
else
@@ -441,19 +441,20 @@
else
kill_objective.find_target()
objectives += kill_objective
else
/*else
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = owner
if(team_mode)
maroon_objective.find_target_by_role(role = ROLE_CHANGELING, role_type = 1, invert = 1)
else
maroon_objective.find_target()
objectives += maroon_objective
objectives += maroon_objective*/
if (!(locate(/datum/objective/escape) in objectives) && escape_objective_possible)
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = owner
identity_theft.target = maroon_objective.target
identity_theft.target = kill_objective.target
identity_theft.update_explanation_text()
objectives += identity_theft
escape_objective_possible = FALSE
@@ -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)
@@ -22,7 +22,7 @@
. = ..()
desc = initial(desc)
obj/item/shield/riot/ratvarian/proc/calc_bash_mult()
/obj/item/shield/riot/ratvarian/proc/calc_bash_mult()
var/bash_mult = 0
if(!dam_absorbed)
return 1
@@ -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
@@ -8,7 +8,7 @@
descname = "Powers Nearby Structures"
name = "Sigil of Transmission"
desc = "Places a sigil that can drain and will store energy to power clockwork structures."
invocations = list("Divinity...", "...power our creations!")
invocations = list("Divinity...", "...power our creations.")
channel_time = 70
power_cost = 200
whispered = TRUE
@@ -28,7 +28,7 @@
descname = "Powered Structure, Delay Emergency Shuttles"
name = "Prolonging Prism"
desc = "Creates a mechanized prism which will delay the arrival of an emergency shuttle by 2 minutes at a massive power cost."
invocations = list("May this prism...", "...grant us time to enact his will!")
invocations = list("May this prism...", "...grant us time to enact his will.")
channel_time = 80
power_cost = 300
object_path = /obj/structure/destructible/clockwork/powered/prolonging_prism
@@ -60,7 +60,7 @@
descname = "Powered Structure, Area Denial"
name = "Mania Motor"
desc = "Creates a mania motor which causes minor damage and a variety of negative mental effects in nearby non-Servant humans, potentially up to and including conversion."
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
invocations = list("May this transmitter...", "...break the will of all who oppose us.")
channel_time = 80
power_cost = 750
object_path = /obj/structure/destructible/clockwork/powered/mania_motor
@@ -83,7 +83,7 @@
descname = "Powered Structure, Teleportation Hub"
name = "Clockwork Obelisk"
desc = "Creates a clockwork obelisk that can broadcast messages over the Hierophant Network or open a Spatial Gateway to any living Servant or clockwork obelisk."
invocations = list("May this obelisk...", "...take us to all places!")
invocations = list("May this obelisk...", "...take us to all places.")
channel_time = 80
power_cost = 300
object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
@@ -163,7 +163,7 @@
descname = "Well-Rounded Combat Construct"
name = "Clockwork Marauder"
desc = "Creates a shell for a clockwork marauder, a balanced frontline construct that can deflect projectiles with its shield."
invocations = list("Arise, avatar of Arbiter!", "Defend the Ark with vengeful zeal.")
invocations = list("Arise, avatar of Arbiter!", "Defend the Ark with vengeful zeal!")
channel_time = 80
power_cost = 8000
creator_message = "<span class='brass'>Your slab disgorges several chunks of replicant alloy that form into a suit of thrumming armor.</span>"
@@ -7,7 +7,7 @@
descname = "Generates Power From Starlight"
name = "Stargazer"
desc = "Forms a weak structure that generates power every second while within three tiles of starlight."
invocations = list("Capture their inferior light for us!")
invocations = list("Capture their inferior light for us.")
channel_time = 50
power_cost = 200
object_path = /obj/structure/destructible/clockwork/stargazer
@@ -16,6 +16,7 @@
usage_tip = "For obvious reasons, make sure to place this near a window or somewhere else that can see space!"
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
whispered = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 1
quickbind = TRUE
@@ -34,7 +35,7 @@
descname = "Power Generation"
name = "Integration Cog"
desc = "Fabricates an integration cog, which can be used on an open APC to replace its innards and passively siphon its power."
invocations = list("Take that which sustains them!")
invocations = list("Take that which sustains them.")
channel_time = 10
power_cost = 10
whispered = TRUE
@@ -55,7 +56,7 @@
descname = "Trap, Stunning"
name = "Sigil of Transgression"
desc = "Wards a tile with a sigil, which will briefly stun the next non-Servant to cross it and apply Belligerent to them."
invocations = list("Divinity, smite...", "...those who trespass here!")
invocations = list("Divinity, smite...", "...those who trespass here.")
channel_time = 50
power_cost = 50
whispered = TRUE
@@ -75,7 +76,7 @@
descname = "Trap, Conversion"
name = "Sigil of Submission"
desc = "Places a luminous sigil that will convert any non-Servants that remain on it for 8 seconds."
invocations = list("Divinity, enlighten...", "...those who trespass here!")
invocations = list("Divinity, enlighten...", "...those who trespass here.")
channel_time = 60
power_cost = 125
whispered = TRUE
@@ -95,7 +96,7 @@
descname = "Short-Range Single-Target Stun"
name = "Kindle"
desc = "Charges your slab with divine energy, allowing you to overwhelm a target with Ratvar's light."
invocations = list("Divinity, show them your light!")
invocations = list("Divinity, show them your light.")
whispered = TRUE
channel_time = 25 //2.5 seconds should be a okay compromise between being able to use it when needed, and not being able to just pause in combat for a second and hardstunning your enemy
power_cost = 125
@@ -118,7 +119,7 @@
descname = "Handcuffs"
name = "Hateful Manacles"
desc = "Forms replicant manacles around a target's wrists that function like handcuffs."
invocations = list("Shackle the heretic!", "Break them in body and spirit!")
invocations = list("Shackle the heretic!", "Break them in body and spirit.")
channel_time = 15
power_cost = 25
whispered = TRUE
@@ -269,7 +270,7 @@
descname = "New Clockwork Slab"
name = "Replicant"
desc = "Creates a new clockwork slab."
invocations = list("Metal, become greater!")
invocations = list("Metal, become greater.")
channel_time = 10
power_cost = 25
whispered = TRUE
@@ -290,7 +291,7 @@
descname = "Limited Xray Vision Glasses"
name = "Wraith Spectacles"
desc = "Fabricates a pair of glasses which grant true sight but cause gradual vision loss."
invocations = list("Show the truth of this world to me!")
invocations = list("Show the truth of this world to me.")
channel_time = 10
power_cost = 50
whispered = TRUE
@@ -310,7 +311,7 @@
name = "Spatial Gateway"
desc = "Tears open a miniaturized gateway in spacetime to any conscious servant that can transport objects or creatures to its destination. \
Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration."
invocations = list("Spatial Gateway...", "...activate!")
invocations = list("Spatial Gateway...", "...activate.")
channel_time = 30
power_cost = 400
whispered = TRUE

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