Merge branch 'master' into abductor-update

This commit is contained in:
Lin
2019-11-11 00:08:59 +00:00
committed by GitHub
1206 changed files with 8463 additions and 9091 deletions
+5
View File
@@ -131,6 +131,11 @@
#define ORGAN_SLOT_BRAIN_ANTISTUN "brain_antistun"
#define ORGAN_SLOT_TAIL "tail"
#define ORGAN_SLOT_PENIS "penis"
#define ORGAN_SLOT_WOMB "womb"
#define ORGAN_SLOT_VAGINA "vagina"
#define ORGAN_SLOT_TESTICLES "testicles"
#define ORGAN_SLOT_BREASTS "breasts"
////organ defines
#define STANDARD_ORGAN_THRESHOLD 100
+18 -22
View File
@@ -15,9 +15,26 @@
#define ui_boxvore "EAST-5:22,SOUTH+1:6"
//Filters
#define CIT_FILTER_STAMINACRIT filter(type="drop_shadow", x=0, y=0, size=-3, border=0, color="#04080F")
#define CIT_FILTER_STAMINACRIT filter(type="drop_shadow", x=0, y=0, size=-3, color="#04080F")
//organ defines
#define VAGINA_LAYER_INDEX 1
#define TESTICLES_LAYER_INDEX 2
#define GENITAL_LAYER_INDEX 3
#define PENIS_LAYER_INDEX 4
#define GENITAL_LAYER_INDEX_LENGTH 4 //keep it updated with each new index added, thanks.
//genital flags
#define GENITAL_BLACKLISTED (1<<0) //for genitals that shouldn't be added to GLOB.genitals_list.
#define GENITAL_INTERNAL (1<<1)
#define GENITAL_HIDDEN (1<<2)
#define GENITAL_THROUGH_CLOTHES (1<<3)
#define GENITAL_FUID_PRODUCTION (1<<4)
#define CAN_MASTURBATE_WITH (1<<5)
#define MASTURBATE_LINKED_ORGAN (1<<6) //used to pass our mission to the linked organ
#define CAN_CLIMAX_WITH (1<<7)
#define COCK_SIZE_MIN 1
#define COCK_SIZE_MAX 20
@@ -50,27 +67,6 @@
#define BREASTS_VOLUME_BASE 50 //base volume for the reagents in the breasts, multiplied by the size then multiplier. 50u for A cups, 850u for HH cups.
#define BREASTS_VOLUME_MULT 1 //global multiplier for breast volume.
#define BREASTS_SIZE_FLAT 0
#define BREASTS_SIZE_A 1
#define BREASTS_SIZE_AA 1.5
#define BREASTS_SIZE_B 2
#define BREASTS_SIZE_BB 2.5
#define BREASTS_SIZE_C 3
#define BREASTS_SIZE_CC 3.5
#define BREASTS_SIZE_D 4
#define BREASTS_SIZE_DD 4.5
#define BREASTS_SIZE_E 5
#define BREASTS_SIZE_EE 5.5
#define BREASTS_SIZE_F 6
#define BREASTS_SIZE_FF 6.5
#define BREASTS_SIZE_G 7
#define BREASTS_SIZE_GG 7.5//Are these even real sizes? The world may never know because cup sizes make no fucking sense.
#define BREASTS_SIZE_H 8
#define BREASTS_SIZE_HH 8.5//Largest size, ever. For now.
#define BREASTS_SIZE_MIN BREASTS_SIZE_A
#define BREASTS_SIZE_DEF BREASTS_SIZE_C
#define BREASTS_SIZE_MAX BREASTS_SIZE_HH
#define MILK_RATE 5
#define MILK_RATE_MULT 1
+10 -1
View File
@@ -70,7 +70,7 @@
#define COMSIG_ATOM_CANREACH "atom_can_reach" //from internal loop in atom/movable/proc/CanReach(): (list/next)
#define COMPONENT_BLOCK_REACH 1
#define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" //from base of atom/screwdriver_act(): (mob/living/user, obj/item/I)
#define COMSIG_ATOM_INTERCEPT_TELEPORT "intercept_teleport" //called when teleporting into a protected turf: (channel, turf/origin)
#define COMSIG_ATOM_INTERCEPT_TELEPORT "intercept_teleport" //called when teleporting into a protected turf: (channel, turf/origin, turf/destination)
#define COMPONENT_BLOCK_TELEPORT 1
/////////////////
#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost" //from base of atom/attack_ghost(): (mob/dead/observer/ghost)
@@ -117,6 +117,7 @@
#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit" //from base of atom/movable/onTransitZ(): (old_z, new_z)
#define COMSIG_MOVABLE_HEAR "movable_hear" //from base of atom/movable/Hear(): (message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
#define COMSIG_MOVABLE_TELEPORTED "movable_teleported" //from base of do_teleport(): (channel, turf/origin, turf/destination)
// /mind signals
#define COMSIG_MIND_TRANSFER "mind_transfer" //from base of mind/transfer_to(): (new_character, old_character)
@@ -153,10 +154,15 @@
#define COMSIG_LIVING_EXTINGUISHED "living_extinguished" //from base of mob/living/ExtinguishMob() (/mob/living)
#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" //from base of mob/living/electrocute_act(): (shock_damage)
#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: ()
#define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override)
// /mob/living/carbon signals
#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity))
// /mob/living/simple_animal/hostile signals
#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget"
#define COMPONENT_HOSTILE_NO_ATTACK 1
// /obj signals
#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
#define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag)
@@ -206,6 +212,9 @@
// /obj/item/pen signals
#define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user)
// /obj/item/projectile signals (sent to the firer)
#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire" // from base of /obj/item/projectile/proc/fire(): (obj/item/projectile, atom/original_target)
// /mob/living/carbon/human signals
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
+5
View File
@@ -0,0 +1,5 @@
#define AFFIX_PREFIX (1 << 0)
#define AFFIX_SUFFIX (1 << 1)
#define AFFIX_GOOD (1 << 0)
#define AFFIX_EVIL (1 << 1)
+3
View File
@@ -243,3 +243,6 @@ GLOBAL_LIST_INIT(security_wintercoat_allowed, typecacheof(list(
//Internals checker
#define GET_INTERNAL_SLOTS(C) list(C.head, C.wear_mask)
//Slots that won't trigger humans' update_genitals() on equip().
GLOBAL_LIST_INIT(no_genitals_update_slots, list(SLOT_L_STORE, SLOT_R_STORE, SLOT_S_STORE, SLOT_IN_BACKPACK, SLOT_LEGCUFFED, SLOT_HANDCUFFED, SLOT_HANDS, SLOT_GENERC_DEXTROUS_STORAGE))
+4
View File
@@ -221,6 +221,10 @@ GLOBAL_LIST_INIT(pointed_types, typecacheof(list(
#define isbodypart(A) (istype(A, /obj/item/bodypart))
#define isprojectile(A) (istype(A, /obj/item/projectile))
#define isgun(A) (istype(A, /obj/item/gun))
//Assemblies
#define isassembly(O) (istype(O, /obj/item/assembly))
+15 -14
View File
@@ -51,24 +51,25 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
//Human Overlays Indexes/////////
//LOTS OF CIT CHANGES HERE. BE CAREFUL WHEN UPSTREAM ADDS MORE LAYERS
#define MUTATIONS_LAYER 31 //mutations. Tk headglows, cold resistance glow, etc
#define GENITALS_BEHIND_LAYER 30 //Some genitalia needs to be behind everything, such as with taurs (Taurs use body_behind_layer
#define BODY_BEHIND_LAYER 29 //certain mutantrace features (tail when looking south) that must appear behind the body parts
#define BODYPARTS_LAYER 28 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag
#define MARKING_LAYER 27 //Matrixed body markings because clashing with snouts?
#define BODY_ADJ_LAYER 26 //certain mutantrace features (snout, body markings) that must appear above the body parts
#define GENITALS_FRONT_LAYER 25 //Draws some genitalia above clothes and the TAUR body if need be.
#define BODY_LAYER 24 //underwear, undershirts, socks, eyes, lips(makeup)
#define FRONT_MUTATIONS_LAYER 23 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes)
#define DAMAGE_LAYER 22 //damage indicators (cuts and burns)
#define UNIFORM_LAYER 21
#define ID_LAYER 20
#define MUTATIONS_LAYER 32 //mutations. Tk headglows, cold resistance glow, etc
#define GENITALS_BEHIND_LAYER 31 //Some genitalia needs to be behind everything, such as with taurs (Taurs use body_behind_layer
#define BODY_BEHIND_LAYER 30 //certain mutantrace features (tail when looking south) that must appear behind the body parts
#define BODYPARTS_LAYER 29 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag
#define MARKING_LAYER 28 //Matrixed body markings because clashing with snouts?
#define BODY_ADJ_LAYER 27 //certain mutantrace features (snout, body markings) that must appear above the body parts
#define GENITALS_FRONT_LAYER 26 //Draws some genitalia above clothes and the TAUR body if need be.
#define BODY_LAYER 25 //underwear, undershirts, socks, eyes, lips(makeup)
#define FRONT_MUTATIONS_LAYER 24 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes)
#define DAMAGE_LAYER 23 //damage indicators (cuts and burns)
#define UNIFORM_LAYER 22
#define ID_LAYER 21
#define HANDS_PART_LAYER 20
#define SHOES_LAYER 19
#define GLOVES_LAYER 18
#define EARS_LAYER 17
#define BODY_TAUR_LAYER 16
#define SUIT_LAYER 15
#define GENITALS_EXPOSED_LAYER 14
#define GLASSES_LAYER 13
#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 11
@@ -82,7 +83,7 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define HANDS_LAYER 3
#define BODY_FRONT_LAYER 2
#define FIRE_LAYER 1 //If you're on fire
#define TOTAL_LAYERS 30 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
#define TOTAL_LAYERS 32 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
//Human Overlay Index Shortcuts for alternate_worn_layer, layers
//Because I *KNOW* somebody will think layer+1 means "above"
@@ -489,7 +490,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define PDAIMG(what) {"<span class="pda16x16 [#what]"></span>"}
//Filters
#define AMBIENT_OCCLUSION list("type"="drop_shadow","x"=0,"y"=-2,"size"=4,"border"=4,"color"="#04080FAA")
#define AMBIENT_OCCLUSION list("type"="drop_shadow","x"=0,"y"=-2,"size"=4,"color"="#04080FAA")
#define EYE_BLUR(size) list("type"="blur", "size"=size)
#define GRAVITY_MOTION_BLUR list("type"="motion_blur","x"=0,"y"=0)
+1 -1
View File
@@ -27,7 +27,7 @@
#define NOBLIUM_RESEARCH_AMOUNT 1000
#define BZ_RESEARCH_SCALE 4
#define BZ_RESEARCH_MAX_AMOUNT 400
#define MIASMA_RESEARCH_AMOUNT 160
#define MIASMA_RESEARCH_AMOUNT 6
#define STIMULUM_RESEARCH_AMOUNT 50
//Plasma fusion properties
#define FUSION_ENERGY_THRESHOLD 3e9 //Amount of energy it takes to start a fusion reaction
+3
View File
@@ -74,6 +74,9 @@
#define STATUS_EFFECT_ICHORIAL_STAIN /datum/status_effect/ichorial_stain //Prevents a servant from being revived by vitality matrices for one minute.
#define STATUS_EFFECT_BREASTS_ENLARGEMENT /datum/status_effect/chem/breast_enlarger //Applied slowdown due to the ominous bulk.
#define STATUS_EFFECT_PENIS_ENLARGEMENT /datum/status_effect/chem/penis_enlarger //More applied slowdown, just like the above.
/////////////
// NEUTRAL //
/////////////
+6 -5
View File
@@ -145,13 +145,14 @@
#define TRAIT_SKITTISH "skittish"
#define TRAIT_POOR_AIM "poor_aim"
#define TRAIT_PROSOPAGNOSIA "prosopagnosia"
#define TRAIT_DRUNK_HEALING "drunk_healing"
#define TRAIT_TAGGER "tagger"
#define TRAIT_PHOTOGRAPHER "photographer"
#define TRAIT_MUSICIAN "musician"
#define TRAIT_CROCRIN_IMMUNE "crocin_immune"
#define TRAIT_DRUNK_HEALING "drunk_healing"
#define TRAIT_TAGGER "tagger"
#define TRAIT_PHOTOGRAPHER "photographer"
#define TRAIT_MUSICIAN "musician"
#define TRAIT_CROCRIN_IMMUNE "crocin_immune"
#define TRAIT_NYMPHO "nymphomania"
#define TRAIT_MASO "masochism"
#define TRAIT_EXHIBITIONIST "exhibitionist"
#define TRAIT_HIGH_BLOOD "high_blood"
#define TRAIT_PHARMA "hepatic_pharmacokinesis"
#define TRAIT_PARA "paraplegic"
+26 -25
View File
@@ -56,6 +56,7 @@ GLOBAL_LIST_EMPTY(ipc_screens_list)
GLOBAL_LIST_EMPTY(ipc_antennas_list)
//Genitals and Arousal Lists
GLOBAL_LIST_EMPTY(genitals_list)
GLOBAL_LIST_EMPTY(cock_shapes_list)//global_lists.dm for the list initializations //Now also _DATASTRUCTURES globals.dm
GLOBAL_LIST_EMPTY(cock_shapes_icons) //Associated list for names->icon_states for cockshapes.
GLOBAL_LIST_EMPTY(gentlemans_organ_names)
@@ -131,53 +132,53 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
SSblackbox.record_feedback("tally", "admin_verb", 1, "TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/mob/living/carbon/proc/has_penis()
if(getorganslot("penis"))//slot shared with ovipositor
if(istype(getorganslot("penis"), /obj/item/organ/genital/penis))
return TRUE
var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_PENIS)
if(G && istype(G, /obj/item/organ/genital/penis))
return TRUE
return FALSE
/mob/living/carbon/proc/has_balls()
if(getorganslot("balls"))
if(istype(getorganslot("balls"), /obj/item/organ/genital/testicles))
return TRUE
var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_TESTICLES)
if(G && istype(G, /obj/item/organ/genital/testicles))
return TRUE
return FALSE
/mob/living/carbon/proc/has_vagina()
if(getorganslot("vagina"))
if(getorganslot(ORGAN_SLOT_VAGINA))
return TRUE
return FALSE
/mob/living/carbon/proc/has_breasts()
if(getorganslot("breasts"))
if(getorganslot(ORGAN_SLOT_BREASTS))
return TRUE
return FALSE
/mob/living/carbon/proc/has_ovipositor()
if(getorganslot("penis"))//shared slot
if(istype(getorganslot("penis"), /obj/item/organ/genital/ovipositor))
return TRUE
var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_PENIS)
if(G && istype(G, /obj/item/organ/genital/ovipositor))
return TRUE
return FALSE
/mob/living/carbon/human/proc/has_eggsack()
if(getorganslot("balls"))
if(istype(getorganslot("balls"), /obj/item/organ/genital/eggsack))
return TRUE
var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_TESTICLES)
if(G && istype(G, /obj/item/organ/genital/eggsack))
return TRUE
return FALSE
/mob/living/carbon/human/proc/is_bodypart_exposed(bodypart)
/mob/living/carbon/proc/is_groin_exposed(var/list/L)
/mob/living/carbon/proc/is_groin_exposed(list/L)
if(!L)
L = get_equipped_items()
for(var/obj/item/I in L)
for(var/A in L)
var/obj/item/I = A
if(I.body_parts_covered & GROIN)
return FALSE
return TRUE
/mob/living/carbon/proc/is_chest_exposed(var/list/L)
/mob/living/carbon/proc/is_chest_exposed(list/L)
if(!L)
L = get_equipped_items()
for(var/obj/item/I in L)
for(var/A in L)
var/obj/item/I = A
if(I.body_parts_covered & CHEST)
return FALSE
return TRUE
@@ -195,9 +196,9 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
message_admins("[src] gave everyone genitals.")
for(var/mob/living/carbon/human/H in GLOB.mob_list)
if(H.gender == MALE)
H.give_penis()
H.give_balls()
H.give_genital(/obj/item/organ/genital/penis)
H.give_genital(/obj/item/organ/genital/testicles)
else
H.give_vagina()
H.give_womb()
H.give_breasts()
H.give_genital(/obj/item/organ/genital/vagina)
H.give_genital(/obj/item/organ/genital/womb)
H.give_genital(/obj/item/organ/genital/breasts)
+4
View File
@@ -72,6 +72,10 @@
var/datum/sprite_accessory/testicles/value = GLOB.balls_shapes_list[K]
GLOB.balls_shapes_icons[K] = value.icon_state
for(var/gpath in subtypesof(/obj/item/organ/genital))
var/obj/item/organ/genital/G = gpath
if(!CHECK_BITFIELD(initial(G.genital_flags), GENITAL_BLACKLISTED))
GLOB.genitals_list[initial(G.name)] = gpath
//END OF CIT CHANGES
//Species
-1
View File
@@ -160,7 +160,6 @@
"xenodorsal" = "Standard",
"xenohead" = "Standard",
"xenotail" = "Xenomorph Tail",
"exhibitionist" = FALSE,
"genitals_use_skintone" = FALSE,
"has_cock" = FALSE,
"cock_shape" = pick(GLOB.cock_shapes_list),
+4 -2
View File
@@ -534,10 +534,12 @@
return parts.Join()
/proc/printobjectives(datum/mind/ply)
/proc/printobjectives(list/objectives)
if(!objectives || !objectives.len)
return
var/list/objective_parts = list()
var/count = 1
for(var/datum/objective/objective in ply.objectives)
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
objective_parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</span>"
else
+1 -1
View File
@@ -759,7 +759,7 @@ GLOBAL_LIST_INIT(can_embed_types, typecacheof(list(
/obj/item/pipe)))
/proc/can_embed(obj/item/W)
if(W.is_sharp())
if(W.get_sharpness())
return 1
if(is_pointed(W))
return 1
+11 -1
View File
@@ -202,4 +202,14 @@ GLOBAL_LIST_INIT(bitfields, list(
"ORGAN_VITAL" = ORGAN_VITAL,
"ORGAN_NO_SPOIL" = ORGAN_NO_SPOIL
),
))
"genital_flags" = list(
"GENITAL_BLACKLISTED" = GENITAL_BLACKLISTED,
"GENITAL_INTERNAL" = GENITAL_INTERNAL,
"GENITAL_HIDDEN" = GENITAL_HIDDEN,
"GENITAL_THROUGH_CLOTHES" = GENITAL_THROUGH_CLOTHES,
"GENITAL_FUID_PRODUCTION" = GENITAL_FUID_PRODUCTION,
"CAN_MASTURBATE_WITH" = CAN_MASTURBATE_WITH,
"MASTURBATE_LINKED_ORGAN" = MASTURBATE_LINKED_ORGAN,
"CAN_CLIMAX_WITH" = CAN_CLIMAX_WITH
)
))
+1 -1
View File
@@ -47,7 +47,7 @@
if(do_mob(user, src, butchering.speed) && Adjacent(I))
butchering.Butcher(user, src)
return 1
else if(I.is_sharp() && !butchering) //give sharp objects butchering functionality, for consistency
else if(I.get_sharpness() && !butchering) //give sharp objects butchering functionality, for consistency
I.AddComponent(/datum/component/butchering, 80 * I.toolspeed)
attackby(I, user, params) //call the attackby again to refresh and do the butchering check again
return
@@ -380,6 +380,22 @@
config_entry_value = 6
min_val = 1
/datum/config_entry/number/dynamic_midround_delay_min
config_entry_value = 15
min_val = 1
/datum/config_entry/number/dynamic_midround_delay_max
config_entry_value = 35
min_val = 1
/datum/config_entry/number/dynamic_latejoin_delay_min
config_entry_value = 5
min_val = 1
/datum/config_entry/number/dynamic_latejoin_delay_max
config_entry_value = 25
min_val = 1
/datum/config_entry/keyed_list/dynamic_cost
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
+1 -1
View File
@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(chat)
name = "Chat"
flags = SS_TICKER|SS_NO_INIT
flags = SS_TICKER
wait = 1
priority = FIRE_PRIORITY_CHAT
init_order = INIT_ORDER_CHAT
+11 -11
View File
@@ -4,7 +4,7 @@ SUBSYSTEM_DEF(job)
flags = SS_NO_FIRE
var/list/occupations = list() //List of all jobs
var/list/name_occupations = list() //Dict of all jobs, keys are titles
var/list/datum/job/name_occupations = list() //Dict of all jobs, keys are titles
var/list/type_occupations = list() //Dict of all jobs, keys are types
var/list/unassigned = list() //Players who need jobs
var/initial_players_to_assign = 0 //used for checking against population caps
@@ -14,6 +14,8 @@ SUBSYSTEM_DEF(job)
var/overflow_role = "Assistant"
var/list/level_order = list(JP_HIGH,JP_MEDIUM,JP_LOW)
/datum/controller/subsystem/job/Initialize(timeofday)
SSmapping.HACK_LoadMapConfig()
if(!occupations.len)
@@ -119,7 +121,7 @@ SUBSYSTEM_DEF(job)
if(player.mind && job.title in player.mind.restricted_roles)
JobDebug("FOC incompatible with antagonist role, Player: [player]")
continue
if(player.client.prefs.job_preferences["[job.title]"] == level)
if(player.client.prefs.job_preferences[job.title] == level)
JobDebug("FOC pass, Player: [player], Level:[level]")
candidates += player
return candidates
@@ -181,7 +183,7 @@ SUBSYSTEM_DEF(job)
//it locates a head or runs out of levels to check
//This is basically to ensure that there's atleast a few heads in the round
/datum/controller/subsystem/job/proc/FillHeadPosition()
for(var/level = 1 to 3)
for(var/level in level_order)
for(var/command_position in GLOB.command_positions)
var/datum/job/job = GetJob(command_position)
if(!job)
@@ -218,7 +220,7 @@ SUBSYSTEM_DEF(job)
if(!job)
return 0
for(var/i = job.total_positions, i > 0, i--)
for(var/level = 1 to 3)
for(var/level in level_order)
var/list/candidates = list()
candidates = FindOccupationCandidates(job, level)
if(candidates.len)
@@ -304,8 +306,7 @@ SUBSYSTEM_DEF(job)
// Loop through all levels from high to low
var/list/shuffledoccupations = shuffle(occupations)
var/list/levels = list(JP_HIGH,JP_MEDIUM,JP_LOW)
for(var/level in levels)
for(var/level in level_order)
//Check the head jobs first each level
CheckHeadPositions(level)
@@ -334,7 +335,7 @@ SUBSYSTEM_DEF(job)
if(job.required_playtime_remaining(player.client))
JobDebug("DO player not enough xp, Player: [player], Job:[job.title]")
continue
if(!player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
JobDebug("DO non-human failed, Player: [player], Job:[job.title]")
continue
@@ -344,7 +345,7 @@ SUBSYSTEM_DEF(job)
continue
// If the player wants that job on this level, then try give it to him.
if(player.client.prefs.job_preferences["[job.title]"] == level)
if(player.client.prefs.job_preferences[job.title] == level)
// If the job isn't filled
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
JobDebug("DO pass, Player: [player], Level:[level], Job:[job.title]")
@@ -475,7 +476,6 @@ SUBSYSTEM_DEF(job)
to_chat(M, "<b>[job.custom_spawn_text]</b>")
if(CONFIG_GET(number/minimal_access_threshold))
to_chat(M, "<span class='notice'><B>As this station was initially staffed with a [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.</B></span>")
if(job && H)
if(job.dresscodecompliant)// CIT CHANGE - dress code compliance
equip_loadout(N, H) // CIT CHANGE - allows players to spawn with loadout items
@@ -551,7 +551,7 @@ SUBSYSTEM_DEF(job)
if(job.required_playtime_remaining(player.client))
young++
continue
switch(player.client.prefs.job_preferences["[job.title]"])
switch(player.client.prefs.job_preferences[job.title])
if(JP_HIGH)
high++
if(JP_MEDIUM)
@@ -698,4 +698,4 @@ SUBSYSTEM_DEF(job)
. |= player.mind
/datum/controller/subsystem/job/proc/JobDebug(message)
log_job_debug(message)
log_job_debug(message)
+7
View File
@@ -37,6 +37,7 @@ SUBSYSTEM_DEF(shuttle)
var/points = 5000 //number of trade-points we have
var/centcom_message = "" //Remarks from CentCom on how well you checked the last order.
var/list/discoveredPlants = list() //Typepaths for unusual plants we've already sent CentCom, associated with their potencies
var/passive_supply_points_per_minute = 750
var/list/supply_packs = list()
var/list/shoppinglist = list()
@@ -111,6 +112,12 @@ SUBSYSTEM_DEF(shuttle)
qdel(T, force=TRUE)
CheckAutoEvac()
//Cargo stuff start
var/fire_time_diff = max(0, world.time - last_fire) //Don't want this to be below 0, seriously.
var/point_gain = (fire_time_diff / 600) * passive_supply_points_per_minute
points += point_gain
//Cargo stuff end
if(!SSmapping.clearing_reserved_turfs)
while(transit_requesters.len)
var/requester = popleft(transit_requesters)
+8
View File
@@ -245,6 +245,14 @@
/datum/action/item_action/toggle_helmet_light
name = "Toggle Helmet Light"
/datum/action/item_action/toggle_welding_screen
name = "Toggle Welding Screen"
/datum/action/item_action/toggle_welding_screen/Trigger()
var/obj/item/clothing/head/hardhat/weldhat/H = target
if(istype(H))
H.toggle_welding_screen(owner)
/datum/action/item_action/toggle_headphones
name = "Toggle Headphones"
desc = "UNTZ UNTZ UNTZ"
+45
View File
@@ -0,0 +1,45 @@
/datum/component/bane
dupe_mode = COMPONENT_DUPE_ALLOWED
var/mobtype
var/speciestype
var/damage_multiplier
/datum/component/bane/Initialize(mobtype, damage_multiplier=1)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
if(ispath(mobtype, /mob/living))
src.mobtype = mobtype
else if(ispath(mobtype, /datum/species))
speciestype = mobtype
else
return COMPONENT_INCOMPATIBLE
src.damage_multiplier = damage_multiplier
/datum/component/bane/RegisterWithParent()
if(speciestype)
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/speciesCheck)
else
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/mobCheck)
/datum/component/bane/UnregisterFromParent()
UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK)
/datum/component/bane/proc/speciesCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
if(!is_species(target, speciestype))
return
activate(source, target, user)
/datum/component/bane/proc/mobCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
if(!istype(target, mobtype))
return
activate(source, target, user)
/datum/component/bane/proc/activate(obj/item/source, mob/living/target, mob/attacker)
if(attacker.a_intent != INTENT_HARM)
return
var/extra_damage = max(0, source.force * damage_multiplier)
target.apply_damage(extra_damage, source.damtype, attacker.zone_selected)
+140
View File
@@ -0,0 +1,140 @@
/datum/component/fantasy
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
var/quality
var/canFail
var/announce
var/originalName
var/list/affixes
var/list/appliedComponents
var/static/list/affixListing
/datum/component/fantasy/Initialize(quality, list/affixes = list(), canFail=FALSE, announce=FALSE)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
src.quality = quality || randomQuality()
src.canFail = canFail
src.announce = announce
src.affixes = affixes
appliedComponents = list()
randomAffixes()
/datum/component/fantasy/Destroy()
unmodify()
affixes = null
return ..()
/datum/component/fantasy/RegisterWithParent()
var/obj/item/master = parent
originalName = master.name
modify()
/datum/component/fantasy/UnregisterFromParent()
unmodify()
/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, list/arguments)
unmodify()
if(newComp)
quality += newComp.quality
canFail = newComp.canFail
announce = newComp.announce
else
arguments.len = 5 // This is done to replicate what happens when an arglist smaller than the necessary arguments is given
quality += arguments[1]
canFail = arguments[4] || canFail
announce = arguments[5] || announce
modify()
/datum/component/fantasy/proc/randomQuality()
var/quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0)
if(prob(50))
quality = -quality
return quality
/datum/component/fantasy/proc/randomAffixes(force)
if(!affixListing)
affixListing = list()
for(var/T in subtypesof(/datum/fantasy_affix))
var/datum/fantasy_affix/affix = new T
affixListing[affix] = affix.weight
if(length(affixes))
if(!force)
return
affixes = list()
var/alignment
if(quality >= 0)
alignment |= AFFIX_GOOD
if(quality <= 0)
alignment |= AFFIX_EVIL
var/usedSlots = NONE
for(var/i in 1 to max(1, abs(quality))) // We want at least 1 affix applied
var/datum/fantasy_affix/affix = pickweight(affixListing)
if(affix.placement & usedSlots)
continue
if(!(affix.alignment & alignment))
continue
if(!affix.validate(src))
continue
affixes += affix
usedSlots |= affix.placement
/datum/component/fantasy/proc/modify()
var/obj/item/master = parent
master.force = max(0, master.force + quality)
master.throwforce = max(0, master.throwforce + quality)
master.armor = master.armor?.modifyAllRatings(quality)
var/newName = originalName
for(var/i in affixes)
var/datum/fantasy_affix/affix = i
newName = affix.apply(src, newName)
if(quality != 0)
newName = "[newName] [quality > 0 ? "+" : ""][quality]"
if(canFail && prob((quality - 9)*10))
var/turf/place = get_turf(parent)
place.visible_message("<span class='danger'>[parent] <span class='blue'>violently glows blue</span> for a while, then evaporates.</span>")
master.burn()
return
else if(announce)
announce()
master.name = newName
/datum/component/fantasy/proc/unmodify()
var/obj/item/master = parent
for(var/i in affixes)
var/datum/fantasy_affix/affix = i
affix.remove(src)
for(var/i in appliedComponents)
qdel(i)
master.force = max(0, master.force - quality)
master.throwforce = max(0, master.throwforce - quality)
master.armor = master.armor?.modifyAllRatings(-quality)
master.name = originalName
/datum/component/fantasy/proc/announce()
var/turf/location = get_turf(parent)
var/span
var/effect_description
if(quality >= 0)
span = "<span class='notice'>"
effect_description = "<span class='heavy_brass'>shimmering golden glow</span>"
else
span = "<span class='danger'>"
effect_description = "<span class='bold'>mottled black glow</span>"
location.visible_message("[span][originalName] is covered by a [effect_description] and then transforms into [parent]!</span>")
+13
View File
@@ -0,0 +1,13 @@
/datum/fantasy_affix
var/placement // A bitflag of "slots" this affix takes up, for example pre/suffix
var/alignment
var/weight = 10
// For those occasional affixes which only make sense in certain circumstances
/datum/fantasy_affix/proc/validate(datum/component/fantasy/comp)
return TRUE
/datum/fantasy_affix/proc/apply(datum/component/fantasy/comp, newName)
return newName
/datum/fantasy_affix/proc/remove(datum/component/fantasy/comp)
@@ -0,0 +1,68 @@
/datum/fantasy_affix/cosmetic_prefixes
placement = AFFIX_PREFIX
alignment = AFFIX_GOOD | AFFIX_EVIL
var/list/goodPrefixes
var/list/badPrefixes
/datum/fantasy_affix/cosmetic_prefixes/New()
goodPrefixes = list(
"greater",
"major",
"blessed",
"superior",
"empowered",
"honed",
"true",
"glorious",
"robust",
)
badPrefixes = list(
"lesser",
"minor",
"blighted",
"inferior",
"enfeebled",
"rusted",
"unsteady",
"tragic",
"gimped",
"cursed",
)
weight = (length(goodPrefixes) + length(badPrefixes)) * 10
/datum/fantasy_affix/cosmetic_prefixes/apply(datum/component/fantasy/comp, newName)
if(comp.quality > 0 || (comp.quality == 0 && prob(50)))
return "[pick(goodPrefixes)] [newName]"
else
return "[pick(badPrefixes)] [newName]"
/datum/fantasy_affix/tactical
placement = AFFIX_PREFIX
alignment = AFFIX_GOOD
weight = 1 // Very powerful, no one should have such power
/datum/fantasy_affix/tactical/apply(datum/component/fantasy/comp, newName)
var/obj/item/master = comp.parent
comp.appliedComponents += master.AddComponent(/datum/component/tactical)
return "tactical [newName]"
/datum/fantasy_affix/pyromantic
placement = AFFIX_PREFIX
alignment = AFFIX_GOOD
/datum/fantasy_affix/pyromantic/apply(datum/component/fantasy/comp, newName)
var/obj/item/master = comp.parent
comp.appliedComponents += master.AddComponent(/datum/component/igniter, CLAMP(comp.quality, 1, 10))
return "pyromantic [newName]"
/datum/fantasy_affix/vampiric
placement = AFFIX_PREFIX
alignment = AFFIX_GOOD
weight = 5
/datum/fantasy_affix/vampiric/apply(datum/component/fantasy/comp, newName)
var/obj/item/master = comp.parent
comp.appliedComponents += master.AddComponent(/datum/component/lifesteal, comp.quality)
return "vampiric [newName]"
+170
View File
@@ -0,0 +1,170 @@
/datum/fantasy_affix/cosmetic_suffixes
placement = AFFIX_SUFFIX
alignment = AFFIX_GOOD | AFFIX_EVIL
var/list/goodSuffixes
var/list/badSuffixes
/datum/fantasy_affix/cosmetic_suffixes/New()
goodSuffixes = list(
"dexterity",
"constitution",
"intelligence",
"wisdom",
"charisma",
"the forest",
"the hills",
"the plains",
"the sea",
"the sun",
"the moon",
"the void",
"the world",
"many secrets",
"many tales",
"many colors",
"rending",
"sundering",
"the night",
"the day",
)
badSuffixes = list(
"draining",
"burden",
"discomfort",
"awkwardness",
"poor hygiene",
"timidity",
)
weight = (length(goodSuffixes) + length(badSuffixes)) * 10
/datum/fantasy_affix/cosmetic_suffixes/apply(datum/component/fantasy/comp, newName)
if(comp.quality > 0 || (comp.quality == 0 && prob(50)))
return "[newName] of [pick(goodSuffixes)]"
else
return "[newName] of [pick(badSuffixes)]"
//////////// Good suffixes
/datum/fantasy_affix/bane
placement = AFFIX_SUFFIX
alignment = AFFIX_GOOD
weight = 20
/datum/fantasy_affix/bane/apply(datum/component/fantasy/comp, newName)
. = ..()
// This is set up to be easy to add to these lists as I expect it will need modifications
var/static/list/possible_mobtypes
if(!possible_mobtypes)
// The base list of allowed mob/species types
possible_mobtypes = typecacheof(list(
/mob/living/simple_animal,
/mob/living/carbon,
/datum/species,
))
// Some particular types to disallow if they're too broad/abstract
possible_mobtypes -= list(
/mob/living/simple_animal/hostile,
)
// Some types to remove them and their subtypes
possible_mobtypes -= typecacheof(list(
/mob/living/carbon/human/species,
))
var/mob/picked_mobtype = pick(possible_mobtypes)
// This works even with the species picks since we're only accessing the name
var/obj/item/master = comp.parent
comp.appliedComponents += master.AddComponent(/datum/component/bane, picked_mobtype)
return "[newName] of [initial(picked_mobtype.name)] slaying"
/datum/fantasy_affix/summoning
placement = AFFIX_SUFFIX
alignment = AFFIX_GOOD
weight = 5
/datum/fantasy_affix/summoning/apply(datum/component/fantasy/comp, newName)
. = ..()
// This is set up to be easy to add to these lists as I expect it will need modifications
var/static/list/possible_mobtypes
if(!possible_mobtypes)
// The base list of allowed mob/species types
possible_mobtypes = typecacheof(list(
/mob/living/simple_animal,
/mob/living/carbon,
/datum/species,
))
// Some particular types to disallow if they're too broad/abstract
possible_mobtypes -= list(
/mob/living/simple_animal/hostile,
)
// Some types to remove them and their subtypes
possible_mobtypes -= typecacheof(list(
/mob/living/carbon/human/species,
/mob/living/simple_animal/hostile/megafauna,
))
var/mob/picked_mobtype = pick(possible_mobtypes)
// This works even with the species picks since we're only accessing the name
var/obj/item/master = comp.parent
var/max_mobs = max(CEILING(comp.quality/2, 1), 1)
var/spawn_delay = 300 - 30 * comp.quality
comp.appliedComponents += master.AddComponent(/datum/component/summoning, list(picked_mobtype), 100, max_mobs, spawn_delay)
return "[newName] of [initial(picked_mobtype.name)] summoning"
/datum/fantasy_affix/shrapnel
placement = AFFIX_SUFFIX
alignment = AFFIX_GOOD
/datum/fantasy_affix/shrapnel/validate(datum/component/fantasy/comp)
if(isgun(comp.parent))
return TRUE
return FALSE
/datum/fantasy_affix/shrapnel/apply(datum/component/fantasy/comp, newName)
. = ..()
// higher means more likely
var/list/weighted_projectile_types = list(/obj/item/projectile/meteor = 1,
/obj/item/projectile/energy/nuclear_particle = 1,
/obj/item/projectile/beam/pulse = 1,
/obj/item/projectile/bullet/honker = 15,
/obj/item/projectile/temp = 15,
/obj/item/projectile/ion = 15,
/obj/item/projectile/magic/door = 15,
/obj/item/projectile/magic/locker = 15,
// /obj/item/projectile/magic/fetch = 15,
/obj/item/projectile/beam/emitter = 15,
// /obj/item/projectile/magic/flying = 15,
/obj/item/projectile/energy/net = 15,
/obj/item/projectile/bullet/incendiary/c9mm = 15,
/obj/item/projectile/temp/hot = 15,
/obj/item/projectile/beam/disabler = 15)
var/obj/item/projectile/picked_projectiletype = pickweight(weighted_projectile_types)
var/obj/item/master = comp.parent
comp.appliedComponents += master.AddComponent(/datum/component/shrapnel, picked_projectiletype)
return "[newName] of [initial(picked_projectiletype.name)] shrapnel"
/datum/fantasy_affix/strength
placement = AFFIX_SUFFIX
alignment = AFFIX_GOOD
/datum/fantasy_affix/strength/apply(datum/component/fantasy/comp, newName)
. = ..()
var/obj/item/master = comp.parent
comp.appliedComponents += master.AddComponent(/datum/component/knockback, CEILING(comp.quality/2, 1), FLOOR(comp.quality/10, 1))
return "[newName] of strength"
//////////// Bad suffixes
/datum/fantasy_affix/fool
placement = AFFIX_SUFFIX
alignment = AFFIX_EVIL
/datum/fantasy_affix/fool/apply(datum/component/fantasy/comp, newName)
. = ..()
var/obj/item/master = comp.parent
comp.appliedComponents += master.AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50)
return "[newName] of the fool"
+37
View File
@@ -0,0 +1,37 @@
/datum/component/igniter
var/fire_stacks
/datum/component/igniter/Initialize(fire_stacks=1)
if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent))
return COMPONENT_INCOMPATIBLE
src.fire_stacks = fire_stacks
/datum/component/igniter/RegisterWithParent()
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
else if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
else if(ishostile(parent))
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
/datum/component/igniter/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
/datum/component/igniter/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return
do_igniter(target)
/datum/component/igniter/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
do_igniter(target)
/datum/component/igniter/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
do_igniter(target)
/datum/component/igniter/proc/do_igniter(atom/target)
if(isliving(target))
var/mob/living/L = target
L.adjust_fire_stacks(fire_stacks)
L.IgniteMob()
+1 -1
View File
@@ -45,7 +45,7 @@
var/knockdown_chance = (target_buckled? mounted_knockdown_chance_per_tile : unmounted_knockdown_chance_per_tile) * current
var/knockdown_time = (target_buckled? mounted_knockdown_time : unmounted_knockdown_time)
var/damage = (target_buckled? mounted_damage_boost_per_tile : unmounted_damage_boost_per_tile) * current
var/sharp = I.is_sharp()
var/sharp = I.get_sharpness()
var/msg
if(damage)
msg += "[user] [sharp? "impales" : "slams into"] [target] [sharp? "on" : "with"] their [parent]"
+44
View File
@@ -0,0 +1,44 @@
/datum/component/knockback
var/throw_distance
var/throw_anchored
/datum/component/knockback/Initialize(throw_distance=1)
if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent))
return COMPONENT_INCOMPATIBLE
src.throw_distance = throw_distance
src.throw_anchored = throw_anchored
/datum/component/knockback/RegisterWithParent()
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
else if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
else if(ishostile(parent))
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
/datum/component/knockback/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
/datum/component/knockback/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return
do_knockback(target, user, get_dir(source, target))
/datum/component/knockback/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
do_knockback(target, attacker, get_dir(attacker, target))
/datum/component/knockback/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
do_knockback(target, null, angle2dir(Angle))
/datum/component/knockback/proc/do_knockback(atom/target, mob/thrower, throw_dir)
if(!ismovableatom(target) || throw_dir == null)
return
var/atom/movable/throwee = target
if(throwee.anchored && !throw_anchored)
return
if(throw_distance < 0)
throw_dir = turn(throw_dir, 180)
throw_distance *= -1
var/atom/throw_target = get_edge_target_turf(throwee, throw_dir)
throwee.safe_throw_at(throw_target, throw_distance, 1, thrower)
+39
View File
@@ -0,0 +1,39 @@
/datum/component/lifesteal
var/flat_heal // heals a constant amount every time a hit occurs
var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
/datum/component/lifesteal/Initialize(flat_heal=0)
if(!isitem(parent) && !ishostile(parent) && !isgun(parent))
return COMPONENT_INCOMPATIBLE
src.flat_heal = flat_heal
/datum/component/lifesteal/RegisterWithParent()
if(isgun(parent))
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
else if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
else if(ishostile(parent))
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
/datum/component/lifesteal/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
/datum/component/lifesteal/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return
do_lifesteal(user, target)
/datum/component/lifesteal/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
do_lifesteal(attacker, target)
/datum/component/lifesteal/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
do_lifesteal(firer, target)
/datum/component/lifesteal/proc/do_lifesteal(atom/heal_target, atom/damage_target)
if(isliving(heal_target) && isliving(damage_target))
var/mob/living/healing = heal_target
var/mob/living/damaging = damage_target
if(damaging.stat != DEAD)
healing.heal_ordered_damage(flat_heal, damage_heal_order)
+6 -15
View File
@@ -7,33 +7,24 @@
var/filter_x
var/filter_y
var/filter_size
var/filter_border
var/filter_color
/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _border = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
. = ..()
if(. == COMPONENT_INCOMPATIBLE)
return
filter_x = _x
filter_y = _y
filter_size = _size
filter_border = _border
filter_color = _color
valid_slots = _valid_slots
/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(datum/source, mob/user, combatmodestate)
if(istype(user))
var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
if(!combatmodestate)
user.filters -= thefilter
else
user.filters += thefilter
/datum/component/wearertargeting/phantomthief/proc/stripdesiredfilter(mob/user)
if(istype(user))
var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
user.filters -= thefilter
if(!combatmodestate)
user.remove_filter("phantomthief")
else
user.add_filter("phantomthief", 4, list(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, color = filter_color))
/datum/component/wearertargeting/phantomthief/on_drop(datum/source, mob/user)
. = ..()
stripdesiredfilter(user)
user.remove_filter("phantomthief")
+23 -24
View File
@@ -18,6 +18,7 @@
var/ride_check_rider_incapacitated = FALSE
var/ride_check_rider_restrained = FALSE
var/ride_check_ridden_incapacitated = FALSE
var/list/offhands = list() // keyed list containing all the current riding offsets associated by mob
/datum/component/riding/Initialize()
if(!ismovableatom(parent))
@@ -299,36 +300,34 @@
M.throw_at(target, 14, 5, AM)
M.Knockdown(60)
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, riding_target_override = null)
var/atom/movable/AM = parent
var/amount_equipped = 0
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, mob/living/riding_target_override)
var/list/equipped
var/mob/living/L = riding_target_override ? riding_target_override : user
for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
if(!riding_target_override)
inhand.rider = user
else
inhand.rider = riding_target_override
inhand.parent = AM
if(user.put_in_hands(inhand, TRUE))
amount_equipped++
else
var/obj/item/riding_offhand/inhand = new
inhand.rider = L
inhand.parent = parent
if(!user.put_in_hands(inhand, TRUE))
qdel(inhand) // it isn't going to be added to offhands anyway
break
LAZYADD(equipped, src)
var/amount_equipped = LAZYLEN(equipped)
if(amount_equipped)
LAZYADD(offhands[L], amount_equipped)
if(amount_equipped >= amount_required)
return TRUE
else
unequip_buckle_inhands(user)
return FALSE
unequip_buckle_inhands(L)
return FALSE
/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
var/atom/movable/AM = parent
for(var/obj/item/riding_offhand/O in user.contents)
if(O.parent != AM)
CRASH("RIDING OFFHAND ON WRONG MOB")
continue
if(O.selfdeleting)
continue
else
qdel(O)
for(var/a in offhands[user])
LAZYREMOVE(offhands[user], a)
if(a) //edge cases null entries
var/obj/item/riding_offhand/O = a
if(O.parent != parent)
CRASH("RIDING OFFHAND ON WRONG MOB")
else if(!O.selfdeleting)
qdel(O)
return TRUE
/obj/item/riding_offhand
+39
View File
@@ -0,0 +1,39 @@
/datum/component/shrapnel
var/projectile_type
var/radius // shoots a projectile for every turf on this radius from the hit target
var/override_projectile_range
/datum/component/shrapnel/Initialize(projectile_type, radius=1, override_projectile_range)
if(!isgun(parent) && !ismachinery(parent) && !isstructure(parent))
return COMPONENT_INCOMPATIBLE
src.projectile_type = projectile_type
src.radius = radius
src.override_projectile_range = override_projectile_range
/datum/component/shrapnel/RegisterWithParent()
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
/datum/component/shrapnel/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_PROJECTILE_ON_HIT))
/datum/component/shrapnel/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
do_shrapnel(firer, target)
/datum/component/shrapnel/proc/do_shrapnel(mob/firer, atom/target)
if(radius < 1)
return
var/turf/target_turf = get_turf(target)
for(var/turf/shootat_turf in RANGE_TURFS(radius, target) - RANGE_TURFS(radius-1, target))
var/obj/item/projectile/P = new projectile_type(target_turf)
//Shooting Code:
P.range = radius+1
if(override_projectile_range)
P.range = override_projectile_range
P.preparePixelProjectile(shootat_turf, target)
P.firer = firer // don't hit ourself that would be really annoying
P.permutated += target // don't hit the target we hit already with the flak
P.fire()
+69
View File
@@ -0,0 +1,69 @@
/datum/component/summoning
var/list/mob_types = list()
var/spawn_chance // chance for the mob to spawn on hit in percent
var/max_mobs
var/spawn_delay // delay in spawning between mobs (deciseconds)
var/spawn_text
var/spawn_sound
var/list/faction
var/last_spawned_time = 0
var/list/spawned_mobs = list()
/datum/component/summoning/Initialize(mob_types, spawn_chance=100, max_mobs=3, spawn_delay=100, spawn_text="appears out of nowhere", spawn_sound='sound/magic/summon_magic.ogg', faction)
if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent))
return COMPONENT_INCOMPATIBLE
src.mob_types = mob_types
src.spawn_chance = spawn_chance
src.max_mobs = max_mobs
src.spawn_delay = spawn_delay
src.spawn_text = spawn_text
src.spawn_sound = spawn_sound
src.faction = faction
/datum/component/summoning/RegisterWithParent()
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
else if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
else if(ishostile(parent))
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
/datum/component/summoning/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
/datum/component/summoning/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return
do_spawn_mob(get_turf(target), user)
/datum/component/summoning/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
do_spawn_mob(get_turf(target), attacker)
/datum/component/summoning/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
do_spawn_mob(get_turf(target), firer)
/datum/component/summoning/proc/do_spawn_mob(atom/spawn_location, summoner)
if(spawned_mobs.len >= max_mobs)
return 0
if(last_spawned_time > world.time)
return 0
if(!prob(spawn_chance))
return 0
last_spawned_time = world.time + spawn_delay
var/chosen_mob_type = pick(mob_types)
var/mob/living/simple_animal/L = new chosen_mob_type(spawn_location)
if(ishostile(L))
var/mob/living/simple_animal/hostile/H = L
H.friends += summoner // do not attack our summon boy
spawned_mobs += L
if(faction != null)
L.faction = faction
RegisterSignal(L, COMSIG_MOB_DEATH, .proc/on_spawned_death) // so we can remove them from the list, etc (for mobs with corpses)
playsound(spawn_location,spawn_sound, 50, 1)
spawn_location.visible_message("<span class='danger'>[L] [spawn_text].</span>")
/datum/component/summoning/proc/on_spawned_death(mob/killed, gibbed)
spawned_mobs -= killed
+42
View File
@@ -0,0 +1,42 @@
/datum/component/tactical
var/allowed_slot
/datum/component/tactical/Initialize(allowed_slot)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
src.allowed_slot = allowed_slot
/datum/component/tactical/RegisterWithParent()
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/modify)
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/unmodify)
/datum/component/tactical/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
unmodify()
/datum/component/fantasy/Destroy()
unmodify()
return ..()
/datum/component/tactical/proc/modify(obj/item/source, mob/user, slot)
if(allowed_slot && slot != allowed_slot)
unmodify()
return
var/obj/item/master = parent
var/image/I = image(icon = master.icon, icon_state = master.icon_state, loc = user)
I.copy_overlays(master)
I.override = TRUE
source.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I)
I.layer = ABOVE_MOB_LAYER
/datum/component/tactical/proc/unmodify(obj/item/source, mob/user)
var/obj/item/master = source || parent
if(!user)
if(!ismob(master.loc))
return
user = master.loc
user.remove_alt_appearance("sneaking_mission")
+2 -2
View File
@@ -15,7 +15,7 @@
/turf/closed/indestructible,
/turf/open/indestructible)
)
var/static/list/resistlist = typecacheof(
/turf/closed/wall/r_wall
)
@@ -77,5 +77,5 @@
thermite_melt()
/datum/component/thermite/proc/attackby_react(datum/source, obj/item/thing, mob/user, params)
if(thing.is_hot())
if(thing.get_temperature())
thermite_melt(user)
+4 -5
View File
@@ -34,11 +34,10 @@
var/turf/T = get_turf(target)
if(target in view(user.client.view, user))
var/obj/spot1 = new phaseout(get_turf(user), user.dir)
user.forceMove(T)
playsound(T, dash_sound, 25, 1)
var/obj/spot2 = new phasein(get_turf(user), user.dir)
spot1.Beam(spot2,beam_effect,time=20)
current_charges--
if(do_teleport(user, T, null, TRUE, null, null, dash_sound, dash_sound, TRUE, TELEPORT_CHANNEL_FREE, TRUE))
var/obj/spot2 = new phasein(get_turf(user), user.dir)
spot1.Beam(spot2,beam_effect,time=20)
current_charges--
holder.update_action_buttons_icon()
addtimer(CALLBACK(src, .proc/charge), charge_rate)
@@ -79,7 +79,7 @@
if(M.getToxLoss() && prob(5))
to_chat(M, "<span class='notice'>Your skin tingles as the starlight seems to heal you.</span>")
M.adjustToxLoss(-(4 * heal_amt)) //most effective on toxins
M.adjustToxLoss(-(4 * heal_amt), forced = TRUE) //most effective on toxins
var/list/parts = M.get_damaged_bodyparts(1,1)
@@ -368,7 +368,7 @@
level = 8
passive_message = "<span class='notice'>You feel an odd attraction to plasma.</span>"
var/temp_rate = 1
threshold_desc = "<b>Transmission 6:</b> Increases temperature adjustment rate.<br>\
threshold_desc = "<b>Transmission 6:</b> Increases temperature adjustment rate and heals toxin lovers.<br>\
<b>Stage Speed 7:</b> Increases healing speed."
/datum/symptom/heal/plasma/Start(datum/disease/advance/A)
@@ -410,7 +410,7 @@
if(prob(5))
to_chat(M, "<span class='notice'>You feel warmer.</span>")
M.adjustToxLoss(-heal_amt)
M.adjustToxLoss(-heal_amt, forced = (temp_rate == 4))
var/list/parts = M.get_damaged_bodyparts(1,1)
if(!parts.len)
@@ -435,7 +435,7 @@
symptom_delay_max = 1
passive_message = "<span class='notice'>Your skin glows faintly for a moment.</span>"
var/cellular_damage = FALSE
threshold_desc = "<b>Transmission 6:</b> Additionally heals cellular damage.<br>\
threshold_desc = "<b>Transmission 6:</b> Additionally heals cellular damage and toxin lovers.<br>\
<b>Resistance 7:</b> Increases healing speed."
/datum/symptom/heal/radiation/Start(datum/disease/advance/A)
@@ -468,7 +468,7 @@
if(cellular_damage)
M.adjustCloneLoss(-heal_amt * 0.5)
M.adjustToxLoss(-(2 * heal_amt))
M.adjustToxLoss(-(2 * heal_amt), forced = cellular_damage)
var/list/parts = M.get_damaged_bodyparts(1,1)
+1
View File
@@ -79,6 +79,7 @@
tele_play_specials(teleatom, destturf, effectout, asoundout)
if(ismegafauna(teleatom))
message_admins("[teleatom] [ADMIN_FLW(teleatom)] has teleported from [ADMIN_VERBOSEJMP(curturf)] to [ADMIN_VERBOSEJMP(destturf)].")
SEND_SIGNAL(teleatom, COMSIG_MOVABLE_TELEPORTED, channel, curturf, destturf)
if(ismob(teleatom))
var/mob/M = teleatom
+93 -158
View File
@@ -41,8 +41,6 @@
var/special_role
var/list/restricted_roles = list()
var/list/datum/objective/objectives = list()
var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
var/linglink
@@ -360,13 +358,15 @@
output += memory
var/list/all_objectives = list()
for(var/datum/antagonist/A in antag_datums)
output += A.antag_memory
all_objectives |= A.objectives
if(objectives.len)
if(all_objectives.len)
output += "<B>Objectives:</B>"
var/obj_count = 1
for(var/datum/objective/objective in objectives)
for(var/datum/objective/objective in all_objectives)
output += "<br><B>Objective #[obj_count++]</B>: [objective.explanation_text]"
var/list/datum/mind/other_owners = objective.get_owners() - src
if(other_owners.len)
@@ -377,7 +377,7 @@
if(window)
recipient << browse(output,"window=memory")
else if(objectives.len || memory)
else if(all_objectives.len || memory)
to_chat(recipient, "<i>[output]</i>")
/datum/mind/Topic(href, href_list)
@@ -408,34 +408,24 @@
memory = new_memo
else if (href_list["obj_edit"] || href_list["obj_add"])
var/datum/objective/objective
var/objective_pos
var/objective_pos //Edited objectives need to keep same order in antag objective list
var/def_value
var/datum/antagonist/target_antag
var/datum/objective/old_objective //The old objective we're replacing/editing
var/datum/objective/new_objective //New objective we're be adding
if (href_list["obj_edit"])
objective = locate(href_list["obj_edit"])
if (!objective)
if(href_list["obj_edit"])
for(var/datum/antagonist/A in antag_datums)
old_objective = locate(href_list["obj_edit"]) in A.objectives
if(old_objective)
target_antag = A
objective_pos = A.objectives.Find(old_objective)
break
if(!old_objective)
to_chat(usr,"Invalid objective.")
return
for(var/datum/antagonist/A in antag_datums)
if(objective in A.objectives)
target_antag = A
objective_pos = A.objectives.Find(objective)
break
if(!target_antag) //Shouldn't happen anymore
stack_trace("objective without antagonist found")
objective_pos = objectives.Find(objective)
//Text strings are easy to manipulate. Revised for simplicity.
var/temp_obj_type = "[objective.type]"//Convert path into a text string.
def_value = copytext(temp_obj_type, 19)//Convert last part of path into an objective keyword.
if(!def_value)//If it's a custom objective, it will be an empty string.
def_value = "custom"
else
//We're adding this objective
if(href_list["target_antag"])
var/datum/antagonist/X = locate(href_list["target_antag"]) in antag_datums
if(X)
@@ -447,7 +437,7 @@
if(1)
target_antag = antag_datums[1]
else
var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", def_value) as null|anything in antag_datums + "(new custom antag)"
var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", "(new custom antag)") as null|anything in antag_datums + "(new custom antag)"
if (QDELETED(target))
return
else if(target == "(new custom antag)")
@@ -455,149 +445,88 @@
else
target_antag = target
var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "maroon", "debrain", "protect", "destroy", "prevent", "hijack", "escape", "survive", "martyr", "steal", "download", "nuclear", "capture", "absorb", "custom")
if (!new_obj_type)
var/static/list/choices
if(!choices)
choices = list()
var/list/allowed_types = list(
/datum/objective/assassinate,
/datum/objective/maroon,
/datum/objective/debrain,
/datum/objective/protect,
/datum/objective/destroy,
/datum/objective/hijack,
/datum/objective/escape,
/datum/objective/survive,
/datum/objective/martyr,
/datum/objective/steal,
/datum/objective/download,
/datum/objective/nuclear,
/datum/objective/capture,
/datum/objective/absorb,
/datum/objective/custom
)
for(var/T in allowed_types)
var/datum/objective/X = T
choices[initial(X.name)] = T
if(old_objective)
if(old_objective.name in choices)
def_value = old_objective.name
var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in choices
selected_type = choices[selected_type]
if (!selected_type)
return
var/datum/objective/new_objective = null
if(!old_objective)
//Add new one
new_objective = new selected_type
new_objective.owner = src
new_objective.admin_edit(usr)
target_antag.objectives += new_objective
switch (new_obj_type)
if ("assassinate","protect","debrain","maroon")
var/list/possible_targets = list("Free objective")
for(var/datum/mind/possible_target in SSticker.minds)
if ((possible_target != src) && ishuman(possible_target.current))
possible_targets += possible_target.current
var/mob/def_target = null
var/list/objective_list = typecacheof(list(/datum/objective/assassinate, /datum/objective/protect, /datum/objective/debrain, /datum/objective/maroon))
if (is_type_in_typecache(objective, objective_list) && objective.target)
def_target = objective.target.current
var/mob/new_target = input("Select target:", "Objective target", def_target) as null|anything in possible_targets
if (!new_target)
return
var/objective_path = text2path("/datum/objective/[new_obj_type]")
if (new_target == "Free objective")
new_objective = new objective_path
new_objective.owner = src
new_objective.target = null
new_objective.explanation_text = "Free objective"
else
new_objective = new objective_path
new_objective.owner = src
new_objective.target = new_target.mind
//Will display as special role if the target is set as MODE. Ninjas/commandos/nuke ops.
new_objective.update_explanation_text()
if ("destroy")
var/list/possible_targets = active_ais(1)
if(possible_targets.len)
var/mob/new_target = input("Select target:", "Objective target") as null|anything in possible_targets
new_objective = new /datum/objective/destroy
new_objective.target = new_target.mind
new_objective.owner = src
new_objective.update_explanation_text()
else
to_chat(usr, "No active AIs with minds")
if ("prevent")
new_objective = new /datum/objective/block
new_objective.owner = src
if ("hijack")
new_objective = new /datum/objective/hijack
new_objective.owner = src
if ("escape")
new_objective = new /datum/objective/escape
new_objective.owner = src
if ("survive")
new_objective = new /datum/objective/survive
new_objective.owner = src
if("martyr")
new_objective = new /datum/objective/martyr
new_objective.owner = src
if ("nuclear")
new_objective = new /datum/objective/nuclear
new_objective.owner = src
if ("steal")
if (!istype(objective, /datum/objective/steal))
new_objective = new /datum/objective/steal
new_objective.owner = src
else
new_objective = objective
var/datum/objective/steal/steal = new_objective
if (!steal.select_target())
return
if("download","capture","absorb")
var/def_num
if(objective&&objective.type==text2path("/datum/objective/[new_obj_type]"))
def_num = objective.target_amount
var/target_number = input("Input target number:", "Objective", def_num) as num | null
if (isnull(target_number))//Ordinarily, you wouldn't need isnull. In this case, the value may already exist.
return
switch(new_obj_type)
if("download")
new_objective = new /datum/objective/download
new_objective.explanation_text = "Download [target_number] research node\s."
if("capture")
new_objective = new /datum/objective/capture
new_objective.explanation_text = "Capture [target_number] lifeforms with an energy net. Live, rare specimens are worth more."
if("absorb")
new_objective = new /datum/objective/absorb
new_objective.explanation_text = "Absorb [target_number] compatible genomes."
new_objective.owner = src
new_objective.target_amount = target_number
if ("custom")
var/expl = stripped_input(usr, "Custom objective:", "Objective", objective ? objective.explanation_text : "")
if (!expl)
return
new_objective = new /datum/objective
new_objective.owner = src
new_objective.explanation_text = expl
if (!new_objective)
return
if (objective)
if(target_antag)
target_antag.objectives -= objective
objectives -= objective
target_antag.objectives.Insert(objective_pos, new_objective)
message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]")
log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]")
else
if(target_antag)
target_antag.objectives += new_objective
objectives += new_objective
message_admins("[key_name_admin(usr)] added a new objective for [current]: [new_objective.explanation_text]")
log_admin("[key_name(usr)] added a new objective for [current]: [new_objective.explanation_text]")
else
if(old_objective.type == selected_type)
//Edit the old
old_objective.admin_edit(usr)
new_objective = old_objective
else
//Replace the old
new_objective = new selected_type
new_objective.owner = src
new_objective.admin_edit(usr)
target_antag.objectives -= old_objective
target_antag.objectives.Insert(objective_pos, new_objective)
message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]")
log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]")
else if (href_list["obj_delete"])
var/datum/objective/objective = locate(href_list["obj_delete"])
if(!istype(objective))
return
var/datum/objective/objective
for(var/datum/antagonist/A in antag_datums)
if(objective in A.objectives)
A.objectives -= objective
objective = locate(href_list["obj_delete"]) in A.objectives
if(istype(objective))
break
objectives -= objective
if(!objective)
to_chat(usr,"Invalid objective.")
return
//qdel(objective) Needs cleaning objective destroys
message_admins("[key_name_admin(usr)] removed an objective for [current]: [objective.explanation_text]")
log_admin("[key_name(usr)] removed an objective for [current]: [objective.explanation_text]")
else if(href_list["obj_completed"])
var/datum/objective/objective = locate(href_list["obj_completed"])
if(!istype(objective))
var/datum/objective/objective
for(var/datum/antagonist/A in antag_datums)
objective = locate(href_list["obj_completed"]) in A.objectives
if(istype(objective))
objective = objective
break
if(!objective)
to_chat(usr,"Invalid objective.")
return
objective.completed = !objective.completed
log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]")
@@ -652,10 +581,16 @@
usr = current
traitor_panel()
/datum/mind/proc/get_all_objectives()
var/list/all_objectives = list()
for(var/datum/antagonist/A in antag_datums)
all_objectives |= A.objectives
return all_objectives
/datum/mind/proc/announce_objectives()
var/obj_count = 1
to_chat(current, "<span class='notice'>Your current objectives:</span>")
for(var/objective in objectives)
for(var/objective in get_all_objectives())
var/datum/objective/O = objective
to_chat(current, "<B>Objective #[obj_count]</B>: [O.explanation_text]")
obj_count++
+3 -1
View File
@@ -66,6 +66,8 @@
place = cmaster_turf
for(var/i in 1 to distance)
place = get_step(place, dir)
if(!place)
break
atoms += get_rad_contents(place)
return atoms
@@ -108,7 +110,7 @@
if(!can_contaminate || blacklisted[thing.type])
continue
if(prob(contamination_chance)) // Only stronk rads get to have little baby rads
if(SEND_SIGNAL(thing, COMSIG_ATOM_RAD_CONTAMINATING, strength) & COMPONENT_BLOCK_CONTAMINATION)
if(CHECK_BITFIELD(thing.rad_flags, RAD_NO_CONTAMINATE) || SEND_SIGNAL(thing, COMSIG_ATOM_RAD_CONTAMINATING, strength) & COMPONENT_BLOCK_CONTAMINATION)
continue
var/rad_strength = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT
thing.AddComponent(/datum/component/radioactive, rad_strength, source)
+44
View File
@@ -94,6 +94,50 @@
lose_text = "<span class='notice'>You don't feel as prudish as before.</span>"
medical_record_text = "Patient exhibits a special gene that makes them immune to Crocin and Hexacrocin."
/datum/quirk/libido
name = "Nymphomania"
desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual."
value = 0
mob_trait = TRAIT_NYMPHO
gain_text = "<span class='notice'>You are feeling extra wild.</span>"
lose_text = "<span class='notice'>You don't feel that burning sensation anymore.</span>"
/datum/quirk/libido/add()
quirk_holder.min_arousal = 16
quirk_holder.arousal_rate = 3
/datum/quirk/libido/remove()
if(quirk_holder)
quirk_holder.min_arousal = initial(quirk_holder.min_arousal)
quirk_holder.arousal_rate = initial(quirk_holder.arousal_rate)
/datum/quirk/maso
name = "Masochism"
desc = "You are aroused by pain."
value = 0
mob_trait = TRAIT_MASO
gain_text = "<span class='notice'>You desire to be hurt.</span>"
lose_text = "<span class='notice'>Pain has become less exciting for you.</span>"
/datum/quirk/exhibitionism
name = "Exhibitionism"
desc = "You don't mind showing off your bare body to strangers, in fact you find it quite satistying."
value = 0
medical_record_text = "Patient has been diagnosed with exhibitionistic disorder."
mob_trait = TRAIT_EXHIBITIONIST
gain_text = "<span class='notice'>You feel like exposing yourself to the world.</span>"
lose_text = "<span class='notice'>Indecent exposure doesn't sound as charming to you anymore.</span>"
/datum/quirk/pharmacokinesis //Prevents unwanted organ additions.
name = "Acute hepatic pharmacokinesis"
desc = "You've a rare genetic disorder that causes Incubus draft and Sucubus milk to be absorbed by your liver instead."
value = 0
mob_trait = TRAIT_PHARMA
lose_text = "<span class='notice'>Your liver feels different.</span>"
var/active = FALSE
var/power = 0
var/cachedmoveCalc = 1
/datum/quirk/assblastusa
name = "Buns of Steel"
desc = "You've never skipped ass day. With this trait, you are completely immune to all forms of ass slapping and anyone who tries to slap your rock hard ass usually gets a broken hand."
@@ -34,11 +34,12 @@
//If you override this method, have it return the number of objectives added.
if(devil_target_list.len && devil_target_list[devil]) // Is a double agent
var/datum/mind/target_mind = devil_target_list[devil]
var/datum/antagonist/devil/D = target_mind.has_antag_datum(/datum/antagonist/devil)
var/datum/objective/devil/outsell/outsellobjective = new
outsellobjective.owner = devil
outsellobjective.target = target_mind
outsellobjective.update_explanation_text()
devil.objectives += outsellobjective
D.objectives += outsellobjective
return 1
return 0
+2 -1
View File
@@ -4,11 +4,12 @@
/datum/game_mode/proc/add_devil_objectives(datum/mind/devil_mind, quantity)
var/list/validtypes = list(/datum/objective/devil/soulquantity, /datum/objective/devil/soulquality, /datum/objective/devil/sintouch, /datum/objective/devil/buy_target)
var/datum/antagonist/devil/D = devil_mind.has_antag_datum(/datum/antagonist/devil)
for(var/i = 1 to quantity)
var/type = pick(validtypes)
var/datum/objective/devil/objective = new type(null)
objective.owner = devil_mind
devil_mind.objectives += objective
D.objectives += objective
if(!istype(objective, /datum/objective/devil/buy_target))
validtypes -= type //prevent duplicate objectives, EXCEPT for buy_target.
else
+4
View File
@@ -111,6 +111,10 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
..()
pop_per_requirement = CONFIG_GET(number/dynamic_pop_per_requirement)
GLOB.dynamic_high_pop_limit = CONFIG_GET(number/dynamic_high_pop_limit)
GLOB.dynamic_latejoin_delay_min = CONFIG_GET(number/dynamic_latejoin_delay_min)*600
GLOB.dynamic_latejoin_delay_max = CONFIG_GET(number/dynamic_latejoin_delay_max)*600
GLOB.dynamic_midround_delay_min = CONFIG_GET(number/dynamic_midround_delay_min)*600
GLOB.dynamic_midround_delay_max = CONFIG_GET(number/dynamic_midround_delay_max)*600
/datum/game_mode/dynamic/admin_panel()
var/list/dat = list("<html><head><title>Game Mode Panel</title></head><body><h1><B>Game Mode Panel</B></h1>")
+133 -13
View File
@@ -4,7 +4,8 @@ GLOBAL_LIST_EMPTY(objectives)
/datum/objective
var/datum/mind/owner //The primary owner of the objective. !!SOMEWHAT DEPRECATED!! Prefer using 'team' for new code.
var/datum/team/team //An alternative to 'owner': a team. Use this when writing new code.
var/datum/team/team //An alternative to 'owner': a team. Use this when writing new code.
var/name = "generic objective" //Name for admin prompts
var/explanation_text = "Nothing" //What that person is supposed to do.
var/team_explanation_text //For when there are multiple owners.
var/datum/mind/target = null //If they are focused on a particular person.
@@ -22,6 +23,32 @@ GLOBAL_LIST_EMPTY(objectives)
if(owner)
. += owner
/datum/objective/proc/admin_edit(mob/admin)
return
//Shared by few objective types
/datum/objective/proc/admin_simple_target_pick(mob/admin)
var/list/possible_targets = list("Free objective")
var/def_value
for(var/datum/mind/possible_target in SSticker.minds)
if ((possible_target != src) && ishuman(possible_target.current))
possible_targets += possible_target.current
if(target && target.current)
def_value = target.current
var/mob/new_target = input(admin,"Select target:", "Objective target", def_value) as null|anything in possible_targets
if (!new_target)
return
if (new_target == "Free objective")
target = null
else
target = new_target.mind
update_explanation_text()
/datum/objective/proc/considered_escaped(datum/mind/M)
if(!considered_alive(M))
return FALSE
@@ -42,7 +69,7 @@ GLOBAL_LIST_EMPTY(objectives)
/datum/objective/proc/is_unique_objective(possible_target)
var/list/datum/mind/owners = get_owners()
for(var/datum/mind/M in owners)
for(var/datum/objective/O in M.objectives)
for(var/datum/objective/O in M.get_all_objectives()) //This scope is debatable, probably should be passed in by caller.
if(istype(O, type) && O.get_target() == possible_target)
return FALSE
return TRUE
@@ -122,6 +149,7 @@ GLOBAL_LIST_EMPTY(objectives)
H.equip_in_one_of_slots(O, slots)
/datum/objective/assassinate
name = "assasinate"
var/target_role_type=0
martyr_compatible = 1
@@ -141,6 +169,9 @@ GLOBAL_LIST_EMPTY(objectives)
else
explanation_text = "Free Objective"
/datum/objective/assassinate/admin_edit(mob/admin)
admin_simple_target_pick(admin)
/datum/objective/assassinate/internal
var/stolen = 0 //Have we already eliminated this target?
@@ -150,6 +181,7 @@ GLOBAL_LIST_EMPTY(objectives)
explanation_text = "Assassinate [target.name], who was obliterated"
/datum/objective/mutiny
name = "mutiny"
var/target_role_type=0
martyr_compatible = 1
@@ -173,6 +205,7 @@ GLOBAL_LIST_EMPTY(objectives)
explanation_text = "Free Objective"
/datum/objective/maroon
name = "maroon"
var/target_role_type=0
martyr_compatible = 1
@@ -191,7 +224,11 @@ GLOBAL_LIST_EMPTY(objectives)
else
explanation_text = "Free Objective"
/datum/objective/maroon/admin_edit(mob/admin)
admin_simple_target_pick(admin)
/datum/objective/debrain
name = "debrain"
var/target_role_type=0
/datum/objective/debrain/find_target_by_role(role, role_type=0, invert=0)
@@ -222,7 +259,11 @@ GLOBAL_LIST_EMPTY(objectives)
else
explanation_text = "Free Objective"
/datum/objective/debrain/admin_edit(mob/admin)
admin_simple_target_pick(admin)
/datum/objective/protect//The opposite of killing a dude.
name = "protect"
martyr_compatible = 1
var/target_role_type = 0
var/human_check = TRUE
@@ -243,10 +284,15 @@ GLOBAL_LIST_EMPTY(objectives)
else
explanation_text = "Free Objective"
/datum/objective/protect/admin_edit(mob/admin)
admin_simple_target_pick(admin)
/datum/objective/protect/nonhuman
name = "protect nonhuman"
human_check = FALSE
/datum/objective/hijack
name = "hijack"
explanation_text = "Hijack the shuttle to ensure no loyalist Nanotrasen crew escape alive and out of custody."
team_explanation_text = "Hijack the shuttle to ensure no loyalist Nanotrasen crew escape alive and out of custody. Leave no team member behind."
martyr_compatible = 0 //Technically you won't get both anyway.
@@ -261,6 +307,7 @@ GLOBAL_LIST_EMPTY(objectives)
return SSshuttle.emergency.is_hijacked()
/datum/objective/block
name = "no organics on shuttle"
explanation_text = "Do not allow any organic lifeforms to escape on the shuttle alive."
martyr_compatible = 1
@@ -274,6 +321,7 @@ GLOBAL_LIST_EMPTY(objectives)
return TRUE
/datum/objective/purge
name = "no mutants on shuttle"
explanation_text = "Ensure no mutant humanoid species are present aboard the escape shuttle."
martyr_compatible = 1
@@ -288,6 +336,7 @@ GLOBAL_LIST_EMPTY(objectives)
return TRUE
/datum/objective/robot_army
name = "robot army"
explanation_text = "Have at least eight active cyborgs synced to you."
martyr_compatible = 0
@@ -304,6 +353,7 @@ GLOBAL_LIST_EMPTY(objectives)
return counter >= 8
/datum/objective/escape
name = "escape"
explanation_text = "Escape on the shuttle or an escape pod alive and without being in custody."
team_explanation_text = "Have all members of your team escape on a shuttle or pod alive, without being in custody."
@@ -316,6 +366,7 @@ GLOBAL_LIST_EMPTY(objectives)
return TRUE
/datum/objective/escape/escape_with_identity
name = "escape with identity"
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
@@ -351,7 +402,11 @@ GLOBAL_LIST_EMPTY(objectives)
return TRUE
return FALSE
/datum/objective/escape/escape_with_identity/admin_edit(mob/admin)
admin_simple_target_pick(admin)
/datum/objective/survive
name = "survive"
explanation_text = "Stay alive until the end."
/datum/objective/survive/check_completion()
@@ -362,6 +417,7 @@ GLOBAL_LIST_EMPTY(objectives)
return TRUE
/datum/objective/survive/exist //Like survive, but works for silicons and zombies and such.
name = "survive nonhuman"
/datum/objective/survive/exist/check_completion()
var/list/datum/mind/owners = get_owners()
@@ -371,6 +427,7 @@ GLOBAL_LIST_EMPTY(objectives)
return TRUE
/datum/objective/martyr
name = "martyr"
explanation_text = "Die a glorious death."
/datum/objective/martyr/check_completion()
@@ -383,6 +440,7 @@ GLOBAL_LIST_EMPTY(objectives)
return TRUE
/datum/objective/nuclear
name = "nuclear"
explanation_text = "Destroy the station with a nuclear device."
martyr_compatible = 1
@@ -393,6 +451,7 @@ GLOBAL_LIST_EMPTY(objectives)
GLOBAL_LIST_EMPTY(possible_items)
/datum/objective/steal
name = "steal"
var/datum/objective_item/targetinfo = null //Save the chosen item datum so we can access it later.
var/obj/item/steal_target = null //Needed for custom objectives (they're just items, not datums).
martyr_compatible = 0
@@ -430,18 +489,19 @@ GLOBAL_LIST_EMPTY(possible_items)
explanation_text = "Free objective"
return
/datum/objective/steal/proc/select_target() //For admins setting objectives manually.
/datum/objective/steal/admin_edit(mob/admin)
var/list/possible_items_all = GLOB.possible_items+"custom"
var/new_target = input("Select target:", "Objective target", steal_target) as null|anything in possible_items_all
var/new_target = input(admin,"Select target:", "Objective target", steal_target) as null|anything in possible_items_all
if (!new_target)
return
if (new_target == "custom") //Can set custom items.
var/obj/item/custom_target = input("Select type:","Type") as null|anything in typesof(/obj/item)
if (!custom_target)
var/custom_path = input(admin,"Search for target item type:","Type") as null|text
if (!custom_path)
return
var/obj/item/custom_target = pick_closest_path(custom_path, make_types_fancy(subtypesof(/obj/item)))
var/custom_name = initial(custom_target.name)
custom_name = stripped_input("Enter target name:", "Objective target", custom_name)
custom_name = stripped_input(admin,"Enter target name:", "Objective target", custom_name)
if (!custom_name)
return
steal_target = custom_target
@@ -449,7 +509,6 @@ GLOBAL_LIST_EMPTY(possible_items)
else
set_target(new_target)
return steal_target
/datum/objective/steal/check_completion()
var/list/datum/mind/owners = get_owners()
@@ -476,6 +535,7 @@ GLOBAL_LIST_EMPTY(possible_items)
GLOBAL_LIST_EMPTY(possible_items_special)
/datum/objective/steal/special //ninjas are so special they get their own subtype good for them
name = "steal special"
/datum/objective/steal/special/New()
..()
@@ -487,8 +547,12 @@ GLOBAL_LIST_EMPTY(possible_items_special)
return set_target(pick(GLOB.possible_items_special))
/datum/objective/steal/exchange
name = "exchange"
martyr_compatible = 0
/datum/objective/steal/exchange/admin_edit(mob/admin)
return
/datum/objective/steal/exchange/proc/set_faction(faction,otheragent)
target = otheragent
if(faction == "red")
@@ -508,6 +572,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
/datum/objective/steal/exchange/backstab
name = "prevent exchange"
/datum/objective/steal/exchange/backstab/set_faction(faction)
if(faction == "red")
@@ -519,12 +584,17 @@ GLOBAL_LIST_EMPTY(possible_items_special)
/datum/objective/download
name = "download"
/datum/objective/download/proc/gen_amount_goal()
target_amount = rand(20,40)
explanation_text = "Download [target_amount] research node\s."
update_explanation_text()
return target_amount
/datum/objective/download/update_explanation_text()
..()
explanation_text = "Download [target_amount] research node\s."
/datum/objective/download/check_completion()
var/datum/techweb/checking = new
var/list/datum/mind/owners = get_owners()
@@ -541,13 +611,24 @@ GLOBAL_LIST_EMPTY(possible_items_special)
TD.stored_research.copy_research_to(checking)
return checking.researched_nodes.len >= target_amount
/datum/objective/download/admin_edit(mob/admin)
var/count = input(admin,"How many nodes ?","Nodes",target_amount) as num|null
if(count)
target_amount = count
update_explanation_text()
/datum/objective/capture
name = "capture"
var/captured_amount = 0
/datum/objective/capture/proc/gen_amount_goal()
target_amount = rand(5,10)
explanation_text = "Capture [target_amount] lifeform\s with an energy net. Live, rare specimens are worth more."
return target_amount
target_amount = rand(5,10)
explanation_text = "Capture [target_amount] lifeform\s with an energy net. Live, rare specimens are worth more."
return target_amount
/datum/objective/capture/update_explanation_text()
. = ..()
explanation_text = "Capture [target_amount] lifeform\s with an energy net. Live, rare specimens are worth more."
/datum/objective/capture/check_completion()//Basically runs through all the mobs in the area to determine how much they are worth.
/*var/area/centcom/holding/A = GLOB.areas_by_type[/area/centcom/holding]
@@ -576,10 +657,16 @@ GLOBAL_LIST_EMPTY(possible_items_special)
captured_amount+=2*/ //Removed in favour of adding points on capture, in energy_net_nets.dm
return captured_amount >= target_amount
/datum/objective/capture/admin_edit(mob/admin)
var/count = input(admin,"How many mobs to capture ?","capture",target_amount) as num|null
if(count)
target_amount = count
update_explanation_text()
//Changeling Objectives
/datum/objective/absorb
name = "absorb"
/datum/objective/absorb/proc/gen_amount_goal(lowbound = 4, highbound = 6)
target_amount = rand (lowbound,highbound)
@@ -595,9 +682,19 @@ GLOBAL_LIST_EMPTY(possible_items_special)
n_p ++
target_amount = min(target_amount, n_p)
explanation_text = "Extract [target_amount] compatible genome\s."
update_explanation_text()
return target_amount
/datum/objective/absorb/update_explanation_text()
. = ..()
explanation_text = "Extract [target_amount] compatible genome\s."
/datum/objective/absorb/admin_edit(mob/admin)
var/count = input(admin,"How many people to absorb?","absorb",target_amount) as num|null
if(count)
target_amount = count
update_explanation_text()
/datum/objective/absorb/check_completion()
var/list/datum/mind/owners = get_owners()
var/absorbedcount = 0
@@ -611,6 +708,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
return absorbedcount >= target_amount
/datum/objective/absorb_most
name = "absorb most"
explanation_text = "Extract more compatible genomes than any other Changeling."
/datum/objective/absorb_most/check_completion()
@@ -631,6 +729,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
return TRUE
/datum/objective/absorb_changeling
name = "absorb changeling"
explanation_text = "Absorb another Changeling."
/datum/objective/absorb_changeling/check_completion()
@@ -653,6 +752,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
//End Changeling Objectives
/datum/objective/destroy
name = "destroy AI"
martyr_compatible = 1
/datum/objective/destroy/find_target()
@@ -674,10 +774,20 @@ GLOBAL_LIST_EMPTY(possible_items_special)
else
explanation_text = "Free Objective"
/datum/objective/destroy/admin_edit(mob/admin)
var/list/possible_targets = active_ais(1)
if(possible_targets.len)
var/mob/new_target = input(admin,"Select target:", "Objective target") as null|anything in possible_targets
target = new_target.mind
else
to_chat(admin, "No active AIs with minds")
update_explanation_text()
/datum/objective/destroy/internal
var/stolen = FALSE //Have we already eliminated this target?
/datum/objective/steal_five_of_type
name = "steal five of"
explanation_text = "Steal at least five items!"
var/list/wanted_items = list(/obj/item)
@@ -686,10 +796,12 @@ GLOBAL_LIST_EMPTY(possible_items_special)
wanted_items = typecacheof(wanted_items)
/datum/objective/steal_five_of_type/summon_guns
name = "steal guns"
explanation_text = "Steal at least five guns!"
wanted_items = list(/obj/item/gun)
/datum/objective/steal_five_of_type/summon_magic
name = "steal magic"
explanation_text = "Steal at least five magical artefacts!"
wanted_items = list(/obj/item/spellbook, /obj/item/gun/magic, /obj/item/clothing/suit/space/hardsuit/wizard, /obj/item/scrying, /obj/item/antag_spawner/contract, /obj/item/necromantic_stone)
@@ -705,6 +817,14 @@ GLOBAL_LIST_EMPTY(possible_items_special)
stolen_count++
return stolen_count >= 5
//Created by admin tools
/datum/objective/custom
name = "custom"
/datum/objective/custom/admin_edit(mob/admin)
var/expl = stripped_input(admin, "Custom objective:", "Objective", explanation_text)
if(expl)
explanation_text = expl
////////////////////////////////
// Changeling team objectives //
+6 -83
View File
@@ -113,11 +113,6 @@ Class Procs:
var/atom/movable/occupant = null
var/speed_process = FALSE // Process as fast as possible?
var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created
var/obj/item/card/id/inserted_scan_id
var/obj/item/card/id/inserted_modify_id
var/list/region_access = null // For the identification console (card.dm)
var/list/head_subordinates = null // For the identification console (card.dm)
var/authenticated = 0 // For the identification console (card.dm)
var/interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE
@@ -459,22 +454,20 @@ Class Procs:
/obj/machinery/examine(mob/user)
. = ..()
if(stat & BROKEN)
. += "<span class='notice'>It looks broken and non-functional.</span>"
to_chat(user, "<span class='notice'>It looks broken and non-functional.</span>")
if(!(resistance_flags & INDESTRUCTIBLE))
if(resistance_flags & ON_FIRE)
. += "<span class='warning'>It's on fire!</span>"
to_chat(user, "<span class='warning'>It's on fire!</span>")
var/healthpercent = (obj_integrity/max_integrity) * 100
switch(healthpercent)
if(50 to 99)
. += "It looks slightly damaged."
to_chat(user, "It looks slightly damaged.")
if(25 to 50)
. += "It appears heavily damaged."
to_chat(user, "It appears heavily damaged.")
if(0 to 25)
. += "<span class='warning'>It's falling apart!</span>"
to_chat(user, "<span class='warning'>It's falling apart!</span>")
if(user.research_scanner && component_parts)
. += display_parts(user, TRUE)
if(inserted_scan_id || inserted_modify_id)
. += "<span class='notice'>Alt-click to eject the ID card.</span>"
to_chat(user, display_parts(user, TRUE))
//called on machinery construction (i.e from frame to machinery) but not on initialization
/obj/machinery/proc/on_construction()
@@ -509,73 +502,3 @@ Class Procs:
. = . % 9
AM.pixel_x = -8 + ((.%3)*8)
AM.pixel_y = -8 + (round( . / 3)*8)
/obj/machinery/proc/id_insert_scan(mob/user, obj/item/card/id/I)
I = user.get_active_held_item()
if(istype(I))
if(inserted_scan_id)
to_chat(user, "<span class='warning'>There's already an ID card in the console!</span>")
return
if(!user.transferItemToLoc(I, src))
return
inserted_scan_id = I
user.visible_message("<span class='notice'>[user] inserts an ID card into the console.</span>", \
"<span class='notice'>You insert the ID card into the console.</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
updateUsrDialog()
/obj/machinery/proc/id_eject_scan(mob/user)
if(!inserted_scan_id)
to_chat(user, "<span class='warning'>There's no ID card in the console!</span>")
return
if(inserted_scan_id)
inserted_scan_id.forceMove(drop_location())
if(!issilicon(user) && Adjacent(user))
user.put_in_hands(inserted_scan_id)
inserted_scan_id = null
user.visible_message("<span class='notice'>[user] gets an ID card from the console.</span>", \
"<span class='notice'>You get the ID card from the console.</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
updateUsrDialog()
/obj/machinery/proc/id_eject_modify(mob/user)
if(inserted_modify_id)
GLOB.data_core.manifest_modify(inserted_modify_id.registered_name, inserted_modify_id.assignment)
inserted_modify_id.update_label()
inserted_modify_id.forceMove(drop_location())
if(!issilicon(user) && Adjacent(user))
user.put_in_hands(inserted_modify_id)
user.visible_message("<span class='notice'>[user] gets an ID card from the console.</span>", \
"<span class='notice'>You get the ID card from the console.</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
inserted_modify_id = null
region_access = null
head_subordinates = null
updateUsrDialog()
/obj/machinery/proc/id_insert_modify(mob/user)
var/obj/item/card/id/I = user.get_active_held_item()
if(istype(I))
if(inserted_modify_id)
to_chat(user, "<span class='warning'>There's already an ID card in the console!</span>")
return
if(!user.transferItemToLoc(I, src))
return
inserted_modify_id = I
user.visible_message("<span class='notice'>[user] inserts an ID card into the console.</span>", \
"<span class='notice'>You insert the ID card into the console.</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
updateUsrDialog()
/obj/machinery/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, !issilicon(user)) || !is_operational())
return
if(inserted_modify_id)
id_eject_modify(user)
authenticated = FALSE
return
if(inserted_scan_id)
id_eject_scan(user)
authenticated = FALSE
return
+4 -3
View File
@@ -13,6 +13,7 @@
var/icon_keyboard = "generic_key"
var/icon_screen = "generic"
var/clockwork = FALSE
var/authenticated = FALSE
/obj/machinery/computer/Initialize(mapload, obj/item/circuitboard/C)
. = ..()
@@ -34,9 +35,9 @@
/obj/machinery/computer/ratvar_act()
if(!clockwork)
clockwork = TRUE
icon_screen = "ratvar[rand(1, 4)]"
icon_keyboard = "ratvar_key[rand(1, 6)]"
icon_state = "ratvarcomputer[rand(1, 4)]"
icon_screen = "ratvar[rand(1, 3)]"
icon_keyboard = "ratvar_key[rand(1, 2)]"
icon_state = "ratvarcomputer"
update_icon()
/obj/machinery/computer/narsie_act()
+2 -1
View File
@@ -86,7 +86,8 @@
/obj/item/circuitboard/computer/arcade/amputation = 2)
var/thegame = pickweight(gameodds)
var/obj/item/circuitboard/CB = new thegame()
new CB.build_path(loc, CB)
var/obj/machinery/computer/arcade/A = new CB.build_path(loc, CB)
A.setDir(dir)
return INITIALIZE_HINT_QDEL
//The below object acts as a spawner with a wide array of possible picks, most being uninspired references to past/current player characters.
//Nevertheless, this keeps its ratio constant with the sum of all the others prizes.
+155 -152
View File
@@ -11,8 +11,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
icon_keyboard = "id_key"
req_one_access = list(ACCESS_HEADS, ACCESS_CHANGE_IDS)
circuit = /obj/item/circuitboard/computer/card
var/obj/item/card/id/scan = null
var/obj/item/card/id/modify = null
var/mode = 0
var/printing = null
var/target_dept = 0 //Which department this computer has access to. 0=all departments
@@ -38,68 +36,68 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
//This is used to keep track of opened positions for jobs to allow instant closing
//Assoc array: "JobName" = (int)<Opened Positions>
var/list/opened_positions = list();
var/list/opened_positions = list()
var/obj/item/card/id/inserted_scan_id
var/obj/item/card/id/inserted_modify_id
var/list/region_access = null
var/list/head_subordinates = null
light_color = LIGHT_COLOR_BLUE
/obj/machinery/computer/card/examine(mob/user)
..()
if(scan || modify)
if(inserted_scan_id || inserted_modify_id)
to_chat(user, "<span class='notice'>Alt-click to eject the ID card.</span>")
/obj/machinery/computer/card/Initialize()
. = ..()
change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay)
/obj/machinery/computer/card/attackby(obj/O, mob/user, params)//TODO:SANITY
if(istype(O, /obj/item/card/id))
var/obj/item/card/id/idcard = O
if(check_access(idcard))
if(!scan)
if (!user.transferItemToLoc(idcard,src))
return
scan = idcard
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
else if(!modify)
if (!user.transferItemToLoc(idcard,src))
return
modify = idcard
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
/obj/machinery/computer/card/examine(mob/user)
. = ..()
if(inserted_scan_id || inserted_modify_id)
to_chat(user, "<span class='notice'>Alt-click to eject the ID card.</span>")
/obj/machinery/computer/card/attackby(obj/I, mob/user, params)
if(istype(I, /obj/item/card/id))
if(!inserted_scan_id)
if(id_insert(user, I, inserted_scan_id))
inserted_scan_id = I
return
if(!inserted_modify_id)
if(id_insert(user, I, inserted_modify_id))
inserted_modify_id = I
return
else
if(!modify)
if (!user.transferItemToLoc(idcard,src))
return
modify = idcard
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
updateUsrDialog()
to_chat(user, "<span class='warning'>There's already an ID card in the console!</span>")
else
return ..()
/obj/machinery/computer/card/Destroy()
if(scan)
qdel(scan)
scan = null
if(modify)
qdel(modify)
modify = null
if(inserted_scan_id)
qdel(inserted_scan_id)
inserted_scan_id = null
if(inserted_modify_id)
qdel(inserted_modify_id)
inserted_modify_id = null
return ..()
/obj/machinery/computer/card/handle_atom_del(atom/A)
..()
if(A == scan)
scan = null
if(A == inserted_scan_id)
inserted_scan_id = null
updateUsrDialog()
if(A == modify)
modify = null
if(A == inserted_modify_id)
inserted_modify_id = null
updateUsrDialog()
/obj/machinery/computer/card/on_deconstruction()
if(scan)
scan.forceMove(drop_location())
scan = null
if(modify)
modify.forceMove(drop_location())
modify = null
if(inserted_scan_id)
inserted_scan_id.forceMove(drop_location())
inserted_scan_id = null
if(inserted_modify_id)
inserted_modify_id.forceMove(drop_location())
inserted_modify_id = null
//Check if you can't open a new position for a certain job
/obj/machinery/computer/card/proc/job_blacklisted(jobtitle)
@@ -130,9 +128,50 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
return -1
return 0
/obj/machinery/computer/card/proc/id_insert(mob/user, obj/item/card/id/I, target)
if(istype(I))
if(target)
to_chat(user, "<span class='warning'>There's already an ID card in the console!</span>")
return FALSE
if(!user.transferItemToLoc(I, src))
return FALSE
user.visible_message("<span class='notice'>[user] inserts an ID card into the console.</span>", \
"<span class='notice'>You insert the ID card into the console.</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
updateUsrDialog()
return TRUE
/obj/machinery/computer/card/proc/id_eject(mob/user, obj/target)
if(!target)
to_chat(user, "<span class='warning'>There's no ID card in the console!</span>")
return FALSE
else
target.forceMove(drop_location())
if(!issilicon(user) && Adjacent(user))
user.put_in_hands(target)
user.visible_message("<span class='notice'>[user] gets an ID card from the console.</span>", \
"<span class='notice'>You get the ID card from the console.</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
updateUsrDialog()
return TRUE
/obj/machinery/computer/card/AltClick(mob/user)
..()
if(!user.canUseTopic(src, !issilicon(user)) || !is_operational())
return
if(inserted_modify_id)
if(id_eject(user, inserted_modify_id))
inserted_modify_id = null
authenticated = FALSE
return
if(inserted_scan_id)
if(id_eject(user, inserted_scan_id))
inserted_scan_id = null
authenticated = FALSE
return
/obj/machinery/computer/card/ui_interact(mob/user)
. = ..()
var/dat
if(!SSticker)
return
@@ -147,15 +186,15 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
dat = "<a href='?src=[REF(src)];choice=return'>Return</a>"
dat += " || Confirm Identity: "
var/S
if(scan)
S = html_encode(scan.name)
if(inserted_scan_id)
S = html_encode(inserted_scan_id.name)
else
S = "--------"
dat += "<a href='?src=[REF(src)];choice=scan'>[S]</a>"
dat += "<a href='?src=[REF(src)];choice=inserted_scan_id'>[S]</a>"
dat += "<table>"
dat += "<tr><td style='width:25%'><b>Job</b></td><td style='width:25%'><b>Slots</b></td><td style='width:25%'><b>Open job</b></td><td style='width:25%'><b>Close job</b><td style='width:25%'><b>Prioritize</b></td></td></tr>"
var/ID
if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept)
if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept)
ID = 1
else
ID = 0
@@ -221,33 +260,33 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
var/target_name
var/target_owner
var/target_rank
if(modify)
target_name = html_encode(modify.name)
if(inserted_modify_id)
target_name = html_encode(inserted_modify_id.name)
else
target_name = "--------"
if(modify && modify.registered_name)
target_owner = html_encode(modify.registered_name)
if(inserted_modify_id && inserted_modify_id.registered_name)
target_owner = html_encode(inserted_modify_id.registered_name)
else
target_owner = "--------"
if(modify && modify.assignment)
target_rank = html_encode(modify.assignment)
if(inserted_modify_id && inserted_modify_id.assignment)
target_rank = html_encode(inserted_modify_id.assignment)
else
target_rank = "Unassigned"
var/scan_name
if(scan)
scan_name = html_encode(scan.name)
if(inserted_scan_id)
scan_name = html_encode(inserted_scan_id.name)
else
scan_name = "--------"
if(!authenticated)
header += "<br><i>Please insert the cards into the slots</i><br>"
header += "Target: <a href='?src=[REF(src)];choice=modify'>[target_name]</a><br>"
header += "Confirm Identity: <a href='?src=[REF(src)];choice=scan'>[scan_name]</a><br>"
header += "Target: <a href='?src=[REF(src)];choice=inserted_modify_id'>[target_name]</a><br>"
header += "Confirm Identity: <a href='?src=[REF(src)];choice=inserted_scan_id'>[scan_name]</a><br>"
else
header += "<div align='center'><br>"
header += "<a href='?src=[REF(src)];choice=modify'>Remove [target_name]</a> || "
header += "<a href='?src=[REF(src)];choice=scan'>Remove [scan_name]</a> <br> "
header += "<a href='?src=[REF(src)];choice=inserted_modify_id'>Remove [target_name]</a> || "
header += "<a href='?src=[REF(src)];choice=inserted_scan_id'>Remove [scan_name]</a> <br> "
header += "<a href='?src=[REF(src)];choice=mode;mode_target=1'>Access Crew Manifest</a> <br> "
header += "<a href='?src=[REF(src)];choice=logout'>Log Out</a></div>"
@@ -262,7 +301,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
var/body
if (authenticated && modify)
if (authenticated && inserted_modify_id)
var/carddesc = text("")
var/jobs = text("")
@@ -303,7 +342,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if(istype(src, /obj/machinery/computer/card/centcom))
accesses += "<h5>Central Command:</h5>"
for(var/A in get_all_centcom_access())
if(A in modify.access)
if(A in inserted_modify_id.access)
accesses += "<a href='?src=[REF(src)];choice=access;access_target=[A];allowed=0'><font color=\"red\">[replacetext(get_centcom_access_desc(A), " ", "&nbsp")]</font></a> "
else
accesses += "<a href='?src=[REF(src)];choice=access;access_target=[A];allowed=1'>[replacetext(get_centcom_access_desc(A), " ", "&nbsp")]</a> "
@@ -321,7 +360,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
continue
accesses += "<td style='width:14%' valign='top'>"
for(var/A in get_region_accesses(i))
if(A in modify.access)
if(A in inserted_modify_id.access)
accesses += "<a href='?src=[REF(src)];choice=access;access_target=[A];allowed=0'><font color=\"red\">[replacetext(get_access_desc(A), " ", "&nbsp")]</font></a> "
else
accesses += "<a href='?src=[REF(src)];choice=access;access_target=[A];allowed=1'>[replacetext(get_access_desc(A), " ", "&nbsp")]</a> "
@@ -353,52 +392,66 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
usr.set_machine(src)
switch(href_list["choice"])
if ("modify")
eject_id_modify(usr)
if ("scan")
eject_id_scan(usr)
if ("inserted_modify_id")
if (inserted_modify_id)
if(id_eject(usr, inserted_modify_id))
inserted_modify_id = null
else
var/mob/M = usr
var/obj/item/card/id/I = M.get_idcard(TRUE)
if(id_insert(usr, I, inserted_modify_id))
inserted_modify_id = I
if ("inserted_scan_id")
if (inserted_scan_id)
if(id_eject(usr, inserted_scan_id))
inserted_scan_id = null
else
var/mob/M = usr
var/obj/item/card/id/I = M.get_idcard(TRUE)
if(id_insert(usr, I, inserted_scan_id))
inserted_scan_id = I
if ("auth")
if ((!( authenticated ) && (scan || issilicon(usr)) && (modify || mode)))
if (check_access(scan))
if ((!( authenticated ) && (inserted_scan_id || issilicon(usr)) && (inserted_modify_id || mode)))
if (check_access(inserted_scan_id))
region_access = list()
head_subordinates = list()
if(ACCESS_CHANGE_IDS in scan.access)
if(ACCESS_CHANGE_IDS in inserted_scan_id.access)
if(target_dept)
head_subordinates = get_all_jobs()
region_access |= target_dept
authenticated = 1
else
authenticated = 2
playsound(src, 'sound/machines/terminal_on.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
else
if((ACCESS_HOP in scan.access) && ((target_dept==1) || !target_dept))
if((ACCESS_HOP in inserted_scan_id.access) && ((target_dept==1) || !target_dept))
region_access |= 1
get_subordinates("Head of Personnel")
if((ACCESS_HOS in scan.access) && ((target_dept==2) || !target_dept))
if((ACCESS_HOS in inserted_scan_id.access) && ((target_dept==2) || !target_dept))
region_access |= 2
get_subordinates("Head of Security")
if((ACCESS_CMO in scan.access) && ((target_dept==3) || !target_dept))
if((ACCESS_CMO in inserted_scan_id.access) && ((target_dept==3) || !target_dept))
region_access |= 3
get_subordinates("Chief Medical Officer")
if((ACCESS_RD in scan.access) && ((target_dept==4) || !target_dept))
if((ACCESS_RD in inserted_scan_id.access) && ((target_dept==4) || !target_dept))
region_access |= 4
get_subordinates("Research Director")
if((ACCESS_CE in scan.access) && ((target_dept==5) || !target_dept))
if((ACCESS_CE in inserted_scan_id.access) && ((target_dept==5) || !target_dept))
region_access |= 5
get_subordinates("Chief Engineer")
if((ACCESS_QM in scan.access) && ((target_dept==6) || !target_dept))
if((ACCESS_QM in inserted_scan_id.access) && ((target_dept==6) || !target_dept))
region_access |= 6
get_subordinates("Quartermaster")
if(region_access)
authenticated = 1
else if ((!( authenticated ) && issilicon(usr)) && (!modify))
else if ((!( authenticated ) && issilicon(usr)) && (!inserted_modify_id))
to_chat(usr, "<span class='warning'>You can't modify an ID without an ID inserted to modify! Once one is in the modify slot on the computer, you can log in.</span>")
if ("logout")
region_access = null
head_subordinates = null
authenticated = 0
playsound(src, 'sound/machines/terminal_off.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
if("access")
if(href_list["allowed"])
@@ -406,20 +459,20 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
var/access_type = text2num(href_list["access_target"])
var/access_allowed = text2num(href_list["allowed"])
if(access_type in (istype(src, /obj/machinery/computer/card/centcom)?get_all_centcom_access() : get_all_accesses()))
modify.access -= access_type
inserted_modify_id.access -= access_type
if(access_allowed == 1)
modify.access += access_type
playsound(src, "terminal_type", 50, 0)
inserted_modify_id.access += access_type
playsound(src, "terminal_type", 50, FALSE)
if ("assign")
if (authenticated == 2)
var/t1 = href_list["assign_target"]
if(t1 == "Custom")
var/newJob = reject_bad_text(input("Enter a custom job assignment.", "Assignment", modify ? modify.assignment : "Unassigned"), MAX_NAME_LEN)
var/newJob = reject_bad_text(input("Enter a custom job assignment.", "Assignment", inserted_modify_id ? inserted_modify_id.assignment : "Unassigned"), MAX_NAME_LEN)
if(newJob)
t1 = newJob
else if(t1 == "Unassigned")
modify.access -= get_all_accesses()
inserted_modify_id.access -= get_all_accesses()
else
var/datum/job/jobdatum
@@ -434,24 +487,24 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
updateUsrDialog()
return
modify.access = ( istype(src, /obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : jobdatum.get_access() )
if (modify)
modify.assignment = t1
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
inserted_modify_id.access = ( istype(src, /obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : jobdatum.get_access() )
if (inserted_modify_id)
inserted_modify_id.assignment = t1
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if ("demote")
if(modify.assignment in head_subordinates || modify.assignment == "Assistant")
modify.assignment = "Unassigned"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
if(inserted_modify_id.assignment in head_subordinates || inserted_modify_id.assignment == "Assistant")
inserted_modify_id.assignment = "Unassigned"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
else
to_chat(usr, "<span class='error'>You are not authorized to demote this position.</span>")
if ("reg")
if (authenticated)
var/t2 = modify
if ((authenticated && modify == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc)))
var/t2 = inserted_modify_id
if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc)))
var/newName = reject_bad_name(href_list["reg"])
if(newName)
modify.registered_name = newName
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
inserted_modify_id.registered_name = newName
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
else
to_chat(usr, "<span class='error'>Invalid name entered.</span>")
updateUsrDialog()
@@ -462,11 +515,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if("return")
//DISPLAY MAIN MENU
mode = 3;
playsound(src, "terminal_type", 25, 0)
playsound(src, "terminal_type", 25, FALSE)
if("make_job_available")
// MAKE ANOTHER JOB POSITION AVAILABLE FOR LATE JOINERS
if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept)
if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept)
var/edit_job_target = href_list["job"]
var/datum/job/j = SSjob.GetJob(edit_job_target)
if(!j)
@@ -479,11 +532,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
GLOB.time_last_changed_position = world.time / 10
j.total_positions++
opened_positions[edit_job_target]++
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if("make_job_unavailable")
// MAKE JOB POSITION UNAVAILABLE FOR LATE JOINERS
if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept)
if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept)
var/edit_job_target = href_list["job"]
var/datum/job/j = SSjob.GetJob(edit_job_target)
if(!j)
@@ -497,11 +550,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
GLOB.time_last_changed_position = world.time / 10
j.total_positions--
opened_positions[edit_job_target]--
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
if ("prioritize_job")
// TOGGLE WHETHER JOB APPEARS AS PRIORITIZED IN THE LOBBY
if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept)
if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept)
var/priority_target = href_list["job"]
var/datum/job/j = SSjob.GetJob(priority_target)
if(!j)
@@ -518,7 +571,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
else
SSjob.prioritized_jobs += j
to_chat(usr, "<span class='notice'>[j.title] has been successfully [priority ? "prioritized" : "unprioritized"]. Potential employees will notice your request.</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if ("print")
if (!( printing ))
@@ -531,59 +584,9 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
P.info = t1
P.name = "paper- 'Crew Manifest'"
printing = null
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
if (modify)
modify.update_label()
updateUsrDialog()
/obj/machinery/computer/card/AltClick(mob/user)
if(!user.canUseTopic(src, !issilicon(user)) || !is_operational())
return
if(scan)
eject_id_scan(user)
if(modify)
eject_id_modify(user)
/obj/machinery/computer/card/proc/eject_id_scan(mob/user)
if(scan)
scan.forceMove(drop_location())
if(!issilicon(user) && Adjacent(user))
user.put_in_hands(scan)
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
scan = null
else //switching the ID with the one you're holding
if(issilicon(user) || !Adjacent(user))
return
var/obj/item/I = user.get_active_held_item()
if(istype(I, /obj/item/card/id))
if(!user.transferItemToLoc(I,src))
return
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
scan = I
authenticated = FALSE
updateUsrDialog()
/obj/machinery/computer/card/proc/eject_id_modify(mob/user)
if(modify)
GLOB.data_core.manifest_modify(modify.registered_name, modify.assignment)
modify.update_label()
modify.forceMove(drop_location())
if(!issilicon(user) && Adjacent(user))
user.put_in_hands(modify)
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
modify = null
region_access = null
head_subordinates = null
else //switching the ID with the one you're holding
if(issilicon(user) || !Adjacent(user))
return
var/obj/item/I = user.get_active_held_item()
if(istype(I, /obj/item/card/id))
if (!user.transferItemToLoc(I,src))
return
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
modify = I
authenticated = FALSE
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
if (inserted_modify_id)
inserted_modify_id.update_label()
updateUsrDialog()
/obj/machinery/computer/card/proc/get_subordinates(rank)
+3 -1
View File
@@ -298,13 +298,15 @@
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
var/prev_locked = scanner.locked
scanner.locked = TRUE
spawn(20)
src.scan_occupant(scanner.occupant)
loading = 0
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
scanner.locked = prev_locked
//No locking an open scanner.
@@ -1,163 +0,0 @@
//computer that handle the points and teleports the prisoner
/obj/machinery/computer/gulag_teleporter_computer
name = "labor camp teleporter console"
desc = "Used to send criminals to the Labor Camp."
icon_screen = "explosive"
icon_keyboard = "security_key"
req_access = list(ACCESS_ARMORY)
circuit = /obj/item/circuitboard/computer/gulag_teleporter_console
var/default_goal = 200
var/obj/item/card/id/prisoner/id = null
var/obj/machinery/gulag_teleporter/teleporter = null
var/obj/structure/gulag_beacon/beacon = null
var/mob/living/carbon/human/prisoner = null
var/datum/data/record/temporary_record = null
light_color = LIGHT_COLOR_RED
/obj/machinery/computer/gulag_teleporter_computer/Initialize()
. = ..()
scan_machinery()
/obj/machinery/computer/gulag_teleporter_computer/Destroy()
if(id)
id.forceMove(get_turf(src))
return ..()
/obj/machinery/computer/gulag_teleporter_computer/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/card/id/prisoner))
if(!id)
if (!user.transferItemToLoc(W,src))
return
id = W
to_chat(user, "<span class='notice'>You insert [W].</span>")
return
else
to_chat(user, "<span class='notice'>There's an ID inserted already.</span>")
return ..()
/obj/machinery/computer/gulag_teleporter_computer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "gulag_console", name, 455, 440, master_ui, state)
ui.open()
/obj/machinery/computer/gulag_teleporter_computer/ui_data(mob/user)
var/list/data = list()
var/list/prisoner_list = list()
var/can_teleport = FALSE
if(teleporter && (teleporter.occupant && ishuman(teleporter.occupant)))
prisoner = teleporter.occupant
prisoner_list["name"] = prisoner.real_name
if(id)
can_teleport = TRUE
if(!isnull(GLOB.data_core.general))
for(var/r in GLOB.data_core.security)
var/datum/data/record/R = r
if(R.fields["name"] == prisoner_list["name"])
temporary_record = R
prisoner_list["crimstat"] = temporary_record.fields["criminal"]
data["prisoner"] = prisoner_list
if(teleporter)
data["teleporter"] = teleporter
data["teleporter_location"] = "([teleporter.x], [teleporter.y], [teleporter.z])"
data["teleporter_lock"] = teleporter.locked
data["teleporter_state_open"] = teleporter.state_open
if(beacon)
data["beacon"] = beacon
data["beacon_location"] = "([beacon.x], [beacon.y], [beacon.z])"
if(id)
data["id"] = id
data["id_name"] = id.registered_name
data["goal"] = id.goal
data["can_teleport"] = can_teleport
return data
/obj/machinery/computer/gulag_teleporter_computer/ui_act(action, list/params)
if(..())
return
if(!allowed(usr))
to_chat(usr, "<span class='warning'>Access denied.</span>")
return
switch(action)
if("scan_teleporter")
teleporter = findteleporter()
if("scan_beacon")
beacon = findbeacon()
if("handle_id")
if(id)
usr.put_in_hands(id)
id = null
else
var/obj/item/I = usr.is_holding_item_of_type(/obj/item/card/id/prisoner)
if(I)
if(!usr.transferItemToLoc(I, src))
return
id = I
if("set_goal")
var/new_goal = input("Set the amount of points:", "Points", id.goal) as num|null
if(!isnum(new_goal))
return
if(!new_goal)
new_goal = default_goal
if (new_goal > 1000)
to_chat(usr, "The entered amount of points is too large. Points have instead been set to the maximum allowed amount.")
id.goal = CLAMP(new_goal, 0, 1000) //maximum 1000 points
if("toggle_open")
if(teleporter.locked)
to_chat(usr, "The teleporter is locked")
return
teleporter.toggle_open()
if("teleporter_lock")
if(teleporter.state_open)
to_chat(usr, "Close the teleporter before locking!")
return
teleporter.locked = !teleporter.locked
if("teleport")
if(!teleporter || !beacon)
return
addtimer(CALLBACK(src, .proc/teleport, usr), 5)
/obj/machinery/computer/gulag_teleporter_computer/proc/scan_machinery()
teleporter = findteleporter()
beacon = findbeacon()
/obj/machinery/computer/gulag_teleporter_computer/proc/findteleporter()
var/obj/machinery/gulag_teleporter/teleporterf = null
for(var/direction in GLOB.cardinals)
teleporterf = locate(/obj/machinery/gulag_teleporter, get_step(src, direction))
if(teleporterf && teleporterf.is_operational())
return teleporterf
/obj/machinery/computer/gulag_teleporter_computer/proc/findbeacon()
return locate(/obj/structure/gulag_beacon)
/obj/machinery/computer/gulag_teleporter_computer/proc/teleport(mob/user)
if(!id) //incase the ID was removed after the transfer timer was set.
say("Warning: Unable to transfer prisoner without a valid Prisoner ID inserted!")
return
var/id_goal_not_set
if(!id.goal)
id_goal_not_set = TRUE
id.goal = default_goal
say("[id]'s ID card goal defaulting to [id.goal] points.")
log_game("[key_name(user)] teleported [key_name(prisoner)] to the Labor Camp [COORD(beacon)] for [id_goal_not_set ? "default goal of ":""][id.goal] points.")
teleporter.handle_prisoner(id, temporary_record)
playsound(src, 'sound/weapons/emitter.ogg', 50, 1)
prisoner.forceMove(get_turf(beacon))
prisoner.Knockdown(40) // small travel dizziness
to_chat(prisoner, "<span class='warning'>The teleportation makes you a little dizzy.</span>")
new /obj/effect/particle_effect/sparks(get_turf(prisoner))
playsound(src, "sparks", 50, 1)
if(teleporter.locked)
teleporter.locked = FALSE
teleporter.toggle_open()
id = null
temporary_record = null
-6
View File
@@ -22,12 +22,6 @@
/obj/machinery/computer/med_data/syndie
icon_keyboard = "syndie_key"
/obj/machinery/computer/med_data/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/card/id))
id_insert_scan(user)
else
return ..()
/obj/machinery/computer/med_data/ui_interact(mob/user)
. = ..()
if(isliving(user))
+2 -1
View File
@@ -35,7 +35,8 @@
//Someone needs to break down the dat += into chunks instead of long ass lines.
/obj/machinery/computer/secure_data/ui_interact(mob/user)
. = ..()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if(isliving(user))
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if(src.z > 6)
to_chat(user, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
return
+5 -7
View File
@@ -370,16 +370,14 @@
O.find_target()
O.update_explanation_text()
if(!(O.target))
O.owner.objectives -= O
qdel(O)
if(mob_occupant.mind && mob_occupant.mind.assigned_role)
if(mob_occupant.mind)
//Handle job slot/tater cleanup.
var/job = mob_occupant.mind.assigned_role
SSjob.FreeRole(job)
if(mob_occupant.mind.objectives.len)
mob_occupant.mind.objectives.Cut()
mob_occupant.mind.special_role = null
if(mob_occupant.mind.assigned_role)
var/job = mob_occupant.mind.assigned_role
SSjob.FreeRole(job)
mob_occupant.mind.special_role = null
// Delete them from datacore.
+3 -3
View File
@@ -249,10 +249,10 @@
return 0
/obj/machinery/door/airlock/plasma/attackby(obj/item/C, mob/user, params)
if(C.is_hot() > 300)//If the temperature of the object is over 300, then ignite
if(C.get_temperature() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma airlock ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(src)]")
log_game("Plasma airlock ignited by [key_name(user)] in [AREACOORD(src)]")
ignite(C.is_hot())
ignite(C.get_temperature())
else
return ..()
@@ -499,7 +499,7 @@
SEND_SOUND(L, sound(pick('sound/hallucinations/turn_around1.ogg','sound/hallucinations/turn_around2.ogg'),0,1,50))
flash_color(L, flash_color="#960000", flash_time=20)
L.Knockdown(40)
L.throw_at(throwtarget, 5, 1,src)
L.throw_at(throwtarget, 5, 1)
return 0
/obj/machinery/door/airlock/cult/proc/conceal()
+6 -5
View File
@@ -24,6 +24,8 @@ Possible to do for anyone motivated enough:
* Holopad
*/
GLOBAL_LIST_EMPTY(network_holopads)
#define HOLOPAD_PASSIVE_POWER_USAGE 1
#define HOLOGRAM_POWER_USAGE 2
@@ -55,7 +57,6 @@ Possible to do for anyone motivated enough:
var/record_user //user that inititiated the recording
var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
var/static/list/holopads = list()
var/obj/effect/overlay/holoray/ray
var/ringing = FALSE
var/offset = FALSE
@@ -96,7 +97,7 @@ Possible to do for anyone motivated enough:
/obj/machinery/holopad/Initialize()
. = ..()
if(on_network)
holopads += src
GLOB.network_holopads += src
/obj/machinery/holopad/Destroy()
if(outgoing_call)
@@ -116,7 +117,7 @@ Possible to do for anyone motivated enough:
QDEL_NULL(disk)
holopads -= src
GLOB.network_holopads -= src
return ..()
/obj/machinery/holopad/power_change()
@@ -260,7 +261,7 @@ Possible to do for anyone motivated enough:
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
if(usr.loc == loc)
var/list/callnames = list()
for(var/I in holopads)
for(var/I in GLOB.network_holopads)
var/area/A = get_area(I)
if(A)
LAZYADD(callnames[A], I)
@@ -474,7 +475,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
var/obj/effect/overlay/holo_pad_hologram/h = masters[holo_owner]
if(!h || h.HC) //Holocalls can't change source.
return FALSE
for(var/pad in holopads)
for(var/pad in GLOB.network_holopads)
var/obj/machinery/holopad/another = pad
if(another == src)
continue
@@ -562,6 +562,7 @@
//Shooting Code:
A.preparePixelProjectile(target, T)
A.firer = src
A.fired_from = src
A.fire()
return A
-1
View File
@@ -89,7 +89,6 @@
buckled_mob.clear_alert("buckled")
buckled_mobs -= buckled_mob
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force)
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, src, force)
post_unbuckle_mob(.)
@@ -45,11 +45,11 @@
if(!reagents.total_volume) //scooped up all of it
qdel(src)
return
if(W.is_hot()) //todo: make heating a reagent holder proc
if(W.get_temperature()) //todo: make heating a reagent holder proc
if(istype(W, /obj/item/clothing/mask/cigarette))
return
else
var/hotness = W.is_hot()
var/hotness = W.get_temperature()
reagents.expose_temperature(hotness)
to_chat(user, "<span class='notice'>You heat [name] with [W]!</span>")
else
+5 -9
View File
@@ -97,9 +97,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// non-clothing items
var/datum/dog_fashion/dog_fashion = null
var/datum/rpg_loot/rpg_loot = null
//Tooltip vars
var/force_string //string form of an item's force. Edit this var only to set a custom force string
var/last_force_string_check = 0
@@ -124,7 +121,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
actions_types = null
if(GLOB.rpg_loot_items)
rpg_loot = new(src)
AddComponent(/datum/component/fantasy)
if(force_string)
item_flags |= FORCE_STRING_OVERRIDE
@@ -149,7 +146,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
m.temporarilyRemoveItemFromInventory(src, TRUE)
for(var/X in actions)
qdel(X)
QDEL_NULL(rpg_loot)
return ..()
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
@@ -557,7 +553,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
/obj/item/throw_impact(atom/A, datum/thrownthing/throwingdatum)
if(A && !QDELETED(A))
SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, A, throwingdatum)
if(is_hot() && isliving(A))
if(get_temperature() && isliving(A))
var/mob/living/L = A
L.IgniteMob()
var/itempush = 1
@@ -624,10 +620,10 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if(flags & ITEM_SLOT_NECK)
owner.update_inv_neck()
/obj/item/proc/is_hot()
/obj/item/proc/get_temperature()
return heat
/obj/item/proc/is_sharp()
/obj/item/proc/get_sharpness()
return sharpness
/obj/item/proc/get_dismemberment_chance(obj/item/bodypart/affecting)
@@ -654,7 +650,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
location.hotspot_expose(flame_heat, 1)
/obj/item/proc/ignition_effect(atom/A, mob/user)
if(is_hot())
if(get_temperature())
. = "<span class='notice'>[user] lights [A] with [src].</span>"
else
. = ""
+2 -2
View File
@@ -439,11 +439,11 @@ RLD
/obj/item/construction/rcd/proc/rcd_create(atom/A, mob/user)
var/list/rcd_results = A.rcd_vals(user, src)
if(!rcd_results)
return FALSE
var/turf/the_turf = get_turf(A)
var/turf_coords = "[COORD(the_turf)]"
investigate_log("[user] is attempting to use [src] on [A] (loc [turf_coords] at [the_turf]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD)
if(!rcd_results)
return FALSE
if(do_after(user, rcd_results["delay"] * delay_mod, target = A))
if(checkResource(rcd_results["cost"], user))
var/atom/cached = A
+1 -1
View File
@@ -34,7 +34,7 @@
light() //honk
return ..()
/obj/item/candle/is_hot()
/obj/item/candle/get_temperature()
return lit * heat
/obj/item/candle/proc/light(show_message)
+5 -5
View File
@@ -90,7 +90,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(istype(mask_item, /obj/item/clothing/mask/cigarette))
return mask_item
/obj/item/match/is_hot()
/obj/item/match/get_temperature()
return lit * heat
//////////////////
@@ -255,7 +255,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/cigarette/fire_act(exposed_temperature, exposed_volume)
light()
/obj/item/clothing/mask/cigarette/is_hot()
/obj/item/clothing/mask/cigarette/get_temperature()
return lit * heat
// Cigarette brands.
@@ -530,7 +530,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
add_overlay(lighter_overlay)
/obj/item/lighter/ignition_effect(atom/A, mob/user)
if(is_hot())
if(get_temperature())
. = "<span class='rose'>With a single flick of [user.p_their()] wrist, [user] smoothly lights [A] with [src]. Damn [user.p_theyre()] cool.</span>"
/obj/item/lighter/proc/set_lit(new_lit)
@@ -605,7 +605,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/lighter/process()
open_flame()
/obj/item/lighter/is_hot()
/obj/item/lighter/get_temperature()
return lit * heat
@@ -654,7 +654,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
add_overlay(lighter_overlay)
/obj/item/lighter/greyscale/ignition_effect(atom/A, mob/user)
if(is_hot())
if(get_temperature())
. = "<span class='notice'>After some fiddling, [user] manages to light [A] with [src].</span>"
+9 -2
View File
@@ -17,6 +17,11 @@
desc = "A stylish upgrade (?) to the intelliCard."
icon_state = "aitater"
/obj/item/aicard/aispook
name = "intelliLantern"
desc = "A spoOoOoky upgrade to the intelliCard."
icon_state = "aispook"
/obj/item/aicard/suicide_act(mob/living/user)
user.visible_message("<span class='suicide'>[user] is trying to upload [user.p_them()]self into [src]! That's not going to work out well!</span>")
return BRUTELOSS
@@ -26,16 +31,18 @@
if(!proximity || !target)
return
if(AI) //AI is on the card, implies user wants to upload it.
target.transfer_ai(AI_TRANS_FROM_CARD, user, AI, src)
log_combat(user, AI, "carded", src)
target.transfer_ai(AI_TRANS_FROM_CARD, user, AI, src)
else //No AI on the card, therefore the user wants to download one.
target.transfer_ai(AI_TRANS_TO_CARD, user, null, src)
if(AI)
log_combat(user, AI, "carded", src)
update_icon() //Whatever happened, update the card's state (icon, name) to match.
/obj/item/aicard/update_icon()
cut_overlays()
if(AI)
name = "[initial(name)]- [AI.name]"
name = "[initial(name)] - [AI.name]"
if(AI.stat == DEAD)
icon_state = "[initial(icon_state)]-404"
else
@@ -89,30 +89,23 @@
else
to_chat(user, "<span class='notice'>Anomalous error. Summon a coder.</span>")
if(istype(target, /mob/living))
var/mob/living/victim = target
if(istype(victim, /mob/living/carbon/human))
if(user.zone_selected == "groin") // pp smol. There's probably a smarter way to do this but im retarded. If you have a simpler method let me know.
var/list/organs = victim.getorganszone("groin")
for(var/internal_organ in organs)
if(istype(internal_organ, /obj/item/organ/genital/penis))
var/obj/item/organ/genital/penis/O = internal_organ
playsound(get_turf(src), 'sound/weapons/flash.ogg', 50, 1)
victim.visible_message("<span class='warning'>[user] is preparing to shrink [victim]\'s [O.name] with their bluespace compression kit!</span>")
if(do_mob(user, victim, 40) && charges > 0 && O.length > 0)
victim.visible_message("<span class='warning'>[user] has shrunk [victim]\'s [O.name]!</span>")
playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 50, 1)
sparks()
flash_lighting_fx(3, 3, LIGHT_COLOR_CYAN)
charges -= 1
O.length -= 5
if(O.length < 1)
victim.visible_message("<span class='warning'>[user]\'s [O.name] vanishes!</span>")
qdel(O) // no pp for you
else
O.update_size()
O.update_appearance()
else if(ishuman(target) && user.zone_selected == BODY_ZONE_PRECISE_GROIN)
var/mob/living/carbon/human/H = target
var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
if(!P)
return
playsound(get_turf(src), 'sound/weapons/flash.ogg', 50, 1)
H.visible_message("<span class='warning'>[user] is preparing to shrink [H]\'s [P.name] with their bluespace compression kit!</span>")
if(do_mob(user, H, 40) && charges > 0 && P.length > 0)
H.visible_message("<span class='warning'>[user] has shrunk [H]\'s [P.name]!</span>")
playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 50, 1)
sparks()
flash_lighting_fx(3, 3, LIGHT_COLOR_CYAN)
charges -= 1
var/p_name = P.name
P.modify_size(-5)
if(QDELETED(P))
H.visible_message("<span class='warning'>[H]\'s [p_name] vanishes!</span>")
/obj/item/compressionkit/attackby(obj/item/I, mob/user, params)
+103 -146
View File
@@ -6,8 +6,7 @@
icon = 'icons/mob/dogborg.dmi'
icon_state = "sleeper"
w_class = WEIGHT_CLASS_TINY
var/mob/living/carbon/patient = null
var/mob/living/silicon/robot/hound = null
var/mob/living/carbon/patient
var/inject_amount = 10
var/min_health = -100
var/cleaning = FALSE
@@ -61,8 +60,18 @@
/obj/item/dogborg/sleeper/Exit(atom/movable/O)
return 0
/obj/item/dogborg/sleeper/proc/get_host()
if(!loc)
return
if(iscyborg(loc))
return loc
else if(iscyborg(loc.loc))
return loc.loc //cursed cyborg code
/obj/item/dogborg/sleeper/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity)
hound = loc
var/mob/living/silicon/robot/hound = get_host()
if(!hound)
return
if(!proximity)
return
if(!iscarbon(target))
@@ -82,7 +91,8 @@
if(!in_range(src, target)) //Proximity is probably old news by now, do a new check.
return //If they moved away, you can't eat them.
if(patient) return //If you try to eat two people at once, you can only eat one.
if(patient)
return //If you try to eat two people at once, you can only eat one.
else //If you don't have someone in you, proceed.
if(!isjellyperson(target) && ("toxin" in injection_chems))
@@ -94,14 +104,17 @@
target.forceMove(src)
target.reset_perspective(src)
target.ExtinguishMob() //The tongue already puts out fire stacks but being put into the sleeper shouldn't allow you to keep burning.
update_gut()
update_gut(hound)
user.visible_message("<span class='warning'>[voracious ? "[hound]'s [src.name] lights up and expands as [target] slips inside into their [src.name]." : "[hound]'s sleeper indicator lights up as [target] is scooped up into [hound.p_their()] [src]."]</span>", \
"<span class='notice'>Your [voracious ? "[src.name] lights up as [target] slips into" : "sleeper indicator light shines brightly as [target] is scooped inside"] your [src]. Life support functions engaged.</span>")
message_admins("[key_name(hound)] has sleeper'd [key_name(patient)] as a dogborg. [ADMIN_JMP(src)]")
playsound(hound, 'sound/effects/bin_close.ogg', 100, 1)
/obj/item/dogborg/sleeper/container_resist(mob/living/user)
hound = loc
var/mob/living/silicon/robot/hound = get_host()
if(!hound)
go_out(user)
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
if(user.a_intent == INTENT_HELP)
@@ -113,55 +126,41 @@
"<span class='notice'>[voracious ? "You start struggling inside of [src]'s tight, flexible confines," : "You start pounding against the metallic walls of [src],"] trying to trigger the release... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
"<span class='italics'>You hear a [voracious ? "couple of thumps" : "loud banging noise"] coming from within [hound].</span>")
if(do_after(user, breakout_time, target = src))
if(!user || user.stat != CONSCIOUS || user.loc != src )
return
user.visible_message("<span class='warning'>[user] successfully broke out of [hound.name]!</span>", \
"<span class='notice'>You successfully break out of [hound.name]!</span>")
go_out()
go_out(user, hound)
/obj/item/dogborg/sleeper/proc/go_out(var/target)
hound = loc
hound.setClickCooldown(50)
var/voracious = TRUE
if(!hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
voracious = FALSE
else
for(var/mob/M in contents)
if(!M.client || !(M.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
voracious = FALSE
if(length(contents) > 0)
hound.visible_message("<span class='warning'>[voracious ? "[hound] empties out [hound.p_their()] contents via [hound.p_their()] release port." : "[hound]'s underside slides open with an audible clunk before [hound.p_their()] [src] flips over, carelessly dumping its contents onto the ground below [hound.p_them()] before closing right back up again."]</span>", \
"<span class='notice'>[voracious ? "You empty your contents via your release port." : "You open your sleeper hatch, quickly releasing all of the contents within before closing it again."]</span>")
if(target)
if(iscarbon(target))
var/mob/living/carbon/person = target
person.forceMove(get_turf(src))
person.reset_perspective()
else
var/obj/T = target
T.loc = hound.loc
/obj/item/dogborg/sleeper/proc/go_out(atom/movable/target, mob/living/silicon/robot/hound)
var/voracious = hound ? TRUE : FALSE
var/list/targets = target && hound ? list(target) : contents
if(hound)
hound.setClickCooldown(50)
if(!hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
voracious = FALSE
else
for(var/C in contents)
if(iscarbon(C))
var/mob/living/carbon/person = C
person.forceMove(get_turf(src))
person.reset_perspective()
else
var/obj/T = C
T.loc = hound.loc
items_preserved.Cut()
update_gut()
cleaning = FALSE
for(var/mob/M in targets)
if(!M.client || !(M.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
voracious = FALSE
if(length(targets))
if(hound)
hound.visible_message("<span class='warning'>[voracious ? "[hound] empties out [hound.p_their()] contents via [hound.p_their()] release port." : "[hound]'s underside slides open with an audible clunk before [hound.p_their()] [src] flips over, carelessly dumping its contents onto the ground below [hound.p_them()] before closing right back up again."]</span>", \
"<span class='notice'>[voracious ? "You empty your contents via your release port." : "You open your sleeper hatch, quickly releasing all of the contents within before closing it again."]</span>")
for(var/a in contents)
var/atom/movable/AM = a
AM.forceMove(get_turf(src))
if(ismob(AM))
var/mob/M = AM
M.reset_perspective()
playsound(loc, voracious ? 'sound/effects/splat.ogg' : 'sound/effects/bin_close.ogg', 50, 1)
else //You clicked eject with nothing in you, let's just reset stuff to be sure.
items_preserved.Cut()
cleaning = FALSE
update_gut()
items_preserved.Cut()
cleaning = FALSE
if(hound)
update_gut(hound)
/obj/item/dogborg/sleeper/attack_self(mob/user)
if(..())
. = ..()
if(. || !iscyborg(user))
return
ui_interact(user)
@@ -219,30 +218,31 @@
return data
/obj/item/dogborg/sleeper/ui_act(action, params)
if(..())
. = ..()
if(. || !iscyborg(usr))
return
switch(action)
if("eject")
go_out()
go_out(null, usr)
. = TRUE
if("inject")
var/chem = params["chem"]
if(!patient)
return
inject_chem(chem)
inject_chem(chem, usr)
. = TRUE
if("cleaning")
if(!contents)
to_chat(src, "Your [src] is already cleaned.")
return
if(patient)
to_chat(patient, "<span class='danger'>[hound.name]'s [src] fills with caustic enzymes around you!</span>")
to_chat(patient, "<span class='danger'>[usr.name]'s [src] fills with caustic enzymes around you!</span>")
to_chat(src, "<span class='danger'>Cleaning process enabled.</span>")
clean_cycle()
clean_cycle(usr)
. = TRUE
/obj/item/dogborg/sleeper/proc/update_gut()
/obj/item/dogborg/sleeper/proc/update_gut(mob/living/silicon/robot/hound)
//Well, we HAD one, what happened to them?
var/prociconupdate = FALSE
var/currentenvy = hound.sleeper_nv
@@ -291,7 +291,7 @@
//Update icon and return new patient
hound.update_icons()
return(C)
return
//Cleaning looks better with red on, even with nobody in it
if(cleaning && !patient)
@@ -307,8 +307,10 @@
hound.update_icons()
//Gurgleborg process
/obj/item/dogborg/sleeper/proc/clean_cycle()
/obj/item/dogborg/sleeper/proc/clean_cycle(mob/living/silicon/robot/hound)
//Sanity
if(!hound)
return
for(var/I in items_preserved)
if(!(I in contents))
items_preserved -= I
@@ -320,13 +322,12 @@
if(cleaning_cycles)
cleaning_cycles--
cleaning = TRUE
for(var/mob/living/carbon/human/T in (touchable_items))
if((T.status_flags & GODMODE) || !T.digestable)
items_preserved += T
for(var/mob/living/carbon/C in (touchable_items))
if((C.status_flags & GODMODE) || !C.digestable)
items_preserved += C
else
T.adjustBruteLoss(2)
T.adjustFireLoss(3)
update_gut()
C.adjustBruteLoss(2)
C.adjustFireLoss(3)
if(contents)
var/atom/target = pick(touchable_items)
if(iscarbon(target)) //Handle the target being a mob
@@ -359,7 +360,6 @@
if(!T.dropItemToGround(W))
qdel(W)
qdel(T)
update_gut()
//Handle the target being anything but a mob
else if(isobj(target))
var/obj/T = target
@@ -374,12 +374,10 @@
cleaning_cycles = initial(cleaning_cycles)
cleaning = FALSE
to_chat(hound, "<span class='notice'>Your [src] chimes it ends its self-cleaning cycle.</span>")//Belly is entirely empty
update_gut()
if(!length(contents))
to_chat(hound, "<span class='notice'>Your [src] is now clean. Ending self-cleaning cycle.</span>")
cleaning = FALSE
update_gut()
//sound effects
if(prob(50))
@@ -397,13 +395,17 @@
else if(H in contents)
H.playsound_local(source, null, 65, falloff = 0, S = prey_digest)
update_gut(hound)
if(cleaning)
addtimer(CALLBACK(src, .proc/clean_cycle), 50)
addtimer(CALLBACK(src, .proc/clean_cycle, hound), 50)
/obj/item/dogborg/sleeper/proc/CheckAccepted(obj/item/I)
return is_type_in_typecache(I, important_items)
/obj/item/dogborg/sleeper/proc/inject_chem(chem)
/obj/item/dogborg/sleeper/proc/inject_chem(chem, mob/living/silicon/robot/hound)
if(!hound)
return
if(hound.cell.charge <= 800) //This is so borgs don't kill themselves with it. Remember, 750 charge used every injection.
to_chat(hound, "<span class='notice'>You don't have enough power to synthesize fluids.</span>")
return
@@ -438,40 +440,27 @@
else
. = ..()
/obj/item/dogborg/sleeper/K9/afterattack(var/atom/movable/target, mob/living/silicon/user, proximity)
hound = loc
/obj/item/dogborg/sleeper/K9/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity)
var/mob/living/silicon/robot/hound = get_host()
if(!hound || !istype(target) || !proximity || target.anchored)
return
if (!target.devourable)
to_chat(user, "The target registers an error code. Unable to insert into [src].")
return
if(target)
to_chat(user,"<span class='warning'>Your [src] is already occupied.</span>")
return
if(target.buckled)
to_chat(user,"<span class='warning'>[target] is buckled and can not be put into your [src].</span>")
return
user.visible_message("<span class='warning'>[hound.name] is ingesting [target] into their [src].</span>", "<span class='notice'>You start ingesting [target] into your [src.name]...</span>")
if(do_after(user, 30, target = target) && !patient && !target.buckled)
target.forceMove(src)
target.reset_perspective(src)
update_gut(hound)
user.visible_message("<span class='warning'>[hound.name]'s mobile brig clunks in series as [target] slips inside.</span>", "<span class='notice'>Your mobile brig groans lightly as [target] slips inside.</span>")
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots
if(!istype(target))
return
if(!proximity)
return
if(target.anchored)
return
if(isobj(target))
to_chat(user, "You are above putting such trash inside of yourself.")
return
if(iscarbon(target))
var/mob/living/carbon/brigman = target
if (!brigman.devourable)
to_chat(user, "The target registers an error code. Unable to insert into [src].")
return
if(patient)
to_chat(user,"<span class='warning'>Your [src] is already occupied.</span>")
return
if(brigman.buckled)
to_chat(user,"<span class='warning'>[brigman] is buckled and can not be put into your [src].</span>")
return
user.visible_message("<span class='warning'>[hound.name] is ingesting [brigman] into their [src].</span>", "<span class='notice'>You start ingesting [brigman] into your [src.name]...</span>")
if(do_after(user, 30, target = brigman) && !patient && !brigman.buckled)
if(!in_range(src, brigman)) //Proximity is probably old news by now, do a new check.
return //If they moved away, you can't eat them.
brigman.forceMove(src)
brigman.reset_perspective(src)
update_gut()
user.visible_message("<span class='warning'>[hound.name]'s mobile brig clunks in series as [brigman] slips inside.</span>", "<span class='notice'>Your mobile brig groans lightly as [brigman] slips inside.</span>")
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots
return
return
/obj/item/dogborg/sleeper/compactor //Janihound gut.
name = "garbage processor"
@@ -489,31 +478,25 @@
else
. = ..()
/obj/item/dogborg/sleeper/compactor/afterattack(var/atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS
hound = loc
var/obj/item/target_obj = target
if(!istype(target))
return
if(!proximity)
return
if(target.anchored)
/obj/item/dogborg/sleeper/compactor/afterattack(atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS
var/mob/living/silicon/robot/hound = get_host()
if(!hound || !istype(target) || !proximity || target.anchored)
return
if(length(contents) > (max_item_count - 1))
to_chat(user,"<span class='warning'>Your [src] is full. Eject or process contents to continue.</span>")
return
if(isobj(target))
if(CheckAccepted(target))
to_chat(user,"<span class='warning'>\The [target] registers an error code to your [src]</span>")
if(isitem(target))
var/obj/item/I = target
if(CheckAccepted(I))
to_chat(user,"<span class='warning'>[I] registers an error code to your [src]</span>")
return
if(target_obj.w_class > WEIGHT_CLASS_NORMAL)
to_chat(user,"<span class='warning'>\The [target] is too large to fit into your [src]</span>")
if(I.w_class > WEIGHT_CLASS_NORMAL)
to_chat(user,"<span class='warning'>[I] is too large to fit into your [src]</span>")
return
user.visible_message("<span class='warning'>[hound.name] is ingesting [target.name] into their [src.name].</span>", "<span class='notice'>You start ingesting [target] into your [src.name]...</span>")
user.visible_message("<span class='warning'>[hound.name] is ingesting [I] into their [src.name].</span>", "<span class='notice'>You start ingesting [target] into your [src.name]...</span>")
if(do_after(user, 15, target = target) && length(contents) < max_item_count)
if(!in_range(src, target)) //Proximity is probably old news by now, do a new check.
return //If they moved away, you can't eat them. This still applies to items, don't magically eat things I picked up already.
target.forceMove(src)
user.visible_message("<span class='warning'>[hound.name]'s garbage processor groans lightly as [target.name] slips inside.</span>", "<span class='notice'>Your garbage compactor groans lightly as [target] slips inside.</span>")
I.forceMove(src)
I.visible_message("<span class='warning'>[hound.name]'s garbage processor groans lightly as [I] slips inside.</span>", "<span class='notice'>Your garbage compactor groans lightly as [I] slips inside.</span>")
playsound(hound, 'sound/machines/disposalflush.ogg', 50, 1)
if(length(contents) > 11) //grow that tum after a certain junk amount
hound.sleeper_r = 1
@@ -523,9 +506,9 @@
hound.update_icons()
return
else if(iscarbon(target))
var/mob/living/carbon/trashman = target
if (!trashman.devourable)
if(iscarbon(target) || issilicon(target))
var/mob/living/trashman = target
if(!trashman.devourable)
to_chat(user, "<span class='warning'>[target] registers an error code to your [src]</span>")
return
if(patient)
@@ -536,34 +519,8 @@
return
user.visible_message("<span class='warning'>[hound.name] is ingesting [trashman] into their [src].</span>", "<span class='notice'>You start ingesting [trashman] into your [src.name]...</span>")
if(do_after(user, 30, target = trashman) && !patient && !trashman.buckled && length(contents) < max_item_count)
if(!in_range(src, trashman)) //Proximity is probably old news by now, do a new check.
return //If they moved away, you can't eat them.
trashman.forceMove(src)
trashman.reset_perspective(src)
update_gut()
user.visible_message("<span class='warning'>[hound.name]'s garbage processor groans lightly as [trashman] slips inside.</span>", "<span class='notice'>Your garbage compactor groans lightly as [trashman] slips inside.</span>")
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1)
return
else if(issilicon(target))
var/mob/living/silicon/trashbot = target
if (!trashbot.devourable)
to_chat(user, "<span class='warning'>[target] registers an error code to your [src]</span>")
return
if(patient)
to_chat(user,"<span class='warning'>Your [src] is already occupied.</span>")
return
if(trashbot.buckled)
to_chat(user,"<span class='warning'>[trashbot] is buckled and can not be put into your [src].</span>")
return
user.visible_message("<span class='warning'>[hound.name] is ingesting [trashbot] into their [src].</span>", "<span class='notice'>You start ingesting [trashbot] into your [src.name]...</span>")
if(do_after(user, 30, target = trashbot) && !patient && !trashbot.buckled && length(contents) < max_item_count)
if(!in_range(src, trashbot)) //Proximity is probably old news by now, do a new check.
return //If they moved away, you can't eat them.
trashbot.forceMove(src)
trashbot.reset_perspective(src)
update_gut()
user.visible_message("<span class='warning'>[hound.name]'s garbage processor groans lightly as [trashbot] slips inside.</span>", "<span class='notice'>Your garbage compactor groans lightly as [trashbot] slips inside.</span>")
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1)
return
return
@@ -324,7 +324,7 @@
damtype = "fire"
START_PROCESSING(SSobj, src)
/obj/item/flashlight/flare/is_hot()
/obj/item/flashlight/flare/get_temperature()
return on * heat
/obj/item/flashlight/flare/torch
+4 -2
View File
@@ -148,9 +148,11 @@
if(10)
src.add_overlay("pai-null")
if(11)
src.add_overlay(mutable_appearance('modular_citadel/icons/obj/aicards.dmi', "pai-exclamation")) // CITADEL EDIT
src.add_overlay("pai-exclamation")
if(12)
src.add_overlay(mutable_appearance('modular_citadel/icons/obj/aicards.dmi', "pai-question")) // CITADEL EDIT
src.add_overlay("pai-question")
if(13)
src.add_overlay("pai-sunglasses")
/obj/item/paicard/proc/alertUpdate()
visible_message("<span class ='info'>[src] flashes a message across its screen, \"Additional personalities available for download.\"", "<span class='notice'>[src] bleeps electronically.</span>")
+10 -9
View File
@@ -338,17 +338,17 @@ SLIME SCANNER
if(report_organs) //we either finish the list, or set it to be empty if no organs were reported in that category
if(!max_damage)
max_damage = "\t<span class='alert'>Non-Functional Organs: </span>"
max_damage = "\t<span class='alert'>Non-Functional Organs: </span>\n"
else
max_damage += "</span>"
max_damage += "</span>\n"
if(!major_damage)
major_damage = "\t<span class='info'>Severely Damaged Organs: </span>"
major_damage = "\t<span class='info'>Severely Damaged Organs: </span>\n"
else
major_damage += "</span>"
major_damage += "</span>\n"
if(!minor_damage)
minor_damage = "\t<span class='info'>Mildly Damaged Organs: </span>"
minor_damage = "\t<span class='info'>Mildly Damaged Organs: </span>\n"
else
minor_damage += "</span>"
minor_damage += "</span>\n"
msg += "[minor_damage]"
msg += "[major_damage]"
msg += "[max_damage]"
@@ -382,10 +382,11 @@ SLIME SCANNER
else if (S.mutantstomach != initial(S.mutantstomach))
mutant = TRUE
msg += "<span class='info'>Species: [H.dna.custom_species ? H.dna.custom_species : S.name] Base: [S.name]</span>\n"
msg += "\t<span class='info'>Reported Species: [H.dna.custom_species ? H.dna.custom_species : S.name]</span>\n"
msg += "\t<span class='info'>Base Species: [S.name]</span>\n"
if(mutant)
msg += "<span class='info'>Subject has mutations present.</span>"
msg += "<span class='info'>Body temperature: [round(M.bodytemperature-T0C,0.1)] &deg;C ([round(M.bodytemperature*1.8-459.67,0.1)] &deg;F)</span>\n"
msg += "\t<span class='info'>Subject has mutations present.</span>\n"
msg += "\t<span class='info'>Body temperature: [round(M.bodytemperature-T0C,0.1)] &deg;C ([round(M.bodytemperature*1.8-459.67,0.1)] &deg;F)</span>\n"
// Time of death
if(M.tod && (M.stat == DEAD || ((HAS_TRAIT(M, TRAIT_FAKEDEATH)) && !advanced)))
@@ -12,7 +12,7 @@
/obj/item/implant/storage/removed(source, silent = FALSE, special = 0)
if(!special)
qdel(pocket)
QDEL_NULL(pocket)
else
pocket?.moveToNullspace()
return ..()
@@ -29,7 +29,7 @@
return FALSE
. = ..()
if(.)
if(pocket)
if(!QDELETED(pocket))
pocket.forceMove(target)
else
pocket = new(target)
@@ -41,7 +41,6 @@
desc = "A tiny yet spacious pocket, usually found implanted inside sneaky syndicate agents and nowhere else."
component_type = /datum/component/storage/concrete/implant
resistance_flags = INDESTRUCTIBLE //A bomb!
item_flags = DROPDEL
/obj/item/implanter/storage
name = "implanter (storage)"
+1 -1
View File
@@ -52,5 +52,5 @@
var/obj/item/tank/T = W
blow(T, user)
return
if (W.is_sharp() || W.is_hot() || is_pointed(W))
if (W.get_sharpness() || W.get_temperature() || is_pointed(W))
burst()
+2 -2
View File
@@ -28,7 +28,7 @@
/obj/item/melee/transforming/energy/add_blood_DNA(list/blood_dna)
return FALSE
/obj/item/melee/transforming/energy/is_sharp()
/obj/item/melee/transforming/energy/get_sharpness()
return active * sharpness
/obj/item/melee/transforming/energy/process()
@@ -46,7 +46,7 @@
STOP_PROCESSING(SSobj, src)
set_light(0)
/obj/item/melee/transforming/energy/is_hot()
/obj/item/melee/transforming/energy/get_temperature()
return active * heat
/obj/item/melee/transforming/energy/ignition_effect(atom/A, mob/user)
@@ -23,7 +23,7 @@
else
if(attack_verb_off.len)
attack_verb = attack_verb_off
if(is_sharp())
if(get_sharpness())
AddComponent(/datum/component/butchering, 50, 100, 0, hitsound, !active)
/obj/item/melee/transforming/attack_self(mob/living/carbon/user)
@@ -65,7 +65,7 @@
icon_state = initial(icon_state)
w_class = initial(w_class)
total_mass = initial(total_mass)
if(is_sharp())
if(get_sharpness())
var/datum/component/butchering/BT = LoadComponent(/datum/component/butchering)
BT.butchering_enabled = TRUE
else
+1 -1
View File
@@ -117,7 +117,7 @@
to_chat(user, "<span class='notice'>You try to pet [src], but it has no stuffing. Aww...</span>")
/obj/item/toy/plush/attackby(obj/item/I, mob/living/user, params)
if(I.is_sharp())
if(I.get_sharpness())
if(!grenade)
if(!stuffed)
to_chat(user, "<span class='warning'>You already murdered it!</span>")
+2 -2
View File
@@ -430,7 +430,7 @@
A.BB.nodamage = FALSE
A.BB.speed = 0.5
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
A.fire_casing(target, user, params, 0, 0, null, 0)
A.fire_casing(target, user, params, 0, 0, null, 0, src)
user.visible_message("<span class='warning'>[user] blasts a flying lollipop at [target]!</span>")
check_amount()
@@ -446,7 +446,7 @@
A.BB.speed = 0.5
A.BB.color = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
playsound(src.loc, 'sound/weapons/bulletflyby3.ogg', 50, 1)
A.fire_casing(target, user, params, 0, 0, null, 0)
A.fire_casing(target, user, params, 0, 0, null, 0, src)
user.visible_message("<span class='warning'>[user] shoots a high-velocity gumball at [target]!</span>")
check_amount()
+1 -1
View File
@@ -128,7 +128,7 @@
/obj/item/stack/medical/gauze/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wirecutters) || I.is_sharp())
if(istype(I, /obj/item/wirecutters) || I.get_sharpness())
if(get_amount() < 2)
to_chat(user, "<span class='warning'>You need at least two gauzes to do this!</span>")
return
@@ -219,7 +219,7 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
//Step one - dehairing.
/obj/item/stack/sheet/animalhide/attackby(obj/item/W, mob/user, params)
if(W.is_sharp())
if(W.get_sharpness())
playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1)
user.visible_message("[user] starts cutting hair off \the [src].", "<span class='notice'>You start cutting the hair off \the [src]...</span>", "<span class='italics'>You hear the sound of a knife rubbing against flesh.</span>")
if(do_after(user, 50, target = src))
@@ -178,11 +178,11 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \
. = ..()
/obj/item/stack/sheet/mineral/plasma/attackby(obj/item/W as obj, mob/user as mob, params)
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
if(W.get_temperature() > 300)//If the temperature of the object is over 300, then ignite
var/turf/T = get_turf(src)
message_admins("Plasma sheets ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]")
log_game("Plasma sheets ignited by [key_name(user)] in [AREACOORD(T)]")
fire_act(W.is_hot())
fire_act(W.get_temperature())
else
return ..()
+1 -1
View File
@@ -855,7 +855,7 @@
if(SMILEY)
desc = "A paper sack with a crude smile etched onto the side."
return 0
else if(W.is_sharp())
else if(W.get_sharpness())
if(!contents.len)
if(item_state == "paperbag_None")
user.show_message("<span class='notice'>You cut eyeholes into [src].</span>", 1)
+3 -2
View File
@@ -309,9 +309,10 @@
if(fancy_open)
icon_state = "[initial(icon_state)]_open"
var/cigar_position = 1 //generate sprites for cigars in the box
var/cigar_position = 0 //to keep track of the pixel_x offset of each new overlay.
for(var/obj/item/clothing/mask/cigarette/cigar/smokes in contents)
var/mutable_appearance/cigar_overlay = mutable_appearance(icon, "[smokes.icon_off]_[cigar_position]")
var/mutable_appearance/cigar_overlay = mutable_appearance(icon, "[smokes.icon_off]")
cigar_overlay.pixel_x = 3 * cigar_position
add_overlay(cigar_overlay)
cigar_position++
+25 -1
View File
@@ -49,6 +49,10 @@
lefthand_file = 'icons/mob/inhands/misc/sheets_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/sheets_righthand.dmi'
var/obj/item/nuke_core/core
var/nt =FALSE //For the lid
/obj/item/nuke_core_container/nt
nt = TRUE
/obj/item/nuke_core_container/Destroy()
QDEL_NULL(core)
@@ -67,10 +71,13 @@
/obj/item/nuke_core_container/proc/seal()
if(istype(core))
STOP_PROCESSING(SSobj, core)
icon_state = "core_container_sealed"
playsound(src, 'sound/items/deconstruct.ogg', 60, 1)
if(ismob(loc))
to_chat(loc, "<span class='warning'>[src] is permanently sealed, [core]'s radiation is contained.</span>")
if(nt != TRUE)
icon_state = "core_container_sealed"
else
icon_state = "core_container_sealed_nt"
/obj/item/nuke_core_container/attackby(obj/item/nuke_core/core, mob/user)
if(istype(core))
@@ -92,6 +99,11 @@
toolspeed = 0.5
random_color = FALSE
/obj/item/screwdriver/nuke/nt
desc = "A screwdriver with an ultra thin diamon tip."
toolspeed = 0.25
icon_state = "screwdriver_nt"
/obj/item/paper/guides/antag/nuke_instructions
info = "How to break into a Nanotrasen self-destruct terminal and remove its plutonium core:<br>\
<ul>\
@@ -103,6 +115,18 @@
<li>???</li>\
</ul>"
/obj/item/paper/guides/nt/nuke_instructions
info = "How to remove its plutonium core:<br>\
<ul>\
<li>Use a screwdriver with a very thin tip (provided) to unscrew the terminal's front panel</li>\
<li>Dislodge and remove the front panel with a crowbar</li>\
<li>Cut the inner metal plate with a welding tool</li>\
<li>Pry off the inner plate with a crowbar to expose the radioactive core</li>\
<li>Use the core container to remove the plutonium core; the container will take some time to seal</li>\
<li>Send core back to CC</li>\
</ul>"
// STEALING SUPERMATTER
/obj/item/paper/guides/antag/supermatter_sliver
+1 -1
View File
@@ -223,7 +223,7 @@
..()
to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].")
/obj/item/weldingtool/is_hot()
/obj/item/weldingtool/get_temperature()
return welding * heat
//Returns whether or not the welding tool is currently on.
+1 -1
View File
@@ -79,7 +79,7 @@
to_chat(user, "<span class='notice'>You fill the balloon with the contents of [I].</span>")
I.reagents.trans_to(src, 10)
update_icon()
else if(I.is_sharp())
else if(I.get_sharpness())
balloon_burst()
else
return ..()
+1 -1
View File
@@ -41,7 +41,7 @@ LINEN BINS
return
/obj/item/bedsheet/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wirecutters) || I.is_sharp())
if(istype(I, /obj/item/wirecutters) || I.get_sharpness())
var/obj/item/stack/sheet/cloth/C = new (get_turf(src), 3)
transfer_fingerprints_to(C)
C.add_fingerprint(user)
@@ -10,7 +10,7 @@
new /obj/item/clothing/under/rank/chief_engineer(src)
new /obj/item/clothing/under/rank/chief_engineer/skirt(src)
new /obj/item/clothing/head/hardhat/white(src)
new /obj/item/clothing/head/welding(src)
new /obj/item/clothing/head/hardhat/weldhat/white(src)
new /obj/item/clothing/gloves/color/yellow(src)
new /obj/item/clothing/shoes/sneakers/brown(src)
new /obj/item/tank/jetpack/suit(src)
+1 -1
View File
@@ -236,7 +236,7 @@
canSmoothWith = list(/obj/structure/falsewall/plasma, /turf/closed/wall/mineral/plasma)
/obj/structure/falsewall/plasma/attackby(obj/item/W, mob/user, params)
if(W.is_hot() > 300)
if(W.get_temperature() > 300)
var/turf/T = get_turf(src)
message_admins("Plasma falsewall ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]")
log_game("Plasma falsewall ignited by [key_name(user)] in [AREACOORD(T)]")
+3 -12
View File
@@ -300,18 +300,9 @@
throw_speed = 2
throw_range = 4
/obj/item/twohanded/required/kirbyplants/equipped(mob/living/user)
var/image/I = image(icon = 'icons/obj/flora/plants.dmi' , icon_state = src.icon_state, loc = user)
I.copy_overlays(src)
I.override = 1
add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I)
I.layer = ABOVE_MOB_LAYER
..()
/obj/item/twohanded/required/kirbyplants/dropped(mob/living/user)
..()
user.remove_alt_appearance("sneaking_mission")
/obj/item/twohanded/required/kirbyplants/Initialize()
. = ..()
AddComponent(/datum/component/tactical)
/obj/item/twohanded/required/kirbyplants/random
icon = 'icons/obj/flora/_flora.dmi'
@@ -193,7 +193,7 @@
return
/obj/structure/mineral_door/transparent/plasma/attackby(obj/item/W, mob/user, params)
if(W.is_hot())
if(W.get_temperature())
var/turf/T = get_turf(src)
message_admins("Plasma mineral door ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]")
log_game("Plasma mineral door ignited by [key_name(user)] in [AREACOORD(T)]")
+2 -2
View File
@@ -127,11 +127,11 @@
..()
/obj/structure/statue/plasma/attackby(obj/item/W, mob/user, params)
if(W.is_hot() > 300 && !QDELETED(src))//If the temperature of the object is over 300, then ignite
if(W.get_temperature() > 300 && !QDELETED(src))//If the temperature of the object is over 300, then ignite
var/turf/T = get_turf(src)
message_admins("Plasma statue ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]")
log_game("Plasma statue ignited by [key_name(user)] in [AREACOORD(T)]")
ignite(W.is_hot())
ignite(W.get_temperature())
else
return ..()
+2 -2
View File
@@ -731,8 +731,8 @@
/obj/structure/window/paperframe/attackby(obj/item/W, mob/user)
if(W.is_hot())
fire_act(W.is_hot())
if(W.get_temperature())
fire_act(W.get_temperature())
return
if(user.a_intent == INTENT_HARM)
return ..()
@@ -43,10 +43,10 @@
PlasmaBurn(exposed_temperature)
/turf/open/floor/mineral/plasma/attackby(obj/item/W, mob/user, params)
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
if(W.get_temperature() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma flooring was ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(src)]")
log_game("Plasma flooring was ignited by [key_name(user)] in [AREACOORD(src)]")
ignite(W.is_hot())
ignite(W.get_temperature())
return
..()
@@ -94,10 +94,10 @@
canSmoothWith = list(/turf/closed/wall/mineral/plasma, /obj/structure/falsewall/plasma)
/turf/closed/wall/mineral/plasma/attackby(obj/item/W, mob/user, params)
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
if(W.get_temperature() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma wall ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(src)]")
log_game("Plasma wall ignited by [key_name(user)] in [AREACOORD(src)]")
ignite(W.is_hot())
ignite(W.get_temperature())
return
..()
+3
View File
@@ -25,6 +25,9 @@
H.facial_hair_color = H.hair_color
H.eye_color = random_eye_color()
H.dna.blood_type = random_blood_type()
H.saved_underwear = H.underwear
H.saved_undershirt = H.undershirt
H.saved_socks = H.socks
// Mutant randomizing, doesn't affect the mob appearance unless it's the specific mutant.
H.dna.features["mcolor"] = random_short_color()
@@ -96,7 +96,6 @@ GLOBAL_LIST_EMPTY(antagonists)
LAZYREMOVE(owner.antag_datums, src)
if(!silent && owner.current)
farewell()
owner.objectives -= objectives
var/datum/team/team = get_team()
if(team)
team.remove_member(owner)
@@ -132,14 +131,14 @@ GLOBAL_LIST_EMPTY(antagonists)
report += printplayer(owner)
var/objectives_complete = TRUE
if(owner.objectives.len)
report += printobjectives(owner)
for(var/datum/objective/objective in owner.objectives)
if(objectives.len)
report += printobjectives(objectives)
for(var/datum/objective/objective in objectives)
if(!objective.check_completion())
objectives_complete = FALSE
break
if(owner.objectives.len == 0 || objectives_complete)
if(objectives.len == 0 || objectives_complete)
report += "<span class='greentext big'>The [name] was successful!</span>"
else
report += "<span class='redtext big'>The [name] has failed!</span>"
@@ -216,25 +215,6 @@ GLOBAL_LIST_EMPTY(antagonists)
return
antag_memory = new_memo
//This datum will autofill the name with special_role
//Used as placeholder for minor antagonists, please create proper datums for these
/datum/antagonist/auto_custom
show_in_antagpanel = FALSE
antagpanel_category = "Other"
show_name_in_check_antagonists = TRUE
/datum/antagonist/auto_custom/on_gain()
..()
name = owner.special_role
//Add all objectives not already owned by other datums to this one.
var/list/already_registered_objectives = list()
for(var/datum/antagonist/A in owner.antag_datums)
if(A == src)
continue
else
already_registered_objectives |= A.objectives
objectives = owner.objectives - already_registered_objectives
//This one is created by admin tools for custom objectives
/datum/antagonist/custom
antagpanel_category = "Custom"
-1
View File
@@ -30,7 +30,6 @@
var/datum/objective/blob_takeover/main = new
main.owner = owner
objectives += main
owner.objectives |= objectives
/datum/antagonist/blob/apply_innate_effects(mob/living/mob_override)
if(!isovermind(owner.current))
@@ -0,0 +1,33 @@
/datum/antagonist/blood_contract
name = "Blood Contract Target"
show_in_roundend = FALSE
show_in_antagpanel = FALSE
/datum/antagonist/blood_contract/on_gain()
. = ..()
give_objective()
start_the_hunt()
/datum/antagonist/blood_contract/proc/give_objective()
var/datum/objective/survive/survive = new
survive.owner = owner
objectives += survive
/datum/antagonist/blood_contract/greet()
. = ..()
to_chat(owner, "<span class='userdanger'>You've been marked for death! Don't let the demons get you! KILL THEM ALL!</span>")
/datum/antagonist/blood_contract/proc/start_the_hunt()
var/mob/living/carbon/human/H = owner.current
if(!istype(H))
return
H.add_atom_colour("#FF0000", ADMIN_COLOUR_PRIORITY)
var/obj/effect/mine/pickup/bloodbath/B = new(H)
INVOKE_ASYNC(B, /obj/effect/mine/pickup/bloodbath/.proc/mineEffect, H) //could use moving out from the mine
for(var/mob/living/carbon/human/P in GLOB.player_list)
if(P == H)
continue
to_chat(P, "<span class='userdanger'>You have an overwhelming desire to kill [H]. [H.p_theyve(TRUE)] been marked red! Whoever [H.p_they()] [H.p_were()], friend or foe, go kill [H.p_them()]!</span>")
P.put_in_hands(new /obj/item/kitchen/knife/butcher(P), TRUE)
@@ -9,7 +9,6 @@
for(var/O in directives)
var/datum/objective/brainwashing/objective = new(O)
B.objectives += objective
M.objectives += objective
B.greet()
else
B = new()
@@ -32,10 +31,6 @@
antagpanel_category = "Other"
show_name_in_check_antagonists = TRUE
/datum/antagonist/brainwashed/on_gain()
owner.objectives |= objectives
. = ..()
/datum/antagonist/brainwashed/greet()
to_chat(owner, "<span class='warning'>Your mind reels as it begins focusing on a single purpose...</span>")
to_chat(owner, "<big><span class='warning'><b>Follow the Directives, at any cost!</b></span></big>")
@@ -20,7 +20,6 @@
/datum/antagonist/brother/on_gain()
SSticker.mode.brothers += owner
objectives += team.objectives
owner.objectives += objectives
owner.special_role = special_role
finalize_brother()
return ..()

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