diff --git a/baystation12.dme b/baystation12.dme index b10cfc162d6..cbe537a6e93 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1248,6 +1248,7 @@ #include "code\modules\mob\living\silicon\decoy\death.dm" #include "code\modules\mob\living\silicon\decoy\decoy.dm" #include "code\modules\mob\living\silicon\decoy\life.dm" +#include "code\modules\mob\living\silicon\pai\admin.dm" #include "code\modules\mob\living\silicon\pai\death.dm" #include "code\modules\mob\living\silicon\pai\examine.dm" #include "code\modules\mob\living\silicon\pai\life.dm" @@ -1279,6 +1280,7 @@ #include "code\modules\mob\living\silicon\robot\drone\drone_damage.dm" #include "code\modules\mob\living\silicon\robot\drone\drone_items.dm" #include "code\modules\mob\living\silicon\robot\drone\drone_manufacturer.dm" +#include "code\modules\mob\living\silicon\robot\drone\drone_say.dm" #include "code\modules\mob\living\simple_animal\bees.dm" #include "code\modules\mob\living\simple_animal\corpse.dm" #include "code\modules\mob\living\simple_animal\parrot.dm" @@ -1460,6 +1462,7 @@ #include "code\modules\random_map\random_map.dm" #include "code\modules\reagents\Chemistry-Colours.dm" #include "code\modules\reagents\Chemistry-Holder.dm" +#include "code\modules\reagents\Chemistry-Logging.dm" #include "code\modules\reagents\Chemistry-Machinery.dm" #include "code\modules\reagents\Chemistry-Metabolism.dm" #include "code\modules\reagents\Chemistry-Readme.dm" diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm index 62a6daea16f..07c7b650d1f 100644 --- a/code/ZAS/Airflow.dm +++ b/code/ZAS/Airflow.dm @@ -241,7 +241,7 @@ mob/living/carbon/human/airflow_hit(atom/A) zone/proc/movables() . = list() for(var/turf/T in contents) - for(var/atom/A in T) - if(istype(A, /obj/effect) || istype(A, /mob/aiEye)) + for(var/atom/movable/A in T) + if(!A.simulated || A.anchored || istype(A, /obj/effect) || istype(A, /mob/aiEye)) continue - . += A \ No newline at end of file + . += A diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm index d26db30a194..501c49ae556 100644 --- a/code/ZAS/Fire.dm +++ b/code/ZAS/Fire.dm @@ -295,7 +295,7 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0) //if the reaction is progressing too slow then it isn't self-sustaining anymore and burns out if(zone) //be less restrictive with canister and tank reactions - if((!liquid_fuel || used_fuel <= FIRE_LIQUD_MIN_BURNRATE) && (!gas_fuel || used_fuel <= FIRE_GAS_MIN_BURNRATE*group_multiplier)) + if((!liquid_fuel || used_fuel <= FIRE_LIQUD_MIN_BURNRATE) && (!gas_fuel || used_fuel <= FIRE_GAS_MIN_BURNRATE*zone.contents.len)) return 0 diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index ecfb96d5629..0bd074e96be 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -881,6 +881,8 @@ proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0) // Movement based on lower left corner. Tiles that do not fit // into the new area will not be moved. + // Does *not* affect gases etc; copied turfs will be changed via ChangeTurf, and the dir, icon, and icon_state copied. All other vars will remain default. + if(!A || !src) return 0 var/list/turfs_src = get_area_turfs(src.type) @@ -934,7 +936,8 @@ proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0) if(istype(B, /turf/space)) continue moving - var/turf/X = new T.type(B) + var/turf/X = B + X.ChangeTurf(T.type) X.set_dir(old_dir1) X.icon_state = old_icon_state1 X.icon = old_icon1 //Shuttle floors are in shuttle.dmi while the defaults are floors.dmi @@ -974,12 +977,6 @@ proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0) copiedobjs += newobjs copiedobjs += newmobs - - - for(var/V in T.vars) - if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key","x","y","z","contents", "luminosity"))) - X.vars[V] = T.vars[V] - // var/area/AR = X.loc // if(AR.lighting_use_dynamic) @@ -995,22 +992,9 @@ proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0) - var/list/doors = new/list() - if(toupdate.len) for(var/turf/simulated/T1 in toupdate) - for(var/obj/machinery/door/D2 in T1) - doors += D2 - /*if(T1.parent) - air_master.groups_to_rebuild += T1.parent - else - air_master.tiles_to_update += T1*/ - - for(var/obj/O in doors) - O:update_nearby_tiles(1) - - - + air_master.mark_for_update(T1) return copiedobjs @@ -1299,24 +1283,29 @@ var/list/WALLITEMS = list( colour += temp_col return colour +var/mob/dview/dview_mob = new + //Version of view() which ignores darkness, because BYOND doesn't have it. /proc/dview(var/range = world.view, var/center, var/invis_flags = 0) if(!center) return - var/global/mob/dview/DV - if(!DV) - DV = new + dview_mob.loc = center - DV.loc = center + dview_mob.see_invisible = invis_flags - DV.see_in_dark = range - DV.see_invisible = invis_flags - - . = view(range, DV) - DV.loc = null + . = view(range, dview_mob) + dview_mob.loc = null /mob/dview invisibility = 101 density = 0 + anchored = 1 + simulated = 0 + + see_in_dark = 1e6 + +/mob/dview/New() + // do nothing. we don't want to be in any mob lists; we're a dummy not a mob. + diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index fe5dcc0d677..fa299b34959 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -121,6 +121,8 @@ var/list/gamemode_cache = list() var/organ_health_multiplier = 1 var/organ_regeneration_multiplier = 1 + var/organs_decay + var/default_brain_health = 400 //Paincrit knocks someone down once they hit 60 shock_stage, so by default make it so that close to 100 additional damage needs to be dealt, //so that it's similar to HALLOSS. Lowered it a bit since hitting paincrit takes much longer to wear off than a halloss stun. @@ -708,6 +710,12 @@ var/list/gamemode_cache = list() config.organ_regeneration_multiplier = value / 100 if("organ_damage_spillover_multiplier") config.organ_damage_spillover_multiplier = value / 100 + if("organs_can_decay") + config.organs_decay = 1 + if("default_brain_health") + config.default_brain_health = text2num(value) + if(!config.default_brain_health || config.default_brain_health < 1) + config.default_brain_health = initial(config.default_brain_health) if("bones_can_break") config.bones_can_break = value if("limbs_can_break") diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 0152af8b130..b0f6c5099be 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -50,6 +50,11 @@ datum/controller/game_controller/proc/setup_objects() for(var/atom/movable/object in world) object.initialize() + admin_notice("Initializing pipe networks", R_DEBUG) sleep(-1) for(var/obj/machinery/atmospherics/machine in machines) diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm index 707880ff553..2bd56163d55 100644 --- a/code/controllers/voting.dm +++ b/code/controllers/voting.dm @@ -188,9 +188,9 @@ datum/controller/vote if(mode) if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder) return 0 - if(current_votes[ckey]) - choices[choices[current_votes[ckey]]]-- - if(vote && 1<=vote && vote<=choices.len) + if(vote && vote >= 1 && vote <= choices.len) + if(current_votes[ckey]) + choices[choices[current_votes[ckey]]]-- voted += usr.ckey choices[choices[vote]]++ //check this current_votes[ckey] = vote diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 808c216d0dd..edfffde816a 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -198,9 +198,7 @@ var/global/const/base_law_type = /datum/ai_laws/nanotrasen var/index = laws.Find(law) if(index) laws -= law - world << state.len for(index, index < state.len, index++) - world << index state[index] = state[index+1] sorted_laws.Cut() diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 4859ce2239f..84a64d8ade4 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -138,9 +138,160 @@ proc/get_id_photo(var/mob/living/carbon/human/H) - H.regenerate_icons() - var/icon/preview_icon = icon(H.icon) - for(var/image/I in H.overlays_standing) - if(I && I.icon) - preview_icon.Blend(icon(I.icon, I.icon_state), ICON_OVERLAY) + var/icon/preview_icon = null + + var/g = "m" + if (H.gender == FEMALE) + g = "f" + + var/icon/icobase = H.species.icobase + + preview_icon = new /icon(icobase, "torso_[g]") + var/icon/temp + temp = new /icon(icobase, "groin_[g]") + preview_icon.Blend(temp, ICON_OVERLAY) + temp = new /icon(icobase, "head_[g]") + preview_icon.Blend(temp, ICON_OVERLAY) + + for(var/obj/item/organ/external/E in H.organs) + preview_icon.Blend(E.get_icon(), ICON_OVERLAY) + + //Tail + if(H.species.tail) + temp = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[H.species.tail]_s") + preview_icon.Blend(temp, ICON_OVERLAY) + + // Skin tone + if(H.species.flags & HAS_SKIN_TONE) + if (H.s_tone >= 0) + preview_icon.Blend(rgb(H.s_tone, H.s_tone, H.s_tone), ICON_ADD) + else + preview_icon.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT) + + // Skin color + if(H.species.flags & HAS_SKIN_TONE) + if(!H.species || H.species.flags & HAS_SKIN_COLOR) + preview_icon.Blend(rgb(H.r_skin, H.g_skin, H.b_skin), ICON_ADD) + + var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = H.species ? H.species.eyes : "eyes_s") + + if (H.species.flags & HAS_EYE_COLOR) + eyes_s.Blend(rgb(H.r_eyes, H.g_eyes, H.b_eyes), ICON_ADD) + + var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] + if(hair_style) + var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + hair_s.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD) + eyes_s.Blend(hair_s, ICON_OVERLAY) + + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style] + if(facial_hair_style) + var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") + facial_s.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD) + eyes_s.Blend(facial_s, ICON_OVERLAY) + + var/icon/clothes_s = null + switch(H.mind.assigned_role) + if("Head of Personnel") + clothes_s = new /icon('icons/mob/uniform.dmi', "hop_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if("Bartender") + clothes_s = new /icon('icons/mob/uniform.dmi', "ba_suit_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Gardener") + clothes_s = new /icon('icons/mob/uniform.dmi', "hydroponics_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Chef") + clothes_s = new /icon('icons/mob/uniform.dmi', "chef_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Janitor") + clothes_s = new /icon('icons/mob/uniform.dmi', "janitor_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Librarian") + clothes_s = new /icon('icons/mob/uniform.dmi', "red_suit_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Quartermaster") + clothes_s = new /icon('icons/mob/uniform.dmi', "qm_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if("Cargo Technician") + clothes_s = new /icon('icons/mob/uniform.dmi', "cargotech_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Shaft Miner") + clothes_s = new /icon('icons/mob/uniform.dmi', "miner_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Lawyer") + clothes_s = new /icon('icons/mob/uniform.dmi', "internalaffairs_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if("Chaplain") + clothes_s = new /icon('icons/mob/uniform.dmi', "chapblack_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Research Director") + clothes_s = new /icon('icons/mob/uniform.dmi', "director_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + if("Scientist") + clothes_s = new /icon('icons/mob/uniform.dmi', "sciencewhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_tox_open"), ICON_OVERLAY) + if("Chemist") + clothes_s = new /icon('icons/mob/uniform.dmi', "chemistrywhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_chem_open"), ICON_OVERLAY) + if("Chief Medical Officer") + clothes_s = new /icon('icons/mob/uniform.dmi', "cmo_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_cmo_open"), ICON_OVERLAY) + if("Medical Doctor") + clothes_s = new /icon('icons/mob/uniform.dmi', "medical_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + if("Geneticist") + clothes_s = new /icon('icons/mob/uniform.dmi', "geneticswhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_gen_open"), ICON_OVERLAY) + if("Virologist") + clothes_s = new /icon('icons/mob/uniform.dmi', "virologywhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_vir_open"), ICON_OVERLAY) + if("Captain") + clothes_s = new /icon('icons/mob/uniform.dmi', "captain_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if("Head of Security") + clothes_s = new /icon('icons/mob/uniform.dmi', "hosred_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) + if("Warden") + clothes_s = new /icon('icons/mob/uniform.dmi', "warden_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) + if("Detective") + clothes_s = new /icon('icons/mob/uniform.dmi', "detective_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "detective"), ICON_OVERLAY) + if("Security Officer") + clothes_s = new /icon('icons/mob/uniform.dmi', "secred_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) + if("Chief Engineer") + clothes_s = new /icon('icons/mob/uniform.dmi', "chief_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + if("Station Engineer") + clothes_s = new /icon('icons/mob/uniform.dmi', "engine_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "orange"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + if("Atmospheric Technician") + clothes_s = new /icon('icons/mob/uniform.dmi', "atmos_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + if("Roboticist") + clothes_s = new /icon('icons/mob/uniform.dmi', "robotics_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + else + clothes_s = new /icon('icons/mob/uniform.dmi', "grey_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + preview_icon.Blend(eyes_s, ICON_OVERLAY) + if(clothes_s) + preview_icon.Blend(clothes_s, ICON_OVERLAY) + qdel(eyes_s) + qdel(clothes_s) + return preview_icon diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 77800d97dfd..b7520acefc5 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -22,9 +22,11 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/New() manifest += "" /datum/supply_packs/specialops diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index efe744174bf..059a883aad3 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -60,7 +60,8 @@ /datum/antagonist/proc/get_candidates(var/ghosts_only) candidates = list() // Clear. candidates = ticker.mode.get_players_for_role(role_type, id) - // Prune restricted jobs and status. Broke it up for readability. + // Prune restricted status. Broke it up for readability. + // Note that this is done before jobs are handed out. for(var/datum/mind/player in candidates) if(ghosts_only && !istype(player.current, /mob/dead)) candidates -= player @@ -75,7 +76,9 @@ return candidates /datum/antagonist/proc/attempt_random_spawn() - attempt_spawn(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB)) + build_candidate_list(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB)) + attempt_spawn() + finalize_spawn() /datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player) if(!can_late_spawn()) @@ -88,27 +91,59 @@ add_antagonist(player,0,1,0,1,1) return -/datum/antagonist/proc/attempt_spawn(var/ghosts_only) - +/datum/antagonist/proc/build_candidate_list(var/ghosts_only) // Get the raw list of potential players. update_current_antag_max() candidates = get_candidates(ghosts_only) +//Selects players that will be spawned in the antagonist role from the potential candidates +//Selected players are added to the pending_antagonists lists. +//Attempting to spawn an antag role with ANTAG_OVERRIDE_JOB should be done before jobs are assigned, +//so that they do not occupy regular job slots. All other antag roles should be spawned after jobs are +//assigned, so that job restrictions can be respected. +/datum/antagonist/proc/attempt_spawn(var/rebuild_candidates = 1) + // Update our boundaries. if(!candidates.len) return 0 //Grab candidates randomly until we have enough. - while(candidates.len) + while(candidates.len && pending_antagonists.len < cur_max) var/datum/mind/player = pick(candidates) - pending_antagonists |= player candidates -= player + draft_antagonist(player) + return 1 +/datum/antagonist/proc/draft_antagonist(var/datum/mind/player) + //Check if the player can join in this antag role, or if the player has already been given an antag role. + if(!can_become_antag(player) || player.special_role) + return 0 + + pending_antagonists |= player + + //Ensure that antags with ANTAG_OVERRIDE_JOB do not occupy job slots. + if(flags & ANTAG_OVERRIDE_JOB) + player.assigned_role = role_text + + //Ensure that a player cannot be drafted for multiple antag roles, taking up slots for antag roles that they will not fill. + player.special_role = role_text + + return 1 + +//Spawns all pending_antagonists. This is done separately from attempt_spawn in case the game mode setup fails. /datum/antagonist/proc/finalize_spawn() - if(!pending_antagonists || !pending_antagonists.len) + if(!pending_antagonists) return + for(var/datum/mind/player in pending_antagonists) - if(can_become_antag(player) && !player.special_role) - add_antagonist(player,0,0,1) - pending_antagonists.Cut() \ No newline at end of file + pending_antagonists -= player + add_antagonist(player,0,0,1) + +//Resets all pending_antagonists, clearing their special_role (and assigned_role if ANTAG_OVERRIDE_JOB is set) +/datum/antagonist/proc/reset() + for(var/datum/mind/player in pending_antagonists) + if(flags & ANTAG_OVERRIDE_JOB) + player.assigned_role = null + player.special_role = null + pending_antagonists.Cut() diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm index c16ea0a7c9f..7815167d6fe 100644 --- a/code/game/antagonist/antagonist_add.dm +++ b/code/game/antagonist/antagonist_add.dm @@ -9,6 +9,8 @@ return 0 current_antagonists |= player + + //do this again, just in case if(flags & ANTAG_OVERRIDE_JOB) player.assigned_role = role_text player.special_role = role_text diff --git a/code/game/antagonist/antagonist_create.dm b/code/game/antagonist/antagonist_create.dm index 3e6585f6b9e..502f1366839 100644 --- a/code/game/antagonist/antagonist_create.dm +++ b/code/game/antagonist/antagonist_create.dm @@ -42,7 +42,13 @@ return W /datum/antagonist/proc/create_radio(var/freq, var/mob/living/carbon/human/player) - var/obj/item/device/radio/R = new /obj/item/device/radio/headset(player) + var/obj/item/device/radio/R + + if(freq == SYND_FREQ) + R = new/obj/item/device/radio/headset/syndicate(player) + else + R = new/obj/item/device/radio/headset(player) + R.set_frequency(freq) player.equip_to_slot_or_del(R, slot_l_ear) return R diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index effb7ad0826..07a18948852 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -901,7 +901,7 @@ area/space/atmosalert() icon_state = "tcomsatcham" /area/server - name = "\improper Messaging Server Room" + name = "\improper Research Server Room" icon_state = "server" //Crew @@ -1793,7 +1793,7 @@ area/space/atmosalert() ambience = list('sound/ambience/ambimalf.ogg') /area/turret_protected/ai_server_room - name = "AI Server Room" + name = "Messaging Server Room" icon_state = "ai_server" /area/turret_protected/ai diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 38452c3d5bd..19746eeef76 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -14,13 +14,17 @@ all_areas += src if(!requires_power) - power_light = 0 //rastaf0 - power_equip = 0 //rastaf0 - power_environ = 0 //rastaf0 + power_light = 0 + power_equip = 0 + power_environ = 0 ..() -// spawn(15) +/area/proc/initialize() + if(!requires_power || !apc) + power_light = 0 + power_equip = 0 + power_environ = 0 power_change() // all machines set to current power level, also updates lighting icon /area/proc/get_contents() @@ -227,7 +231,7 @@ var/list/mob/living/forced_ambiance_list = new var/area/oldarea = L.lastarea if((oldarea.has_gravity == 0) && (newarea.has_gravity == 1) && (L.m_intent == "run")) // Being ready when you change areas gives you a chance to avoid falling all together. thunk(L) - L.make_floating(0) + L.update_floating( L.Check_Dense_Object() ) L.lastarea = newarea play_ambience(L) @@ -260,21 +264,10 @@ var/list/mob/living/forced_ambiance_list = new /area/proc/gravitychange(var/gravitystate = 0, var/area/A) A.has_gravity = gravitystate - if(gravitystate) - for(var/mob/living/carbon/human/M in A) + for(var/mob/M in A) + if(has_gravity) thunk(M) - for(var/mob/M1 in A) - M1.make_floating(0) - else - for(var/mob/M in A) - if(M.Check_Dense_Object() && istype(src,/mob/living/carbon/human/)) - var/mob/living/carbon/human/H = src - if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP)) //magboots + dense_object = no floaty effect - H.make_floating(0) - else - H.make_floating(1) - else - M.make_floating(1) + M.update_floating( M.Check_Dense_Object() ) /area/proc/thunk(mob) if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing. diff --git a/code/game/atoms.dm b/code/game/atoms.dm index c811163330c..69abb073582 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -66,9 +66,6 @@ /atom/proc/meteorhit(obj/meteor as obj) return -/atom/proc/allow_drop() - return 1 - /atom/proc/CheckExit() return 1 diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index deb4426cf56..96fcebfe3b4 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -64,9 +64,6 @@ component_parts += new /obj/item/stack/cable_coil(src) RefreshParts() -/obj/machinery/dna_scannernew/allow_drop() - return 0 - /obj/machinery/dna_scannernew/relaymove(mob/user as mob) if (user.stat) return diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index 29619503774..447225b6ce2 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -193,7 +193,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E src << "This creature's DNA is ruined beyond useability!" return - if(!G.state == GRAB_KILL) + if(G.state != GRAB_KILL) src << "We must have a tighter grip to absorb this creature." return diff --git a/code/game/gamemodes/cult/cultify/obj.dm b/code/game/gamemodes/cult/cultify/obj.dm index 405ea6b29cd..517c6079fd9 100644 --- a/code/game/gamemodes/cult/cultify/obj.dm +++ b/code/game/gamemodes/cult/cultify/obj.dm @@ -136,8 +136,8 @@ // Make it a wood-reinforced wooden table. // There are cult materials available, but it'd make the table non-deconstructable with how holotables work. // Could possibly use a new material var for holographic-ness? - material = name_to_material["wood"] - reinforced = name_to_material["wood"] + material = get_material_by_name("wood") + reinforced = get_material_by_name("wood") update_desc() update_connections(1) update_icon() diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 8ead4b96bad..36eb038e569 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -592,6 +592,7 @@ var/list/sacrificed = list() usr.whisper("[input]") input = sanitize(input) + log_and_message_admins("used a communicate rune to say '[input]'") for(var/datum/mind/H in cult.current_antagonists) if (H.current) H.current << "\red \b [input]" diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index cc6722f8a53..d49247263f9 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -324,7 +324,7 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is //AI laws for(var/mob/living/silicon/ai/M in living_mob_list) - if(M.stat != 2 && M.has_power) + if(M.stat != 2 && M.see_in_dark != 0) var/who2 = pick("ALIENS", "BEARS", "CLOWNS", "XENOS", "PETES", "BOMBS", "FETISHES", "WIZARDS", "SYNDICATE AGENTS", "CENTCOM OFFICERS", "SPACE PIRATES", "TRAITORS", "MONKEYS", "BEES", "CARP", "CRABS", "EELS", "BANDITS", "LIGHTS") var/what2 = pick("BOLTERS", "STAVES", "DICE", "SINGULARITIES", "TOOLBOXES", "NETTLES", "AIRLOCKS", "CLOTHES", "WEAPONS", "MEDKITS", "BOMBS", "CANISTERS", "CHAIRS", "BBQ GRILLS", "ID CARDS", "CAPTAINS") var/what2pref = pick("SOFT", "WARM", "WET", "COLD", "ICY", "SEXY", "UGLY", "CUBAN") @@ -468,4 +468,4 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is world << "Ion Storm Main Done" - */ + */ \ No newline at end of file diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index e8962eb2945..4a89de7ea6f 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -245,12 +245,8 @@ var/global/list/additional_antag_types = list() if(!(antag_templates && antag_templates.len)) return 1 - // Attempt to mark folks down as ready to go. Don't finalize until post setup. var/datum/antagonist/main_antags = antag_templates[1] - var/list/candidates = main_antags.get_candidates() - if(candidates.len >= required_enemies) - for(var/datum/antagonist/antag in antag_templates) - antag.attempt_spawn() + if(main_antags.candidates.len >= required_enemies) return 1 return 0 @@ -264,6 +260,14 @@ var/global/list/additional_antag_types = list() var/datum/event_container/EMajor = event_manager.event_containers[EVENT_LEVEL_MAJOR] EMajor.delay_modifier = event_delay_mod_major +/datum/game_mode/proc/pre_setup() + for(var/datum/antagonist/antag in antag_templates) + antag.build_candidate_list() //compile a list of all eligible candidates + + //antag roles that replace jobs need to be assigned before the job controller hands out jobs. + if(antag.flags & ANTAG_OVERRIDE_JOB) + antag.attempt_spawn() //select antags to be spawned + ///post_setup() /datum/game_mode/proc/post_setup() @@ -277,11 +281,13 @@ var/global/list/additional_antag_types = list() spawn(rand(100,150)) announce_ert_disabled() - if(antag_templates && antag_templates.len) - for(var/datum/antagonist/antag in antag_templates) - antag.finalize_spawn() - if(antag.is_latejoin_template()) - latejoin_templates |= antag + //Assign all antag types for this game mode. Any players spawned as antags earlier should have been removed from the pending list, so no need to worry about those. + for(var/datum/antagonist/antag in antag_templates) + if(!(antag.flags & ANTAG_OVERRIDE_JOB)) + antag.attempt_spawn() //select antags to be spawned + antag.finalize_spawn() //actually spawn antags + if(antag.is_latejoin_template()) + latejoin_templates |= antag if(emergency_shuttle && auto_recall_shuttle) emergency_shuttle.auto_recall = 1 @@ -292,6 +298,10 @@ var/global/list/additional_antag_types = list() feedback_set_details("server_ip","[world.internet_address]:[world.port]") return 1 +/datum/game_mode/proc/fail_setup() + for(var/datum/antagonist/antag in antag_templates) + antag.reset() + /datum/game_mode/proc/announce_ert_disabled() if(!ert_disabled) return diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 7a27f4f7c5f..bfffffc8ff9 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -91,11 +91,14 @@ var/global/datum/controller/gameticker/ticker else src.mode = config.pick_mode(master_mode) + src.mode.pre_setup() + job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly. if(!mode_started && !src.mode.can_start()) world << "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby." current_state = GAME_STATE_PREGAME + mode.fail_setup() mode = null job_master.ResetOccupations() return 0 @@ -110,6 +113,7 @@ var/global/datum/controller/gameticker/ticker else src.mode.announce() + setup_economy() current_state = GAME_STATE_PLAYING create_characters() //Create player characters and transfer them collect_minds() @@ -118,9 +122,6 @@ var/global/datum/controller/gameticker/ticker callHook("roundstart") - //here to initialize the random events nicely at round start - setup_economy() - shuttle_controller.setup_shuttle_docks() spawn(0)//Forking here so we dont have to wait for this to finish diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 7e1ba6d3684..03680c8ff34 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -20,12 +20,3 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' if (skipjack && skipjack.returned_home) return 1 return 0 - -/datum/game_mode/heist/cleanup() - //the skipjack and everything in it have left and aren't coming back, so get rid of them. - var/area/skipjack = locate(/area/shuttle/skipjack/station) - for (var/mob/living/M in skipjack.contents) - //maybe send the player a message that they've gone home/been kidnapped? Someone responsible for vox lore should write that. - qdel(M) - for (var/obj/O in skipjack.contents) - qdel(O) //no hiding in lockers or anything \ No newline at end of file diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 449e5f68ba9..7a9fc51329e 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -50,8 +50,6 @@ /var/const/access_mining = 48 /var/const/access_mining_office = 49 //not in use /var/const/access_mailsorting = 50 -/var/const/access_mint = 51 -/var/const/access_mint_vault = 52 /var/const/access_heads_vault = 53 /var/const/access_mining_station = 54 /var/const/access_xenobiology = 55 @@ -311,10 +309,6 @@ return "Mining Office" if(access_mailsorting) return "Cargo Office" - if(access_mint) - return "Mint" - if(access_mint_vault) - return "Mint Vault" if(access_heads_vault) return "Main Vault" if(access_mining_station) diff --git a/code/game/jobs/job/assistant.dm b/code/game/jobs/job/assistant.dm index 98c7a4dd986..f390303452f 100644 --- a/code/game/jobs/job/assistant.dm +++ b/code/game/jobs/job/assistant.dm @@ -10,7 +10,7 @@ selection_color = "#dddddd" access = list() //See /datum/job/assistant/get_access() minimal_access = list() //See /datum/job/assistant/get_access() - alt_titles = list("Technical Assistant","Medical Intern","Research Assistant","Security Cadet","Visitor") + alt_titles = list("Technical Assistant","Medical Intern","Research Assistant","Visitor") /datum/job/assistant/equip(var/mob/living/carbon/human/H) if(!H) return 0 diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index 7d847533530..26f5c020201 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -97,8 +97,8 @@ spawn_positions = 1 supervisors = "the head of personnel" selection_color = "#dddddd" - access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station) - minimal_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station) + access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station) + minimal_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station) equip(var/mob/living/carbon/human/H) @@ -124,7 +124,7 @@ spawn_positions = 2 supervisors = "the quartermaster and the head of personnel" selection_color = "#dddddd" - access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station) + access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station) minimal_access = list(access_maint_tunnels, access_cargo, access_cargo_bot, access_mailsorting) @@ -149,8 +149,8 @@ spawn_positions = 3 supervisors = "the quartermaster and the head of personnel" selection_color = "#dddddd" - access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station) - minimal_access = list(access_mining, access_mint, access_mining_station, access_mailsorting) + access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station) + minimal_access = list(access_mining, access_mining_station, access_mailsorting) alt_titles = list("Drill Technician","Prospector") equip(var/mob/living/carbon/human/H) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 0617f6421f4..6a7c73dc725 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -177,11 +177,6 @@ return return - - allow_drop() - return 0 - - process() if (stat & (NOPOWER|BROKEN)) return diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 58ebfb38abf..635cc9097f0 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -14,9 +14,6 @@ idle_power_usage = 60 active_power_usage = 10000 //10 kW. It's a big all-body scanner. -/*/obj/machinery/bodyscanner/allow_drop() - return 0*/ - /obj/machinery/bodyscanner/relaymove(mob/user as mob) if (user.stat) return diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index a5106be41ea..57f5f9eeef7 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -69,6 +69,7 @@ var/datum/radio_frequency/radio_connection var/list/TLV = list() + var/list/trace_gas = list("sleeping_agent", "volatile_fuel") //list of other gases that this air alarm is able to detect var/danger_level = 0 var/pressure_dangerlevel = 0 @@ -240,23 +241,24 @@ /obj/machinery/alarm/proc/overall_danger_level(var/datum/gas_mixture/environment) var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume var/environment_pressure = environment.return_pressure() - //var/other_moles = 0.0 - ////for(var/datum/gas/G in environment.trace_gases) - // other_moles+=G.moles + + var/other_moles = 0 + for(var/g in trace_gas) + other_moles += environment.gas[g] //this is only going to be used in a partial pressure calc, so we don't need to worry about group_multiplier here. pressure_dangerlevel = get_danger_level(environment_pressure, TLV["pressure"]) oxygen_dangerlevel = get_danger_level(environment.gas["oxygen"]*partial_pressure, TLV["oxygen"]) co2_dangerlevel = get_danger_level(environment.gas["carbon_dioxide"]*partial_pressure, TLV["carbon dioxide"]) phoron_dangerlevel = get_danger_level(environment.gas["phoron"]*partial_pressure, TLV["phoron"]) temperature_dangerlevel = get_danger_level(environment.temperature, TLV["temperature"]) - //other_dangerlevel = get_danger_level(other_moles*partial_pressure, TLV["other"]) + other_dangerlevel = get_danger_level(other_moles*partial_pressure, TLV["other"]) return max( pressure_dangerlevel, oxygen_dangerlevel, co2_dangerlevel, phoron_dangerlevel, - //other_dangerlevel, + other_dangerlevel, temperature_dangerlevel ) @@ -504,34 +506,13 @@ var/list/environment_data = new data["has_environment"] = total if(total) - var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume - - var/list/current_settings = TLV["pressure"] var/pressure = environment.return_pressure() - var/pressure_danger = get_danger_level(pressure, current_settings) - environment_data[++environment_data.len] = list("name" = "Pressure", "value" = pressure, "unit" = "kPa", "danger_level" = pressure_danger) - data["total_danger"] = pressure_danger - - current_settings = TLV["oxygen"] - var/oxygen_danger = get_danger_level(environment.gas["oxygen"]*partial_pressure, current_settings) - environment_data[++environment_data.len] = list("name" = "Oxygen", "value" = environment.gas["oxygen"] / total * 100, "unit" = "%", "danger_level" = oxygen_danger) - data["total_danger"] = max(oxygen_danger, data["total_danger"]) - - current_settings = TLV["carbon dioxide"] - var/carbon_dioxide_danger = get_danger_level(environment.gas["carbon_dioxide"]*partial_pressure, current_settings) - environment_data[++environment_data.len] = list("name" = "Carbon dioxide", "value" = environment.gas["carbon_dioxide"] / total * 100, "unit" = "%", "danger_level" = carbon_dioxide_danger) - data["total_danger"] = max(carbon_dioxide_danger, data["total_danger"]) - - current_settings = TLV["phoron"] - var/phoron_danger = get_danger_level(environment.gas["phoron"]*partial_pressure, current_settings) - environment_data[++environment_data.len] = list("name" = "Toxins", "value" = environment.gas["phoron"] / total * 100, "unit" = "%", "danger_level" = phoron_danger) - data["total_danger"] = max(phoron_danger, data["total_danger"]) - - current_settings = TLV["temperature"] - var/temperature_danger = get_danger_level(environment.temperature, current_settings) - environment_data[++environment_data.len] = list("name" = "Temperature", "value" = environment.temperature, "unit" = "K ([round(environment.temperature - T0C, 0.1)]C)", "danger_level" = temperature_danger) - data["total_danger"] = max(temperature_danger, data["total_danger"]) - + environment_data[++environment_data.len] = list("name" = "Pressure", "value" = pressure, "unit" = "kPa", "danger_level" = pressure_dangerlevel) + environment_data[++environment_data.len] = list("name" = "Oxygen", "value" = environment.gas["oxygen"] / total * 100, "unit" = "%", "danger_level" = oxygen_dangerlevel) + environment_data[++environment_data.len] = list("name" = "Carbon dioxide", "value" = environment.gas["carbon_dioxide"] / total * 100, "unit" = "%", "danger_level" = co2_dangerlevel) + environment_data[++environment_data.len] = list("name" = "Toxins", "value" = environment.gas["phoron"] / total * 100, "unit" = "%", "danger_level" = phoron_dangerlevel) + environment_data[++environment_data.len] = list("name" = "Temperature", "value" = environment.temperature, "unit" = "K ([round(environment.temperature - T0C, 0.1)]C)", "danger_level" = temperature_dangerlevel) + data["total_danger"] = danger_level data["environment"] = environment_data data["atmos_alarm"] = alarm_area.atmosalm data["fire_alarm"] = alarm_area.fire != null @@ -919,7 +900,7 @@ FIRE ALARM /obj/machinery/firealarm/attack_ai(mob/user as mob) return src.attack_hand(user) -/obj/machinery/firealarm/bullet_act(BLAH) +/obj/machinery/firealarm/bullet_act() return src.alarm() /obj/machinery/firealarm/emp_act(severity) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 83112ea778f..c613124cede 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -290,7 +290,7 @@ /obj/machinery/autolathe/dismantle() for(var/mat in stored_material) - var/material/M = name_to_material[mat] + var/material/M = get_material_by_name(mat) if(!istype(M)) continue var/obj/item/stack/material/S = new M.stack_type(get_turf(src)) diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm index 9f144c23b17..23d00318ea8 100644 --- a/code/game/machinery/bioprinter.dm +++ b/code/game/machinery/bioprinter.dm @@ -66,19 +66,19 @@ user << "You inject the blood sample into the bioprinter." return // Meat for biomass. - else if(!prints_prosthetics && istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) + if(!prints_prosthetics && istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) stored_matter += 50 user.drop_item() user << "\The [src] processes \the [W]. Levels of stored biomass now: [stored_matter]" qdel(W) return // Steel for matter. - else if(prints_prosthetics && istype(W, /obj/item/stack/material/steel)) - var/obj/item/stack/material/steel/M = W - stored_matter += M.amount * 10 + if(prints_prosthetics && istype(W, /obj/item/stack/material) && W.get_material_name() == DEFAULT_WALL_MATERIAL) + var/obj/item/stack/S = W + stored_matter += S.amount * 10 user.drop_item() user << "\The [src] processes \the [W]. Levels of stored matter now: [stored_matter]" qdel(W) return - else - return..() \ No newline at end of file + + return..() \ No newline at end of file diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 2f6166905a1..fd2b11c3b1d 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -59,7 +59,7 @@ ..() wires = new(src) botcard = new(src) - botcard.access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station) + botcard.access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station) cell = new(src) cell.charge = 2000 cell.maxcharge = 2000 diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 53416cd2b35..4dbdabd7fcf 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -88,8 +88,8 @@ var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( loc ) A.amount = 5 - if(istype(P, /obj/item/stack/material/glass/reinforced)) - var/obj/item/stack/material/glass/reinforced/RG = P + if(istype(P, /obj/item/stack/material) && P.get_material_name() == "rglass") + var/obj/item/stack/RG = P if (RG.get_amount() < 2) user << "You need two sheets of glass to put in the glass panel." return @@ -201,6 +201,7 @@ transfer.control_disabled = 0 transfer.aiRadio.disabledAi = 0 transfer.loc = get_turf(src) + transfer.create_eyeobj() transfer.cancel_camera() user << "\blue Transfer successful: \black [transfer.name] ([rand(1000,9999)].exe) downloaded to host terminal. Local copy wiped." transfer << "You have been uploaded to a stationary terminal. Remote device connection restored." diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 7cae6c6d93b..3a6deafa3d1 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -87,8 +87,8 @@ var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( src.loc ) A.amount = 5 - if(istype(P, /obj/item/stack/material/glass)) - var/obj/item/stack/material/glass/G = P + if(istype(P, /obj/item/stack/material) && P.get_material_name() == "glass") + var/obj/item/stack/G = P if (G.get_amount() < 2) user << "You need two sheets of glass to put in the glass panel." return diff --git a/code/game/machinery/computer3/buildandrepair.dm b/code/game/machinery/computer3/buildandrepair.dm index 5e5c8af8568..5ecd89e30e3 100644 --- a/code/game/machinery/computer3/buildandrepair.dm +++ b/code/game/machinery/computer3/buildandrepair.dm @@ -178,13 +178,14 @@ if(istype(P, /obj/item/weapon/crowbar)) // complicated check remove_peripheral() - if(istype(P, /obj/item/stack/material/glass)) - if(P:amount >= 2) + if(istype(P, /obj/item/stack/material) && P.get_material_name() == "glass") + var/obj/item/stack/S = P + if(S.amount >= 2) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, 20)) - if(P) - P:use(2) - user << "\blue You put in the glass panel." + if(S) + S.use(2) + user << "You put in the glass panel." src.state = 4 src.icon_state = "4" if(4) diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 4a85b7e543e..0f1b0a2844f 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -60,11 +60,6 @@ return 1 - -/obj/machinery/atmospherics/unary/cryo_cell/allow_drop() - return 0 - - /obj/machinery/atmospherics/unary/cryo_cell/relaymove(mob/user as mob) if(user.stat) return diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 4f19ab0118b..fcb66fef095 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -79,12 +79,14 @@ for reference: maxhealth = material.integrity health = maxhealth +/obj/structure/barricade/get_material() + return material + /obj/structure/barricade/attackby(obj/item/W as obj, mob/user as mob) - if (istype(W, /obj/item/stack/material)) - var/obj/item/stack/material/D = W - if(D.material.name != material.name) - user << "That is the wrong material needed to repair \the [src]." - return + if (istype(W, /obj/item/stack)) + var/obj/item/stack/D = W + if(D.get_material_name() != material.name) + return //hitting things with the wrong type of stack usually doesn't produce messages, and probably doesn't need to. if (health < maxhealth) if (D.get_amount() < 1) user << "You need one sheet of [material.display_name] to repair \the [src]." diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 1313838cf5d..d604cefff5d 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -48,6 +48,11 @@ return ..() +/obj/machinery/door/airlock/get_material() + if(mineral) + return get_material_by_name(mineral) + return get_material_by_name(DEFAULT_WALL_MATERIAL) + /obj/machinery/door/airlock/command name = "Airlock" icon = 'icons/obj/doors/Doorcom.dmi' diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm index 2c5c00caaae..00101893e94 100644 --- a/code/game/machinery/doors/blast_door.dm +++ b/code/game/machinery/doors/blast_door.dm @@ -96,12 +96,12 @@ else usr << "[src]'s motors resist your effort." return - if(istype(C, /obj/item/stack/material/plasteel)) - var/amt = repair_price() + if(istype(C, /obj/item/stack/material) && C.get_material_name() == "plasteel") + var/amt = Ceiling((maxhealth - health)/150) if(!amt) usr << "\The [src] is already fully repaired." return - var/obj/item/stack/material/plasteel/P = C + var/obj/item/stack/P = C if(P.amount < amt) usr << "You don't have enough sheets to repair this! You need at least [amt] sheets." return @@ -135,16 +135,6 @@ return force_close() -// Proc: repair_price() -// Parameters: None -// Description: Determines amount of sheets needed for full repair. (max)150HP per sheet, (max)10 emitter hits per sheet. -/obj/machinery/door/blast/proc/repair_price() - var/sheets_needed = 0 - var/dam = maxhealth - health - while(dam > 0) - dam -= 150 - sheets_needed++ - return sheets_needed // Proc: repair() // Parameters: None @@ -154,7 +144,7 @@ if(stat & BROKEN) stat &= ~BROKEN - + /obj/machinery/door/blast/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) if(air_group) return 1 return ..() diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 03971f4fbbb..99982675d00 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -203,10 +203,9 @@ /obj/machinery/door/attackby(obj/item/I as obj, mob/user as mob) if(istype(I, /obj/item/device/detective_scanner)) return - if(src.operating > 0 || isrobot(user)) return //borgs can't attack doors open because it conflicts with their AI-like interaction with them. src.add_fingerprint(user) - if(istype(I, /obj/item/stack/material/steel)) + if(istype(I, /obj/item/stack/material) && I.get_material_name() == src.get_material_name()) if(stat & BROKEN) user << "It looks like \the [src] is pretty busted. It's going to need more than just patching up now." return @@ -221,20 +220,20 @@ var/amount_needed = (maxhealth - health) / DOOR_REPAIR_AMOUNT amount_needed = (round(amount_needed) == amount_needed)? amount_needed : round(amount_needed) + 1 //Why does BYOND not have a ceiling proc? - var/obj/item/stack/material/steel/metalstack = I + var/obj/item/stack/stack = I var/transfer if (repairing) - transfer = metalstack.transfer_to(repairing, amount_needed - repairing.amount) + transfer = stack.transfer_to(repairing, amount_needed - repairing.amount) if (!transfer) user << "You must weld or remove \the [repairing] from \the [src] before you can add anything else." else - repairing = metalstack.split(amount_needed) + repairing = stack.split(amount_needed) if (repairing) repairing.loc = src transfer = repairing.amount if (transfer) - user << "You fit [transfer] [metalstack.singular_name]\s to damaged and broken parts on \the [src]." + user << "You fit [transfer] [stack.singular_name]\s to damaged and broken parts on \the [src]." return @@ -274,6 +273,8 @@ take_damage(W.force) return + if(src.operating > 0 || isrobot(user)) return //borgs can't attack doors open because it conflicts with their AI-like interaction with them. + if(src.operating) return if(src.density && (operable() && istype(I, /obj/item/weapon/card/emag))) @@ -336,7 +337,8 @@ /obj/machinery/door/emp_act(severity) if(prob(20/severity) && (istype(src,/obj/machinery/door/airlock) || istype(src,/obj/machinery/door/window)) ) - open() + spawn(0) + open() ..() diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 0c0d23b52a9..a3131c649ba 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -75,6 +75,8 @@ A.all_doors.Remove(src) . = ..() +/obj/machinery/door/firedoor/get_material() + return get_material_by_name(DEFAULT_WALL_MATERIAL) /obj/machinery/door/firedoor/examine(mob/user) . = ..(user, 1) diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm index 23efb8ab4c5..782e9c4cde1 100644 --- a/code/game/machinery/kitchen/microwave.dm +++ b/code/game/machinery/kitchen/microwave.dm @@ -130,7 +130,7 @@ if (!(R.id in acceptable_reagents)) user << "\red Your [O] contains components unsuitable for cookery." return 1 - //G.reagents.trans_to(src,G.amount_per_transfer_from_this) + return else if(istype(O,/obj/item/weapon/grab)) var/obj/item/weapon/grab/G = O user << "\red This is ridiculous. You can not fit \the [G.affecting] in this [src]." diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 313efe3bb2c..62909fc3daf 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -176,7 +176,7 @@ Class Procs: qdel(src) //sets the use_power var and then forces an area power update -/obj/machinery/proc/update_use_power(var/new_use_power, var/force_update = 0) +/obj/machinery/proc/update_use_power(var/new_use_power) use_power = new_use_power /obj/machinery/proc/auto_use_power() diff --git a/code/game/machinery/pipe/pipelayer.dm b/code/game/machinery/pipe/pipelayer.dm index 0f2dc3c8551..ca164d7d0c5 100644 --- a/code/game/machinery/pipe/pipelayer.dm +++ b/code/game/machinery/pipe/pipelayer.dm @@ -50,7 +50,7 @@ user.visible_message("[user] has [!a_dis?"de":""]activated auto-dismantling.", "You [!a_dis?"de":""]activate auto-dismantling.") return - if(istype(W, /obj/item/stack/material/steel)) + if(istype(W, /obj/item/stack/material) && W.get_material_name() == DEFAULT_WALL_MATERIAL) var/result = load_metal(W) if(isnull(result)) @@ -86,7 +86,7 @@ on=0 return -/obj/machinery/pipelayer/proc/load_metal(var/obj/item/stack/material/steel/MM) +/obj/machinery/pipelayer/proc/load_metal(var/obj/item/stack/MM) if(istype(MM) && MM.get_amount()) var/cur_amount = metal var/to_load = max(max_metal - round(cur_amount),0) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 934aeec09c3..fc32db7852d 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -397,15 +397,16 @@ var/list/turret_icons emagged = 1 enabled=0 - sleep(rand(60,600)) - if(!enabled) - enabled=1 + spawn(rand(60,600)) + if(!enabled) + enabled=1 ..() /obj/machinery/porta_turret/ex_act(severity) switch (severity) if (1) + del(src) qdel(src) if (2) if (prob(25)) @@ -624,6 +625,14 @@ var/list/turret_icons // Emagged turrets again use twice as much power due to higher firing rates use_power(reqpower * (2 * (emagged || lethal)) * (2 * emagged)) + //Turrets aim for the center of mass by default. + //If the target is grabbing someone then the turret smartly aims for extremities + var/obj/item/weapon/grab/G = locate() in target + if(G && G.state >= GRAB_NECK) //works because mobs are currently not allowed to upgrade to NECK if they are grabbing two people. + A.def_zone = pick("head", "l_hand", "r_hand", "l_foot", "r_foot", "l_arm", "r_arm", "l_leg", "r_leg") + else + A.def_zone = pick("chest", "groin") + //Shooting Code: A.current = T A.starting = T @@ -696,8 +705,8 @@ var/list/turret_icons return if(1) - if(istype(I, /obj/item/stack/material/steel)) - var/obj/item/stack/material/steel/M = I + if(istype(I, /obj/item/stack/material) && I.get_material_name() == DEFAULT_WALL_MATERIAL) + var/obj/item/stack/M = I if(M.use(2)) user << "You add some metal armor to the interior frame." build_step = 2 @@ -788,8 +797,8 @@ var/list/turret_icons //attack_hand() removes the prox sensor if(6) - if(istype(I, /obj/item/stack/material/steel)) - var/obj/item/stack/material/steel/M = I + if(istype(I, /obj/item/stack/material) && I.get_material_name() == DEFAULT_WALL_MATERIAL) + var/obj/item/stack/M = I if(M.use(2)) user << "You add some metal armor to the exterior frame." build_step = 7 diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index d41ab317d96..c20ca8468a5 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -1,22 +1,25 @@ /obj/machinery/recharge_station name = "cyborg recharging station" + desc = "A heavy duty rapid charging system, designed to quickly recharge cyborg power reserves." icon = 'icons/obj/objects.dmi' icon_state = "borgcharger0" density = 1 anchored = 1 use_power = 1 idle_power_usage = 50 - active_power_usage = 50 var/mob/occupant = null var/obj/item/weapon/cell/cell = null - //var/max_internal_charge = 15000 // Two charged borgs in a row with default cell - //var/current_internal_charge = 15000 // Starts charged, to prevent power surges on round start - var/charging_cap_active = 1000 // Active Cap - When cyborg is inside - var/charging_cap_passive = 250 // Passive Cap - Recharging internal capacitor when no cyborg is inside - var/icon_update_tick = 0 // Used to update icon only once every 10 ticks - var/charge_rate = 250 // How much charge is restored per tick - var/weld_rate = 0 // How much brute damage is repaired per tick - var/wire_rate = 0 // How much burn damage is repaired per tick + var/icon_update_tick = 0 // Used to rebuild the overlay only once every 10 ticks + var/charging = 0 + + var/charging_power // W. Power rating used for charging the cyborg. 120 kW if un-upgraded + var/restore_power_active // W. Power drawn from APC when an occupant is charging. 40 kW if un-upgraded + var/restore_power_passive // W. Power drawn from APC when idle. 7 kW if un-upgraded + var/weld_rate = 0 // How much brute damage is repaired per tick + var/wire_rate = 0 // How much burn damage is repaired per tick + + var/weld_power_use = 2300 // power used per point of brute damage repaired. 2.3 kW ~ about the same power usage of a handheld arc welder + var/wire_power_use = 500 // power used per point of burn damage repaired. /obj/machinery/recharge_station/New() ..() @@ -30,51 +33,76 @@ component_parts += new /obj/item/weapon/cell/high(src) component_parts += new /obj/item/stack/cable_coil(src, 5) - build_icon() + RefreshParts() + update_icon() - RefreshParts() +/obj/machinery/recharge_station/proc/has_cell_power() + return cell && cell.percent() > 0 /obj/machinery/recharge_station/process() if(stat & (BROKEN)) return - - if((stat & (NOPOWER)) && (!cell || cell.percent() <= 0)) // No Power. - return - - var/chargemode = 0 - if(occupant) - process_occupant() - chargemode = 1 - // Power Stuff - if(!cell) // Shouldn't be possible, but sanity check return - if(stat & NOPOWER) - cell.use(50 * CELLRATE) // Internal Circuitry, 50W load. No power - Runs from internal cell - return // No external power = No charging + if((stat & NOPOWER) && !has_cell_power()) // No power and cell is dead. + if(icon_update_tick) + icon_update_tick = 0 //just rebuild the overlay once more only + update_icon() + return - // Calculating amount of power to draw - var/charge_diff = (chargemode ? charging_cap_active : charging_cap_passive) + 50 // 50W for circuitry + //First, draw from the internal power cell to recharge/repair/etc the occupant + if(occupant) + process_occupant() - charge_diff = cell.give(charge_diff) + //Then, if external power is available, recharge the internal cell + var/recharge_amount = 0 + if(!(stat & NOPOWER)) + // Calculating amount of power to draw + recharge_amount = (occupant ? restore_power_active : restore_power_passive) * CELLRATE - if(idle_power_usage != charge_diff) // Force update, but only when our power usage changed this tick. - idle_power_usage = charge_diff - update_use_power(1, 1) + recharge_amount = cell.give(recharge_amount) + use_power(recharge_amount / CELLRATE) if(icon_update_tick >= 10) - update_icon() icon_update_tick = 0 else icon_update_tick++ + if(occupant || recharge_amount) + update_icon() + +//since the recharge station can still be on even with NOPOWER. Instead it draws from the internal cell. +/obj/machinery/recharge_station/auto_use_power() + if(!(stat & NOPOWER)) + return ..() + + if(!has_cell_power()) + return 0 + if(src.use_power == 1) + cell.use(idle_power_usage * CELLRATE) + else if(src.use_power >= 2) + cell.use(active_power_usage * CELLRATE) return 1 +//Processes the occupant, drawing from the internal power cell if needed. +/obj/machinery/recharge_station/proc/process_occupant() + if(istype(occupant, /mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = occupant -/obj/machinery/recharge_station/allow_drop() - return 0 + if(R.module) + R.module.respawn_consumable(R, charging_power * CELLRATE / 250) //consumables are magical, apparently + if(R.cell && !R.cell.fully_charged()) + var/diff = min(R.cell.maxcharge - R.cell.charge, charging_power * CELLRATE) // Capped by charging_power / tick + var/charge_used = cell.use(diff) + R.cell.give(charge_used) + + //Lastly, attempt to repair the cyborg if enabled + if(weld_rate && R.getBruteLoss() && cell.checked_use(weld_power_use * weld_rate * CELLRATE)) + R.adjustBruteLoss(-weld_rate) + if(wire_rate && R.getFireLoss() && cell.checked_use(wire_power_use * wire_rate * CELLRATE)) + R.adjustFireLoss(-wire_rate) /obj/machinery/recharge_station/examine(mob/user) ..(user) @@ -92,9 +120,6 @@ return /obj/machinery/recharge_station/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return if(occupant) occupant.emp_act(severity) go_out() @@ -125,13 +150,20 @@ man_rating += P.rating cell = locate(/obj/item/weapon/cell) in component_parts - charge_rate = 125 * cap_rating - charging_cap_passive = charge_rate + charging_power = 40000 + 40000 * cap_rating + restore_power_active = 10000 + 15000 * cap_rating + restore_power_passive = 5000 + 1000 * cap_rating weld_rate = max(0, man_rating - 3) wire_rate = max(0, man_rating - 5) -/obj/machinery/recharge_station/update_icon() - ..() + desc = initial(desc) + desc += " Uses a dedicated internal power cell to deliver [charging_power]W when in use." + if(weld_rate) + desc += "
It is capable of repairing structural damage." + if(wire_rate) + desc += "
It is capable of repairing burn damage." + +/obj/machinery/recharge_station/proc/build_overlays() overlays.Cut() switch(round(chargepercentage())) if(1 to 20) @@ -147,50 +179,33 @@ if(99 to 110) overlays += image('icons/obj/objects.dmi', "statn_c100") -/obj/machinery/recharge_station/Bumped(var/mob/AM) - move_inside(AM) +/obj/machinery/recharge_station/update_icon() + ..() + if(stat & BROKEN) + icon_state = "borgcharger0" + return -/obj/machinery/recharge_station/proc/build_icon() - if(NOPOWER|BROKEN) - if(occupant) - icon_state = "borgcharger1" + if(occupant) + if((stat & NOPOWER) && !has_cell_power()) + icon_state = "borgcharger2" else - icon_state = "borgcharger0" + icon_state = "borgcharger1" else icon_state = "borgcharger0" -/obj/machinery/recharge_station/proc/process_occupant() - if(occupant) - if(istype(occupant, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = occupant - if(R.module) - R.module.respawn_consumable(R, charge_rate / 250) - if(!R.cell) - return - if(!R.cell.fully_charged()) - var/diff = min(R.cell.maxcharge - R.cell.charge, charge_rate) // Capped at charge_rate charge / tick - if (cell.charge >= diff) - cell.use(diff) - R.cell.give(diff) - if(weld_rate && R.getBruteLoss()) - R.adjustBruteLoss(-1) - if(wire_rate && R.getFireLoss()) - R.adjustFireLoss(-1) - else - update_use_power(1) + if(icon_update_tick == 0) + build_overlays() + +/obj/machinery/recharge_station/Bumped(var/mob/AM) + move_inside(AM) /obj/machinery/recharge_station/proc/go_out() if(!(occupant)) return - //for(var/obj/O in src) - // O.loc = loc - if(occupant.client) - occupant.client.eye = occupant.client.mob - occupant.client.perspective = MOB_PERSPECTIVE occupant.loc = loc + occupant.reset_view() occupant = null - build_icon() - update_use_power(1) + update_icon() return /obj/machinery/recharge_station/verb/move_eject() @@ -202,37 +217,26 @@ add_fingerprint(usr) return -/obj/machinery/recharge_station/verb/move_inside(var/mob/user = usr) +/obj/machinery/recharge_station/verb/move_inside() set category = "Object" set src in oview(1) - if(!user) - return - - if(!(istype(user, /mob/living/silicon/robot))) - user << "Only non-organics may enter the recharger!" - return - var/mob/living/silicon/robot/R = user - - if(R.stat == 2) - //Whoever had it so that a borg with a dead cell can't enter this thing should be shot. --NEO + if(usr.stat == DEAD) return if(occupant) - R << "The cell is already occupied!" + usr << "\The [src] is already occupied!" + return + + var/mob/living/silicon/robot/R = usr + if(!istype(R)) + usr << "Only synthetics may enter the recharger!" return if(!R.cell) - R << "Without a powercell, you can't be recharged." - //Make sure they actually HAVE a cell, now that they can get in while powerless. --NEO + usr << "Without a powercell, you can't be recharged." return - R.stop_pulling() - if(R.client) - R.client.perspective = EYE_PERSPECTIVE - R.client.eye = src - R.loc = src - occupant = R - /*for(var/obj/O in src) - O.loc = loc*/ - add_fingerprint(R) - build_icon() - update_use_power(1) - return + + usr.reset_view(src) + usr.loc = src + occupant = usr + add_fingerprint(usr) + update_icon() diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm index b2461f1d7f7..4c44bcd4eeb 100644 --- a/code/game/machinery/robot_fabricator.dm +++ b/code/game/machinery/robot_fabricator.dm @@ -12,8 +12,8 @@ active_power_usage = 10000 /obj/machinery/robotic_fabricator/attackby(var/obj/item/O as obj, var/mob/user as mob) - if (istype(O, /obj/item/stack/material/steel)) - var/obj/item/stack/material/steel/M = O + if (istype(O, /obj/item/stack/material) && O.get_material_name() == DEFAULT_WALL_MATERIAL) + var/obj/item/stack/M = O if (src.metal_amount < 150000.0) var/count = 0 src.overlays += "fab-load-metal" diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm index fb4a03d21f6..99d713cccba 100644 --- a/code/game/machinery/syndicatebeacon.dm +++ b/code/game/machinery/syndicatebeacon.dm @@ -71,7 +71,7 @@ /obj/machinery/syndicate_beacon/proc/selfdestruct() selfdestructing = 1 - spawn() explosion(src.loc, rand(3,8), rand(1,3), 1, 10) + spawn() explosion(src.loc, 1, rand(1,3), rand(3,8), 10) //////////////////////////////////////// //Singularity beacon diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 35c2ecdc1f5..f91fd2d40c5 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -40,8 +40,8 @@ id = "Hub" network = "tcommsat" autolinkers = list("hub", "relay", "c_relay", "s_relay", "m_relay", "r_relay", "science", "medical", - "supply", "service", "common", "command", "engineering", "security", - "receiverA", "receiverB", "broadcasterA", "broadcasterB") + "supply", "service", "common", "command", "engineering", "security", "unused", + "receiverA", "broadcasterA") /obj/machinery/telecomms/hub/preset_cent id = "CentComm Hub" @@ -52,22 +52,11 @@ //Receivers -//--PRESET LEFT--// - -/obj/machinery/telecomms/receiver/preset_left +/obj/machinery/telecomms/receiver/preset_right id = "Receiver A" network = "tcommsat" autolinkers = list("receiverA") // link to relay - freq_listening = list(SCI_FREQ, MED_FREQ, SUP_FREQ, SRV_FREQ) // science, medical, supply, service - - -//--PRESET RIGHT--// - -/obj/machinery/telecomms/receiver/preset_right - id = "Receiver B" - network = "tcommsat" - autolinkers = list("receiverB") // link to relay - freq_listening = list(COMM_FREQ, ENG_FREQ, SEC_FREQ) //command, engineering, security + freq_listening = list(SCI_FREQ, MED_FREQ, SUP_FREQ, SRV_FREQ, COMM_FREQ, ENG_FREQ, SEC_FREQ) //Common and other radio frequencies for people to freely use New() @@ -95,7 +84,14 @@ id = "Bus 2" network = "tcommsat" freq_listening = list(SUP_FREQ, SRV_FREQ) - autolinkers = list("processor2", "supply", "service") + autolinkers = list("processor2", "supply", "service", "unused") + +/obj/machinery/telecomms/bus/preset_two/New() + for(var/i = 1441, i < 1489, i += 2) + if(i == AI_FREQ || i == PUB_FREQ) + continue + freq_listening |= i + ..() /obj/machinery/telecomms/bus/preset_three id = "Bus 3" @@ -106,14 +102,9 @@ /obj/machinery/telecomms/bus/preset_four id = "Bus 4" network = "tcommsat" - freq_listening = list(ENG_FREQ) + freq_listening = list(ENG_FREQ, AI_FREQ, PUB_FREQ) autolinkers = list("processor4", "engineering", "common") -/obj/machinery/telecomms/bus/preset_four/New() - for(var/i = 1441, i < 1489, i += 2) - freq_listening |= i - ..() - /obj/machinery/telecomms/bus/preset_cent id = "CentComm Bus" network = "tcommsat" @@ -169,7 +160,7 @@ id = "Supply Server" freq_listening = list(SUP_FREQ) autolinkers = list("supply") - + /obj/machinery/telecomms/server/presets/service id = "Service Server" freq_listening = list(SRV_FREQ) @@ -177,13 +168,19 @@ /obj/machinery/telecomms/server/presets/common id = "Common Server" - freq_listening = list() + freq_listening = list(PUB_FREQ, AI_FREQ) // AI Private and Common autolinkers = list("common") - //Common and other radio frequencies for people to freely use - // 1441 to 1489 -/obj/machinery/telecomms/server/presets/common/New() +// "Unused" channels, AKA all others. +/obj/machinery/telecomms/server/presets/unused + id = "Unused Server" + freq_listening = list() + autolinkers = list("unused") + +/obj/machinery/telecomms/server/presets/unused/New() for(var/i = 1441, i < 1489, i += 2) + if(i == AI_FREQ || i == PUB_FREQ) + continue freq_listening |= i ..() @@ -213,18 +210,11 @@ //--PRESET LEFT--// -/obj/machinery/telecomms/broadcaster/preset_left +/obj/machinery/telecomms/broadcaster/preset_right id = "Broadcaster A" network = "tcommsat" autolinkers = list("broadcasterA") -//--PRESET RIGHT--// - -/obj/machinery/telecomms/broadcaster/preset_right - id = "Broadcaster B" - network = "tcommsat" - autolinkers = list("broadcasterB") - /obj/machinery/telecomms/broadcaster/preset_cent id = "CentComm Broadcaster" network = "tcommsat" diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm index 223b503f4f7..9823037f500 100644 --- a/code/game/machinery/turret_control.dm +++ b/code/game/machinery/turret_control.dm @@ -213,9 +213,9 @@ enabled=0 updateTurrets() - sleep(rand(60,600)) - if(!enabled) - enabled=1 - updateTurrets() + spawn(rand(60,600)) + if(!enabled) + enabled=1 + updateTurrets() ..() diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 3581c51e182..87edc01204c 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -266,6 +266,15 @@ else A = new /obj/item/projectile/energy/electrode( loc ) use_power(200) + + //Turrets aim for the center of mass by default. + //If the target is grabbing someone then the turret smartly aims for extremities + var/obj/item/weapon/grab/G = locate() in target + if(G && G.state >= GRAB_NECK) //works because mobs are currently not allowed to upgrade to NECK if they are grabbing two people. + A.def_zone = pick("head", "l_hand", "r_hand", "l_foot", "r_foot", "l_arm", "r_arm", "l_leg", "r_leg") + else + A.def_zone = pick("chest", "groin") + A.current = T A.starting = T A.yo = U.y - T.y diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm index 3fd4fae3e89..71b7de64c02 100644 --- a/code/game/machinery/wishgranter.dm +++ b/code/game/machinery/wishgranter.dm @@ -45,6 +45,7 @@ if (!(XRAY in user.mutations)) user.mutations.Add(XRAY) user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) + user.see_in_dark = 8 user.see_invisible = SEE_INVISIBLE_LEVEL_TWO if (!(COLD_RESISTANCE in user.mutations)) @@ -66,4 +67,4 @@ show_objectives(user.mind) user << "You have a very bad feeling about this." - return + return \ No newline at end of file diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index fb2f6b9657d..695a3be4d2e 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -23,12 +23,6 @@ Destroy() qdel(pr_mech_sleeper) - ..() - - allow_drop() - return 0 - - destroy() for(var/atom/movable/AM in src) AM.forceMove(get_turf(src)) return ..() diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index 073c807be94..31e142db804 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -1085,9 +1085,6 @@ var/door_locked = 1 salvageable = 0 -/obj/item/mecha_parts/mecha_equipment/tool/passenger/allow_drop() - return 0 - /obj/item/mecha_parts/mecha_equipment/tool/passenger/destroy() for(var/atom/movable/AM in src) AM.forceMove(get_turf(src)) diff --git a/code/game/objects/effects/explosion_particles.dm b/code/game/objects/effects/explosion_particles.dm index 90020e50801..e0750ba1c35 100644 --- a/code/game/objects/effects/explosion_particles.dm +++ b/code/game/objects/effects/explosion_particles.dm @@ -9,7 +9,7 @@ /obj/effect/expl_particles/New() ..() spawn (15) - src.loc = null + qdel(src) return /obj/effect/expl_particles/Move() @@ -49,7 +49,7 @@ /obj/effect/explosion/New() ..() spawn (10) - src.loc = null + qdel(src) return /datum/effect/system/explosion diff --git a/code/game/objects/empulse.dm b/code/game/objects/empulse.dm index 05cdbfee1da..c1df6b5454b 100644 --- a/code/game/objects/empulse.dm +++ b/code/game/objects/empulse.dm @@ -1,3 +1,9 @@ +// Uncomment this define to check for possible lengthy processing of emp_act()s. +// If emp_act() takes more than defined deciseconds (1/10 seconds) an admin message and log is created. +// I do not recommend having this uncommented on main server, it probably causes a bit more lag, espicially with larger EMPs. + +// #define EMPDEBUG 10 + proc/empulse(turf/epicenter, heavy_range, light_range, log=0) if(!epicenter) return @@ -24,6 +30,9 @@ proc/empulse(turf/epicenter, heavy_range, light_range, log=0) M << 'sound/effects/EMPulse.ogg' for(var/atom/T in range(light_range, epicenter)) + #ifdef EMPDEBUG + var/time = world.timeofday + #endif var/distance = get_dist(epicenter, T) if(distance < 0) distance = 0 @@ -36,4 +45,8 @@ proc/empulse(turf/epicenter, heavy_range, light_range, log=0) T.emp_act(2) else if(distance <= light_range) T.emp_act(2) + #ifdef EMPDEBUG + if((world.timeofday - time) >= EMPDEBUG) + log_and_message_admins("EMPDEBUG: [T.name] - [T.type] - took [world.timeofday - time]ds to process emp_act()!") + #endif return 1 \ No newline at end of file diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index a483a378b75..8084d7a9909 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -110,6 +110,7 @@ ai.loc = src ai.cancel_camera() + ai.destroy_eyeobj(src) ai.control_disabled = 1 ai.aiRestorePowerRoutine = 0 carded_ai = ai diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index cd930cc5775..d59b7ceaa0a 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -71,8 +71,8 @@ Emag() return - if(istype(W, /obj/item/stack/material/glass)) - var/obj/item/stack/material/glass/G = W + if(istype(W, /obj/item/stack/material) && W.get_material_name() == "glass") + var/obj/item/stack/G = W if(uses >= max_uses) user << "[src.name] is full." return diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 0e5116f5d83..7acedbfde97 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -156,6 +156,9 @@ else channels[chan_name] |= FREQ_LISTENING + if(href_list["nowindow"]) // here for pAIs, maybe others will want it, idk + return + interact(usr) /obj/item/device/radio/proc/autosay(var/message, var/from, var/channel) //BS12 EDIT diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index 563df642efa..2ee5e723eaa 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -125,8 +125,8 @@ /obj/item/robot_parts/robot_suit/attackby(obj/item/W as obj, mob/user as mob) ..() - if(istype(W, /obj/item/stack/material/steel) && !l_arm && !r_arm && !l_leg && !r_leg && !chest && !head) - var/obj/item/stack/material/steel/M = W + if(istype(W, /obj/item/stack/material) && W.get_material_name() == DEFAULT_WALL_MATERIAL && !l_arm && !r_arm && !l_leg && !r_leg && !chest && !head) + var/obj/item/stack/material/M = W if (M.use(1)) var/obj/item/weapon/secbot_assembly/ed209_assembly/B = new /obj/item/weapon/secbot_assembly/ed209_assembly B.loc = get_turf(src) diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 2893b4f3a10..8f24a93c10d 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -146,7 +146,7 @@ return - return -1 // the bullet/projectile goes through the target! Ie, you missed + return PROJECTILE_CONTINUE // the bullet/projectile goes through the target! // Small memory holder entity for transparent bullet holes diff --git a/code/game/objects/items/stacks/sheets/light.dm b/code/game/objects/items/stacks/sheets/light.dm index b32cb54def7..424eab6a034 100644 --- a/code/game/objects/items/stacks/sheets/light.dm +++ b/code/game/objects/items/stacks/sheets/light.dm @@ -22,8 +22,8 @@ user.drop_from_inventory(src) qdel(src) - if(istype(O,/obj/item/stack/material/steel)) - var/obj/item/stack/material/steel/M = O + if(istype(O,/obj/item/stack/material) && O.get_material_name() == DEFAULT_WALL_MATERIAL) + var/obj/item/stack/M = O if (M.use(1)) use(1) new/obj/item/stack/tile/light(get_turf(user)) diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index 8acd6bd09fd..f620fd64e92 100755 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -40,7 +40,7 @@ AI MODULES if (comp.current.stat == 2 || comp.current.control_disabled == 1) usr << "Upload failed. No signal is being detected from the AI." - else if (!comp.current.has_power) + else if (comp.current.see_in_dark == 0) usr << "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power." else src.transmitInstructions(comp.current, usr) diff --git a/code/game/objects/items/weapons/material/material_weapons.dm b/code/game/objects/items/weapons/material/material_weapons.dm index c396f8d4b9b..18181df6b07 100644 --- a/code/game/objects/items/weapons/material/material_weapons.dm +++ b/code/game/objects/items/weapons/material/material_weapons.dm @@ -34,6 +34,9 @@ if(!isnull(matter[material_type])) matter[material_type] *= force_divisor // May require a new var instead. +/obj/item/weapon/material/get_material() + return material + /obj/item/weapon/material/proc/update_force() if(edge || sharp) force = material.get_edge_damage() diff --git a/code/game/objects/items/weapons/material/shards.dm b/code/game/objects/items/weapons/material/shards.dm index fa39ce719e7..2f395f2ed0f 100644 --- a/code/game/objects/items/weapons/material/shards.dm +++ b/code/game/objects/items/weapons/material/shards.dm @@ -87,4 +87,4 @@ ..(loc, "steel") /obj/item/weapon/material/shard/phoron/New(loc) - ..(loc, "phoron glass") + ..(loc, "phglass") diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index d91ecb463c5..0d3d92aa6f7 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -119,10 +119,10 @@ //verbs += /obj/item/weapon/storage/bag/sheetsnatcher/quick_empty can_be_inserted(obj/item/W as obj, stop_messages = 0) - if(!istype(W,/obj/item/stack/material) || istype(W,/obj/item/stack/material/sandstone) || istype(W,/obj/item/stack/material/wood)) + if(!istype(W,/obj/item/stack/material)) if(!stop_messages) usr << "The snatcher does not accept [W]." - return 0 //I don't care, but the existing code rejects them for not being "sheets" *shrug* -Sayu + return 0 var/current = 0 for(var/obj/item/stack/material/S in contents) current += S.amount diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 61786e10db0..22277c33e2a 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -335,7 +335,6 @@ ..() if(isrobot(user)) - user << "\blue You're a robot. No." return //Robots can't interact with storage items. if(!can_be_inserted(W)) diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 5f83f325818..aa2a8734a6b 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -211,8 +211,12 @@ /obj/item/weapon/weldingtool/process() - if(welding && prob(5) && !remove_fuel(1)) - setWelding(0) + if(welding) + if(prob(5)) + remove_fuel(1) + + if(get_fuel() == 0) + setWelding(0) //I'm not sure what this does. I assume it has to do with starting fires... //...but it doesnt check to see if the welder is on or not. diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 3de1075f388..4e3a6298f7e 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -236,20 +236,20 @@ electronics = null else if(istype(W, /obj/item/stack/material) && !glass) - var/obj/item/stack/material/S = W + var/obj/item/stack/S = W + var/material_name = S.get_material_name() if (S) if (S.get_amount() >= 1) - if(istype(S, /obj/item/stack/material/glass/reinforced)) + if(material_name == "rglass") playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.") if(do_after(user, 40) && !glass) if (S.use(1)) user << "You installed reinforced glass windows into the airlock assembly." glass = 1 - else if(istype(S, /obj/item/stack/material) && S.default_type) - var/M = S.default_type + else if(material_name) // Ugly hack, will suffice for now. Need to fix it upstream as well, may rewrite mineral walls. ~Z - if(M in list("mhydrogen","osmium","tritium","platinum","iron")) + if(!(material_name in list("gold", "silver", "diamond", "uranium", "phoron", "sandstone"))) user << "You cannot make an airlock out of that material." return if(S.get_amount() >= 2) @@ -257,8 +257,8 @@ user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.") if(do_after(user, 40) && !glass) if (S.use(2)) - user << "You installed [M] plating into the airlock assembly." - glass = "[M]" + user << "You installed [material_display_name(material_name)] plating into the airlock assembly." + glass = material_name else if(istype(W, /obj/item/weapon/screwdriver) && state == 2 ) playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 38caaa3230b..98947a2dae9 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -25,7 +25,7 @@ /obj/structure/girder/bullet_act(var/obj/item/projectile/Proj) //Girders only provide partial cover. There's a chance that the projectiles will just pass through. (unless you are trying to shoot the girder) if(Proj.original != src && !prob(cover)) - return -1 //pass through + return PROJECTILE_CONTINUE //pass through //Tasers and the like should not damage girders. if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN)) @@ -108,11 +108,11 @@ else if(istype(W, /obj/item/stack/material)) - var/obj/item/stack/material/S = W + var/obj/item/stack/S = W if(S.get_amount() < 2) return ..() - var/material/M = name_to_material[S.default_type] + var/material/M = S.get_material() if(!istype(M)) return ..() @@ -183,7 +183,7 @@ user << "There is not enough material here to reinforce the girder." return - var/material/M = name_to_material[S.default_type] + var/material/M = S.get_material() if(!istype(M) || M.integrity < 50) user << "You cannot reinforce \the [src] with that; it is too soft." return diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 569a4eb3b95..5f5dcaa48ab 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -94,7 +94,7 @@ passthrough = 1 if(passthrough) - . = -1 + . = PROJECTILE_CONTINUE damage = between(0, (damage - Proj.damage)*(Proj.damage_type == BRUTE? 0.4 : 1), 10) //if the bullet passes through then the grille avoids most of the damage src.health -= damage*0.2 diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index 237250e3fdd..36f65251a52 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -83,22 +83,23 @@ /obj/structure/janitorialcart/attack_hand(mob/user) - user.set_machine(src) - var/dat - if(mybag) - dat += "[mybag.name]
" - if(mymop) - dat += "[mymop.name]
" - if(myspray) - dat += "[myspray.name]
" - if(myreplacer) - dat += "[myreplacer.name]
" - if(signs) - dat += "[signs] sign\s
" - var/datum/browser/popup = new(user, "janicart", name, 240, 160) - popup.set_content(dat) - popup.open() + ui_interact(user) + return +/obj/structure/janitorialcart/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/data[0] + data["name"] = capitalize(name) + data["bag"] = mybag ? capitalize(mybag.name) : null + data["mop"] = mymop ? capitalize(mymop.name) : null + data["spray"] = myspray ? capitalize(myspray.name) : null + data["replacer"] = myreplacer ? capitalize(myreplacer.name) : null + data["signs"] = signs ? "[signs] sign\s" : null + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if(!ui) + ui = new(user, src, ui_key, "janitorcart.tmpl", "Janitorial cart", 240, 160) + ui.set_initial_data(data) + ui.open() /obj/structure/janitorialcart/Topic(href, href_list) if(!in_range(src, usr)) @@ -106,36 +107,39 @@ if(!isliving(usr)) return var/mob/living/user = usr - if(href_list["garbage"]) - if(mybag) - user.put_in_hands(mybag) - user << "You take [mybag] from [src]." - mybag = null - if(href_list["mop"]) - if(mymop) - user.put_in_hands(mymop) - user << "You take [mymop] from [src]." - mymop = null - if(href_list["spray"]) - if(myspray) - user.put_in_hands(myspray) - user << "You take [myspray] from [src]." - myspray = null - if(href_list["replacer"]) - if(myreplacer) - user.put_in_hands(myreplacer) - user << "You take [myreplacer] from [src]." - myreplacer = null - if(href_list["sign"]) - if(signs) - var/obj/item/weapon/caution/Sign = locate() in src - if(Sign) - user.put_in_hands(Sign) - user << "You take \a [Sign] from [src]." - signs-- - else - warning("[src] signs ([signs]) didn't match contents") - signs = 0 + + if(href_list["take"]) + switch(href_list["take"]) + if("garbage") + if(mybag) + user.put_in_hands(mybag) + user << "You take [mybag] from [src]." + mybag = null + if("mop") + if(mymop) + user.put_in_hands(mymop) + user << "You take [mymop] from [src]." + mymop = null + if("spray") + if(myspray) + user.put_in_hands(myspray) + user << "You take [myspray] from [src]." + myspray = null + if("replacer") + if(myreplacer) + user.put_in_hands(myreplacer) + user << "You take [myreplacer] from [src]." + myreplacer = null + if("sign") + if(signs) + var/obj/item/weapon/caution/Sign = locate() in src + if(Sign) + user.put_in_hands(Sign) + user << "You take \a [Sign] from [src]." + signs-- + else + warning("[src] signs ([signs]) didn't match contents") + signs = 0 update_icon() updateUsrDialog() diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 26f3608bf0a..b7c980e0d39 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -40,21 +40,21 @@ switch(severity) if(1.0) for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc + A.forceMove(src.loc) ex_act(severity) qdel(src) return if(2.0) if (prob(50)) for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc + A.forceMove(src.loc) ex_act(severity) qdel(src) return if(3.0) if (prob(5)) for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc + A.forceMove(src.loc) ex_act(severity) qdel(src) return @@ -67,7 +67,7 @@ if (src.connected) for(var/atom/movable/A as mob|obj in src.connected.loc) if (!( A.anchored )) - A.loc = src + A.forceMove(src) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) qdel(src.connected) src.connected = null @@ -81,7 +81,7 @@ src.connected.connected = src src.icon_state = "morgue0" for(var/atom/movable/A as mob|obj in src) - A.loc = src.connected.loc + A.forceMove(src.connected.loc) src.connected.icon_state = "morguet" src.connected.set_dir(src.dir) else @@ -117,7 +117,7 @@ src.connected.connected = src src.icon_state = "morgue0" for(var/atom/movable/A as mob|obj in src) - A.loc = src.connected.loc + A.forceMove(src.connected.loc) src.connected.icon_state = "morguet" else qdel(src.connected) @@ -149,7 +149,7 @@ if (src.connected) for(var/atom/movable/A as mob|obj in src.loc) if (!( A.anchored )) - A.loc = src.connected + A.forceMove(src.connected) //Foreach goto(26) src.connected.connected = null src.connected.update() @@ -166,7 +166,7 @@ return if (!ismob(user) || user.stat || user.lying || user.stunned) return - O.loc = src.loc + O.forceMove(src.loc) if (user != O) for(var/mob/B in viewers(user, 3)) if ((B.client && !( B.blinded ))) @@ -210,21 +210,21 @@ switch(severity) if(1.0) for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc + A.forceMove(src.loc) ex_act(severity) qdel(src) return if(2.0) if (prob(50)) for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc + A.forceMove(src.loc) ex_act(severity) qdel(src) return if(3.0) if (prob(5)) for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc + A.forceMove(src.loc) ex_act(severity) qdel(src) return @@ -246,7 +246,7 @@ if ((src.connected) && (src.locked == 0)) for(var/atom/movable/A as mob|obj in src.connected.loc) if (!( A.anchored )) - A.loc = src + A.forceMove(src) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) //src.connected = null qdel(src.connected) @@ -260,7 +260,7 @@ src.connected.connected = src src.icon_state = "crema0" for(var/atom/movable/A as mob|obj in src) - A.loc = src.connected.loc + A.forceMove(src.connected.loc) src.connected.icon_state = "cremat" else //src.connected = null @@ -294,7 +294,7 @@ src.connected.connected = src src.icon_state = "crema0" for(var/atom/movable/A as mob|obj in src) - A.loc = src.connected.loc + A.forceMove(src.connected.loc) src.connected.icon_state = "cremat" else qdel(src.connected) @@ -366,11 +366,17 @@ anchored = 1 throwpass = 1 +/obj/structure/c_tray/Destroy() + if(connected && connected.connected == src) + connected.connected = null + connected = null + return ..() + /obj/structure/c_tray/attack_hand(mob/user as mob) if (src.connected) for(var/atom/movable/A as mob|obj in src.loc) if (!( A.anchored )) - A.loc = src.connected + A.forceMove(src.connected) //Foreach goto(26) src.connected.connected = null src.connected.update() @@ -387,7 +393,7 @@ return if (!ismob(user) || user.stat || user.lying || user.stunned) return - O.loc = src.loc + O.forceMove(src.loc) if (user != O) for(var/mob/B in viewers(user, 3)) if ((B.client && !( B.blinded ))) @@ -406,7 +412,7 @@ /obj/machinery/button/crematorium/attack_hand(mob/user as mob) if(..()) return - if(src.allowed(usr)) + if(src.allowed(user)) for (var/obj/structure/crematorium/C in world) if (C.id == id) if (!C.cremating) diff --git a/code/game/objects/structures/simple_doors.dm b/code/game/objects/structures/simple_doors.dm index b3230095c13..10fa149e8b4 100644 --- a/code/game/objects/structures/simple_doors.dm +++ b/code/game/objects/structures/simple_doors.dm @@ -44,6 +44,9 @@ update_nearby_tiles() ..() +/obj/structure/simple_door/get_material() + return material + /obj/structure/simple_door/Bumped(atom/user) ..() if(!state) diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 1030afd0199..3067b70d361 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -33,6 +33,9 @@ padding_material = get_material_by_name(new_padding_material) update_icon() +/obj/structure/bed/get_material() + return material + // Reuse the cache/code from stools, todo maybe unify. /obj/structure/bed/update_icon() // Prep icon. diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index 253d96174df..044143269ea 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -195,16 +195,12 @@ var/list/mechtoys = list( find_slip = 0 continue - // Sell phoron - if(istype(A, /obj/item/stack/material/phoron)) - var/obj/item/stack/material/phoron/P = A - phoron_count += P.get_amount() - - // Sell platinum - if(istype(A, /obj/item/stack/material/platinum)) - var/obj/item/stack/material/platinum/P = A - plat_count += P.get_amount() - + // Sell phoron and platinum + if(istype(A, /obj/item/stack)) + var/obj/item/stack/P + switch(P.get_material_name()) + if("phoron") phoron_count += P.get_amount() + if("platinum") plat_count += P.get_amount() qdel(MA) if(phoron_count) diff --git a/code/game/turfs/simulated/wall_icon.dm b/code/game/turfs/simulated/wall_icon.dm index fa6ee92855e..aa7db8a0ccb 100644 --- a/code/game/turfs/simulated/wall_icon.dm +++ b/code/game/turfs/simulated/wall_icon.dm @@ -8,7 +8,7 @@ else construction_stage = null if(!material) - material = name_to_material[DEFAULT_WALL_MATERIAL] + material = get_material_by_name(DEFAULT_WALL_MATERIAL) if(material) explosion_resistance = material.explosion_resistance if(reinf_material && reinf_material.explosion_resistance > explosion_resistance) @@ -44,6 +44,7 @@ return overlays.Cut() + damage_overlay = 0 if(!wall_cache["[new_state]-[material.icon_colour]"]) var/image/I = image(icon='icons/turf/wall_masks.dmi',icon_state="[new_state]") @@ -74,7 +75,6 @@ check_relatives(1) /turf/simulated/wall/proc/update_icon() - if(!material) return @@ -86,15 +86,23 @@ else set_wall_state("[material.icon_base]fwall_open") - var/dmg_amt = material.integrity - if(reinf_material) - dmg_amt += reinf_material.integrity - var/overlay = round(damage / dmg_amt * damage_overlays.len) + 1 - if(overlay > damage_overlays.len) - overlay = damage_overlays.len - if(density) + if(damage == 0) + if(damage_overlay != 0) + overlays -= damage_overlays[damage_overlay] + damage_overlay = 0 + else if(density) + var/integrity = material.integrity + if(reinf_material) + integrity += reinf_material.integrity + + var/overlay = round(damage / integrity * damage_overlays.len) + 1 + if(overlay > damage_overlays.len) + overlay = damage_overlays.len + if(damage_overlay && overlay == damage_overlay) //No need to update. return + + if(damage_overlay) overlays -= damage_overlays[damage_overlay] overlays += damage_overlays[overlay] damage_overlay = overlay return @@ -131,4 +139,4 @@ /turf/simulated/wall/proc/can_join_with(var/turf/simulated/wall/W) if(material && W.material && material.icon_base == W.material.icon_base) return 1 - return 0 \ No newline at end of file + return 0 diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 5185c9b81c9..cdcab2eb39f 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -12,8 +12,8 @@ var/list/global/wall_cache = list() heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall var/damage = 0 - var/damage_overlay - var/global/damage_overlays[8] + var/damage_overlay = 0 + var/global/damage_overlays[16] var/active var/can_open = 0 var/material/material @@ -28,7 +28,7 @@ var/list/global/wall_cache = list() materialtype = DEFAULT_WALL_MATERIAL material = get_material_by_name(materialtype) if(!isnull(rmaterialtype)) - reinf_material = name_to_material[rmaterialtype] + reinf_material = get_material_by_name(rmaterialtype) update_material() processing_turfs |= src @@ -38,7 +38,6 @@ var/list/global/wall_cache = list() dismantle_wall(null,null,1) ..() - /turf/simulated/wall/process() // Calling parent will kill processing if(!radiate()) @@ -170,7 +169,7 @@ var/list/global/wall_cache = list() O.loc = src clear_plants() - material = name_to_material["placeholder"] + material = get_material_by_name("placeholder") reinf_material = null check_relatives() diff --git a/code/modules/admin/ToRban.dm b/code/modules/admin/ToRban.dm index efa835b25e0..d127bfe6f41 100644 --- a/code/modules/admin/ToRban.dm +++ b/code/modules/admin/ToRban.dm @@ -23,7 +23,7 @@ /proc/ToRban_update() spawn(0) log_misc("Downloading updated ToR data...") - var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses") + var/http[] = world.Export("https://check.torproject.org/exit-addresses") var/list/rawlist = file2list(http["CONTENT"]) if(rawlist.len) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 452754d7460..c8a23881c3a 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1097,7 +1097,7 @@ proc/admin_notice(var/message, var/rights) else new chosen(usr.loc) - log_admin("[key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])") + log_and_message_admins("spawned [chosen] at ([usr.x],[usr.y],[usr.z])") feedback_add_details("admin_verb","SA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 9655ba5bcec..2036e209b8b 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -83,10 +83,13 @@ var/list/admin_verbs_admin = list( /client/proc/allow_character_respawn, /* Allows a ghost to respawn */ /client/proc/event_manager_panel, /client/proc/empty_ai_core_toggle_latejoin, + /client/proc/empty_ai_core_toggle_latejoin, /client/proc/aooc, /client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */ /client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */ - /client/proc/change_security_level + /client/proc/change_security_level, + /client/proc/view_chemical_reaction_logs, + /client/proc/makePAI ) var/list/admin_verbs_ban = list( /client/proc/unban_panel, diff --git a/code/modules/admin/player_notes.dm b/code/modules/admin/player_notes.dm index c5a54694c81..4a28ece9151 100644 --- a/code/modules/admin/player_notes.dm +++ b/code/modules/admin/player_notes.dm @@ -1,147 +1,147 @@ -//This stuff was originally intended to be integrated into the ban-system I was working on -//but it's safe to say that'll never be finished. So I've merged it into the current player panel. -//enjoy ~Carn -/* -#define NOTESFILE "data/player_notes.sav" //where the player notes are saved - -datum/admins/proc/notes_show(var/ckey) - usr << browse("Player Notes[notes_gethtml(ckey)]","window=player_notes;size=700x400") - - -datum/admins/proc/notes_gethtml(var/ckey) - var/savefile/notesfile = new(NOTESFILE) - if(!notesfile) return "Error: Cannot access [NOTESFILE]" - if(ckey) - . = "Notes for [ckey]: \[+\] \[-\]
" - notesfile.cd = "/[ckey]" - var/index = 1 - while( !notesfile.eof ) - var/note - notesfile >> note - . += "[note] \[-\]
" - index++ - else - . = "All Notes: \[+\] \[-\]
" - notesfile.cd = "/" - for(var/dir in notesfile.dir) - . += "[dir]
" - return - -//handles removing entries from the buffer, or removing the entire directory if no start_index is given -/proc/notes_remove(var/ckey, var/start_index, var/end_index) - var/savefile/notesfile = new(NOTESFILE) - if(!notesfile) return - - if(!ckey) - notesfile.cd = "/" - ckey = ckey(input(usr,"Who would you like to remove notes for?","Enter a ckey",null) as null|anything in notesfile.dir) - if(!ckey) return - - if(start_index) - notesfile.cd = "/[ckey]" - var/list/noteslist = list() - if(!end_index) end_index = start_index - var/index = 0 - while( !notesfile.eof ) - index++ - var/temp - notesfile >> temp - if( (start_index <= index) && (index <= end_index) ) - continue - noteslist += temp - - notesfile.eof = -2 //Move to the start of the buffer and then erase. - - for( var/note in noteslist ) - notesfile << note - else - notesfile.cd = "/" - if(alert(usr,"Are you sure you want to remove all their notes?","Confirmation","No","Yes - Remove all notes") == "Yes - Remove all notes") - notesfile.dir.Remove(ckey) - return - -#undef NOTESFILE -*/ - -//Hijacking this file for BS12 playernotes functions. I like this ^ one systemm alright, but converting sounds too bothersome~ Chinsky. - +//This stuff was originally intended to be integrated into the ban-system I was working on +//but it's safe to say that'll never be finished. So I've merged it into the current player panel. +//enjoy ~Carn +/* +#define NOTESFILE "data/player_notes.sav" //where the player notes are saved + +datum/admins/proc/notes_show(var/ckey) + usr << browse("Player Notes[notes_gethtml(ckey)]","window=player_notes;size=700x400") + + +datum/admins/proc/notes_gethtml(var/ckey) + var/savefile/notesfile = new(NOTESFILE) + if(!notesfile) return "Error: Cannot access [NOTESFILE]" + if(ckey) + . = "Notes for [ckey]: \[+\] \[-\]
" + notesfile.cd = "/[ckey]" + var/index = 1 + while( !notesfile.eof ) + var/note + notesfile >> note + . += "[note] \[-\]
" + index++ + else + . = "All Notes: \[+\] \[-\]
" + notesfile.cd = "/" + for(var/dir in notesfile.dir) + . += "[dir]
" + return + +//handles removing entries from the buffer, or removing the entire directory if no start_index is given +/proc/notes_remove(var/ckey, var/start_index, var/end_index) + var/savefile/notesfile = new(NOTESFILE) + if(!notesfile) return + + if(!ckey) + notesfile.cd = "/" + ckey = ckey(input(usr,"Who would you like to remove notes for?","Enter a ckey",null) as null|anything in notesfile.dir) + if(!ckey) return + + if(start_index) + notesfile.cd = "/[ckey]" + var/list/noteslist = list() + if(!end_index) end_index = start_index + var/index = 0 + while( !notesfile.eof ) + index++ + var/temp + notesfile >> temp + if( (start_index <= index) && (index <= end_index) ) + continue + noteslist += temp + + notesfile.eof = -2 //Move to the start of the buffer and then erase. + + for( var/note in noteslist ) + notesfile << note + else + notesfile.cd = "/" + if(alert(usr,"Are you sure you want to remove all their notes?","Confirmation","No","Yes - Remove all notes") == "Yes - Remove all notes") + notesfile.dir.Remove(ckey) + return + +#undef NOTESFILE +*/ + +//Hijacking this file for BS12 playernotes functions. I like this ^ one systemm alright, but converting sounds too bothersome~ Chinsky. + /proc/notes_add(var/key, var/note, var/mob/user) - if (!key || !note) - return - - //Loading list of notes for this key - var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") - var/list/infos - info >> infos - if(!infos) infos = list() - - //Overly complex timestamp creation - var/modifyer = "th" - switch(time2text(world.timeofday, "DD")) - if("01","21","31") - modifyer = "st" - if("02","22",) - modifyer = "nd" - if("03","23") - modifyer = "rd" - var/day_string = "[time2text(world.timeofday, "DD")][modifyer]" - if(copytext(day_string,1,2) == "0") - day_string = copytext(day_string,2) - var/full_date = time2text(world.timeofday, "DDD, Month DD of YYYY") - var/day_loc = findtext(full_date, time2text(world.timeofday, "DD")) - - var/datum/player_info/P = new + if (!key || !note) + return + + //Loading list of notes for this key + var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") + var/list/infos + info >> infos + if(!infos) infos = list() + + //Overly complex timestamp creation + var/modifyer = "th" + switch(time2text(world.timeofday, "DD")) + if("01","21","31") + modifyer = "st" + if("02","22",) + modifyer = "nd" + if("03","23") + modifyer = "rd" + var/day_string = "[time2text(world.timeofday, "DD")][modifyer]" + if(copytext(day_string,1,2) == "0") + day_string = copytext(day_string,2) + var/full_date = time2text(world.timeofday, "DDD, Month DD of YYYY") + var/day_loc = findtext(full_date, time2text(world.timeofday, "DD")) + + var/datum/player_info/P = new if (user) P.author = user.key P.rank = user.client.holder.rank - else - P.author = "Adminbot" - P.rank = "Friendly Robot" - P.content = note - P.timestamp = "[copytext(full_date,1,day_loc)][day_string][copytext(full_date,day_loc+2)]" - - infos += P - info << infos - + else + P.author = "Adminbot" + P.rank = "Friendly Robot" + P.content = note + P.timestamp = "[copytext(full_date,1,day_loc)][day_string][copytext(full_date,day_loc+2)]" + + infos += P + info << infos + message_admins("\blue [key_name_admin(user)] has edited [key]'s notes.") log_admin("[key_name(user)] has edited [key]'s notes.") - - qdel(info) - - //Updating list of keys with notes on them - var/savefile/note_list = new("data/player_notes.sav") - var/list/note_keys - note_list >> note_keys - if(!note_keys) note_keys = list() - if(!note_keys.Find(key)) note_keys += key - note_list << note_keys - qdel(note_list) - - -/proc/notes_del(var/key, var/index) - var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") - var/list/infos - info >> infos - if(!infos || infos.len < index) return - - var/datum/player_info/item = infos[index] - infos.Remove(item) - info << infos - - message_admins("\blue [key_name_admin(usr)] deleted one of [key]'s notes.") - log_admin("[key_name(usr)] deleted one of [key]'s notes.") - - qdel(info) - -/proc/show_player_info_irc(var/key as text) - var/dat = " Info on [key]%0D%0A" - var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") - var/list/infos - info >> infos - if(!infos) - dat = "No information found on the given key." - else - for(var/datum/player_info/I in infos) - dat += "[I.content]%0D%0Aby [I.author] ([I.rank]) on [I.timestamp]%0D%0A%0D%0A" - - return dat + + qdel(info) + + //Updating list of keys with notes on them + var/savefile/note_list = new("data/player_notes.sav") + var/list/note_keys + note_list >> note_keys + if(!note_keys) note_keys = list() + if(!note_keys.Find(key)) note_keys += key + note_list << note_keys + qdel(note_list) + + +/proc/notes_del(var/key, var/index) + var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") + var/list/infos + info >> infos + if(!infos || infos.len < index) return + + var/datum/player_info/item = infos[index] + infos.Remove(item) + info << infos + + message_admins("\blue [key_name_admin(usr)] deleted one of [key]'s notes.") + log_admin("[key_name(usr)] deleted one of [key]'s notes.") + + qdel(info) + +/proc/show_player_info_irc(var/key as text) + var/dat = " Info on [key]\n" + var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") + var/list/infos + info >> infos + if(!infos) + dat = "No information found on the given key." + else + for(var/datum/player_info/I in infos) + dat += "[I.content]\nby [I.author] ([I.rank]) on [I.timestamp]\n\n" + + return list2params(list(dat)) diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index a25d2de0438..9a9a2b44b7f 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -358,7 +358,7 @@ dat += "NA" - dat += {"[(M.client ? "[M.client]" : "No client")] + dat += {"[M.key ? (M.client ? M.key : "[M.key] (DC)") : "No key"] X PM "} diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 3aeb9ebc133..aa7e8e10c5e 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1651,18 +1651,7 @@ var/mob/M = O M.real_name = obj_name - if (number == 1) - log_admin("[key_name(usr)] created a [english_list(paths)]") - for(var/path in paths) - if(ispath(path, /mob)) - message_admins("[key_name_admin(usr)] created a [english_list(paths)]", 1) - break - else - log_admin("[key_name(usr)] created [number]ea [english_list(paths)]") - for(var/path in paths) - if(ispath(path, /mob)) - message_admins("[key_name_admin(usr)] created [number]ea [english_list(paths)]", 1) - break + log_and_message_admins("created [number] [english_list(paths)]") return else if(href_list["secretsfun"]) diff --git a/code/modules/admin/verbs/buildmode.dm b/code/modules/admin/verbs/buildmode.dm index 4b90283a56d..2131e977ac7 100644 --- a/code/modules/admin/verbs/buildmode.dm +++ b/code/modules/admin/verbs/buildmode.dm @@ -42,6 +42,12 @@ icon = 'icons/misc/buildmode.dmi' var/obj/effect/bmode/buildholder/master = null +/obj/effect/bmode/Destroy() + if(master && master.cl) + master.cl.screen -= src + master = null + return ..() + /obj/effect/bmode/builddir icon_state = "build" screen_loc = "NORTH,WEST" @@ -117,6 +123,19 @@ var/obj/effect/bmode/buildquit/buildquit = null var/atom/movable/throw_atom = null +/obj/effect/bmode/buildholder/Destroy() + qdel(builddir) + builddir = null + qdel(buildhelp) + buildhelp = null + qdel(buildmode) + buildmode = null + qdel(buildquit) + buildquit = null + throw_atom = null + cl = null + return ..() + /obj/effect/bmode/buildmode icon_state = "buildmode1" screen_loc = "NORTH,WEST+2" diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index ef9c5c6376c..2ae2a5d495c 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -64,6 +64,28 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null if(!procname) return + + if(targetselected) + if(!target) + usr << "Your target no longer exists." + return + if(!hascall(target,procname)) + usr << "Error: callproc(): target has no such call [procname]." + return + else + if(copytext(procname, 1, 7) == "/proc/") + // nothing + else if(copytext(procname, 1, 6) == "proc/") + procname = "/[procname]" + else if(copytext(procname, 1, 2) == "/") + procname = "/proc[procname]" + else + procname = "/proc/[procname]" + // Procs have the strange property that text2path will return non-null, but ispath() will return false. + var/path = text2path(procname) + if(!path || ispath(path)) + usr << "Invalid proc [procname]" + return var/argnum = input("Number of arguments","Number:",0) as num|null if(!argnum && (argnum!=0)) return @@ -117,13 +139,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that if(!target) usr << "Error: callproc(): owner of proc no longer exists." return - if(!hascall(target,procname)) - usr << "Error: callproc(): target has no such call [procname]." - return log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc else - //this currently has no hascall protection. wasn't able to get it working. log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index e1ce028c13c..55349977310 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -468,7 +468,7 @@ Traitors and the like can also be revived with the previous role mostly intact. for(var/mob/living/silicon/ai/M in mob_list) if (M.stat == 2) usr << "Upload failed. No signal is being detected from the AI." - else if (!M.has_power) + else if (M.see_in_dark == 0) usr << "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power." else M.add_ion_law(input) diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm index ef217b16f96..37fc52eda80 100644 --- a/code/modules/admin/verbs/striketeam.dm +++ b/code/modules/admin/verbs/striketeam.dm @@ -52,4 +52,4 @@ var/const/commandos_possible = 6 //if more Commandos are needed in the future usr << "Looks like someone beat you to it." return - team.attempt_spawn(1) + team.attempt_random_spawn() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index e0c0af3b0aa..5ca38604712 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -85,7 +85,6 @@ datum/preferences var/religion = "None" //Religious association. //Mob preview - var/mob/living/carbon/human/dummy //the mannequin var/icon/preview_icon = null var/icon/preview_icon_front = null var/icon/preview_icon_side = null @@ -1645,18 +1644,30 @@ datum/preferences character.gen_record = gen_record character.exploit_record = exploit_record - character.change_gender(gender) + character.gender = gender character.age = age character.b_type = b_type - character.change_eye_color(r_eyes,g_eyes,b_eyes) - character.change_hair_color(r_hair,g_hair,b_hair) - character.change_facial_hair_color(r_facial,g_facial,b_facial) - character.change_skin_color(r_skin,g_skin,b_skin) - character.change_skin_tone(s_tone) + character.r_eyes = r_eyes + character.g_eyes = g_eyes + character.b_eyes = b_eyes - character.change_hair(h_style) - character.change_facial_hair(f_style) + character.r_hair = r_hair + character.g_hair = g_hair + character.b_hair = b_hair + + character.r_facial = r_facial + character.g_facial = g_facial + character.b_facial = b_facial + + character.r_skin = r_skin + character.g_skin = g_skin + character.b_skin = b_skin + + character.s_tone = s_tone + + character.h_style = h_style + character.f_style = f_style character.home_system = home_system character.citizenship = citizenship diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 2bfcce82b6d..15577a308b8 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -176,7 +176,7 @@ BLIND // can't see anything slot_flags = SLOT_EYES var/vision_flags = 0 var/darkness_view = 0//Base human is 2 - var/invisa_view = 0 + var/see_invisible = -1 sprite_sheets = list("Vox" = 'icons/mob/species/vox/eyes.dmi') /obj/item/clothing/glasses/update_clothing_icon() @@ -383,23 +383,42 @@ BLIND // can't see anything var/displays_id = 1 var/rolled_down = -1 //0 = unrolled, 1 = rolled, -1 = cannot be toggled sprite_sheets = list("Vox" = 'icons/mob/species/vox/uniform.dmi') - + //convenience var for defining the icon state for the overlay used when the clothing is worn. //Also used by rolling/unrolling. var/worn_state = null /obj/item/clothing/under/New() if(worn_state) - if(!item_state_slots) + if(!item_state_slots) item_state_slots = list() item_state_slots[slot_w_uniform_str] = worn_state else worn_state = icon_state - - //autodetect rollability - if(rolled_down < 0) - if((worn_state + "_d_s") in icon_states('icons/mob/uniform.dmi')) + +/obj/item/clothing/under/proc/update_rolldown_status() + + var/mob/living/carbon/human/H + if(istype(src.loc, /mob/living/carbon/human)) + H = src.loc + + var/icon/under_icon + if(icon_override) + under_icon = icon_override + else if(H && sprite_sheets && sprite_sheets[H.species.name]) + under_icon = sprite_sheets[H.species.name] + else if(item_icons && item_icons[slot_w_uniform_str]) + under_icon = item_icons[slot_w_uniform_str] + else + under_icon = INV_W_UNIFORM_DEF_ICON + + // The _s is because the icon update procs append it. + if(("[worn_state]_d_s") in icon_states(under_icon)) + if(rolled_down != 1) rolled_down = 0 + else + rolled_down = -1 + if(H) update_clothing_icon() /obj/item/clothing/under/update_clothing_icon() if (ismob(src.loc)) @@ -459,10 +478,10 @@ BLIND // can't see anything if (( usr.restrained() ) || ( usr.stat )) return - + if (!usr.unEquip(src)) return - + switch(over_object.name) if("r_hand") usr.put_in_r_hand(src) @@ -542,10 +561,11 @@ BLIND // can't see anything if(!istype(usr, /mob/living)) return if(usr.stat) return - if(rolled_down < 0) + update_rolldown_status() + if(rolled_down == -1) usr << "You cannot roll down [src]!" return - + rolled_down = !rolled_down if(rolled_down) body_parts_covered &= LOWER_TORSO|LEGS|FEET diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 82331722111..0c778dc04a1 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -7,7 +7,6 @@ //slot_flags = SLOT_EYES //var/vision_flags = 0 //var/darkness_view = 0//Base human is 2 - //var/invisa_view = 0 var/prescription = 0 var/toggleable = 0 var/off_state = "degoggles" @@ -75,6 +74,7 @@ origin_tech = "magnets=2" darkness_view = 7 toggleable = 1 + see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING icon_action_button = "action_nvg" off_state = "denight" @@ -224,7 +224,6 @@ toggleable = 1 icon_action_button = "action_thermal" vision_flags = SEE_MOBS - invisa_view = 2 emp_act(severity) if(istype(src.loc, /mob/living/carbon/human)) diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index 60dd6174b15..fb3d94ee89d 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -33,7 +33,7 @@ icon_state = "jensenshades" item_state = "jensenshades" vision_flags = SEE_MOBS - invisa_view = 2 + see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING /obj/item/clothing/glasses/hud/security/process_hud(var/mob/M) process_sec_hud(M, 1) diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 9552a0f17d5..f3eb8a81831 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -46,6 +46,8 @@ /obj/item/clothing/mask/gas/swat/vox name = "\improper alien mask" desc = "Clearly not designed for a human face." + body_parts_covered = 0 //Hack to allow vox to eat while wearing this mask. + species_restricted = list("Vox") /obj/item/clothing/mask/gas/syndicate name = "tactical mask" diff --git a/code/modules/clothing/spacesuits/breaches.dm b/code/modules/clothing/spacesuits/breaches.dm index 6789a50dfcb..7caa4e0bdfb 100644 --- a/code/modules/clothing/spacesuits/breaches.dm +++ b/code/modules/clothing/spacesuits/breaches.dm @@ -178,23 +178,29 @@ var/global/list/breach_burn_descriptors = list( //Handles repairs (and also upgrades). /obj/item/clothing/suit/space/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W,/obj/item/stack/material/plastic) || istype(W,/obj/item/stack/material/steel)) - + if(istype(W,/obj/item/stack/material)) + var/repair_power = 0 + switch(W.get_material_name()) + if(DEFAULT_WALL_MATERIAL) + repair_power = 2 + if("plastic") + repair_power = 1 + + if(!repair_power) + return + if(istype(src.loc,/mob/living)) - user << "\red How do you intend to patch a hardsuit while someone is wearing it?" + user << "How do you intend to patch a hardsuit while someone is wearing it?" return if(!damage || !burn_damage) user << "There is no surface damage on \the [src] to repair." return - var/obj/item/stack/material/P = W - if(P.get_amount() < 3) - P.use(P.get_amount()) - repair_breaches(BURN, ( istype(P,/obj/item/stack/material/plastic) ? P.get_amount() : (P.get_amount()*2) ), user) - else - P.use(3) - repair_breaches(BURN, ( istype(P,/obj/item/stack/material/plastic) ? 3 : 5), user) + var/obj/item/stack/P = W + var/use_amt = min(P.get_amount(), 3) + if(use_amt && P.use(use_amt)) + repair_breaches(BURN, use_amt * repair_power, user) return else if(istype(W, /obj/item/weapon/weldingtool)) diff --git a/code/modules/clothing/spacesuits/rig/modules/modules.dm b/code/modules/clothing/spacesuits/rig/modules/modules.dm index 9db0fbdb737..81af43d9f4a 100644 --- a/code/modules/clothing/spacesuits/rig/modules/modules.dm +++ b/code/modules/clothing/spacesuits/rig/modules/modules.dm @@ -260,7 +260,6 @@ return 0 /stat_rig_module/Click() - ..() if(CanUse()) var/list/href_list = list( "interact_module" = module.holder.installed_modules.Find(module), @@ -269,6 +268,9 @@ AddHref(href_list) module.holder.Topic(usr, href_list) +/stat_rig_module/DblClick() + return Click() + /stat_rig_module/activate/New(var/obj/item/rig_module/module) ..() name = module.activate_string diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index ff29b6bb7a3..785e22d3c7c 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -71,6 +71,7 @@ var/offline_slowdown = 3 // If the suit is deployed and unpowered, it sets slowdown to this. var/vision_restriction var/offline_vision_restriction = 1 // 0 - none, 1 - welder vision, 2 - blind. Maybe move this to helmets. + var/airtight = 1 //If set, will adjust AIRTIGHT and STOPPRESSUREDAMAGE flags on components. Otherwise it should leave them untouched. var/emp_protection = 0 @@ -178,8 +179,9 @@ for(var/obj/item/piece in list(helmet,boots,gloves,chest)) if(!piece) continue piece.icon_state = "[initial(icon_state)]" - piece.flags &= ~STOPPRESSUREDAMAGE - piece.flags &= ~AIRTIGHT + if(airtight) + piece.flags &= ~STOPPRESSUREDAMAGE + piece.flags &= ~AIRTIGHT update_icon(1) /obj/item/weapon/rig/proc/toggle_seals(var/mob/living/carbon/human/M,var/instant) @@ -247,11 +249,6 @@ M << "\The [piece] hisses [!seal_target ? "closed" : "open"]." M.update_inv_head() if(helmet) - if(!seal_target) - if(flags & AIRTIGHT) - helmet.flags |= AIRTIGHT - else - helmet.flags &= ~AIRTIGHT helmet.update_light(wearer) //sealed pieces become airtight, protecting against diseases @@ -273,13 +270,8 @@ if(!piece) continue piece.icon_state = "[initial(icon_state)][!seal_target ? "" : "_sealed"]" canremove = !seal_target - if(helmet) - if(canremove) - if(flags & AIRTIGHT) - helmet.flags |= AIRTIGHT - else - if(flags & AIRTIGHT) - helmet.flags &= ~AIRTIGHT + if(airtight) + update_component_sealed() update_icon(1) return 0 @@ -290,15 +282,18 @@ if(canremove) for(var/obj/item/rig_module/module in installed_modules) module.deactivate() + if(airtight) + update_component_sealed() + update_icon(1) + +/obj/item/weapon/rig/proc/update_component_sealed() for(var/obj/item/piece in list(helmet,boots,gloves,chest)) - if(!piece) continue if(canremove) piece.flags &= ~STOPPRESSUREDAMAGE piece.flags &= ~AIRTIGHT else piece.flags |= STOPPRESSUREDAMAGE piece.flags |= AIRTIGHT - update_icon(1) /obj/item/weapon/rig/process() diff --git a/code/modules/clothing/spacesuits/rig/rig_attackby.dm b/code/modules/clothing/spacesuits/rig/rig_attackby.dm index 2bf00e66c0f..14e5ecc1b95 100644 --- a/code/modules/clothing/spacesuits/rig/rig_attackby.dm +++ b/code/modules/clothing/spacesuits/rig/rig_attackby.dm @@ -7,7 +7,7 @@ return // Pass repair items on to the chestpiece. - if(chest && (istype(W,/obj/item/stack/material/plastic) || istype(W,/obj/item/stack/material/steel) || istype(W, /obj/item/weapon/weldingtool))) + if(chest && (istype(W,/obj/item/stack/material) || istype(W, /obj/item/weapon/weldingtool))) return chest.attackby(W,user) // Lock or unlock the access panel. diff --git a/code/modules/clothing/spacesuits/rig/rig_pieces.dm b/code/modules/clothing/spacesuits/rig/rig_pieces.dm index 294644f3cba..e38fa950ff2 100644 --- a/code/modules/clothing/spacesuits/rig/rig_pieces.dm +++ b/code/modules/clothing/spacesuits/rig/rig_pieces.dm @@ -24,6 +24,7 @@ /obj/item/clothing/shoes/magboots/rig name = "boots" + body_parts_covered = FEET cold_protection = FEET heat_protection = FEET species_restricted = null @@ -69,3 +70,38 @@ return 1 return 0 + +//Rig pieces for non-spacesuit based rigs + +/obj/item/clothing/head/lightrig + name = "mask" + body_parts_covered = HEAD|FACE|EYES + heat_protection = HEAD|FACE|EYES + cold_protection = HEAD|FACE|EYES + flags = THICKMATERIAL|AIRTIGHT + +/obj/item/clothing/suit/lightrig + name = "suit" + allowed = list(/obj/item/device/flashlight) + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + flags_inv = HIDEJUMPSUIT + flags = THICKMATERIAL + +/obj/item/clothing/shoes/lightrig + name = "boots" + body_parts_covered = FEET + cold_protection = FEET + heat_protection = FEET + species_restricted = null + gender = PLURAL + +/obj/item/clothing/gloves/lightrig + name = "gloves" + flags = THICKMATERIAL + body_parts_covered = HANDS + heat_protection = HANDS + cold_protection = HANDS + species_restricted = null + gender = PLURAL diff --git a/code/modules/clothing/spacesuits/rig/suits/light.dm b/code/modules/clothing/spacesuits/rig/suits/light.dm index 8aa50f4ab9a..270e7a37613 100644 --- a/code/modules/clothing/spacesuits/rig/suits/light.dm +++ b/code/modules/clothing/spacesuits/rig/suits/light.dm @@ -33,22 +33,43 @@ /obj/item/weapon/rig/light/hacker name = "cybersuit control module" suit_type = "cyber" - desc = "An advanced powered armour suit with many cyberwarfare enhancements." + desc = "An advanced powered armour suit with many cyberwarfare enhancements. Comes with built-in insulated gloves for safely tampering with electronics." icon_state = "hacker_rig" req_access = list(access_syndicate) - helm_type = /obj/item/clothing/head/helmet/space/rig/mask + airtight = 0 + seal_delay = 5 //not being vaccum-proof has an upside I guess + + helm_type = /obj/item/clothing/head/lightrig/hacker + chest_type = /obj/item/clothing/suit/lightrig/hacker + glove_type = /obj/item/clothing/gloves/lightrig/hacker + boot_type = /obj/item/clothing/shoes/lightrig/hacker initial_modules = list( /obj/item/rig_module/ai_container, /obj/item/rig_module/power_sink, - /obj/item/rig_module/datajack + /obj/item/rig_module/datajack, + /obj/item/rig_module/electrowarfare_suite, + /obj/item/rig_module/voice, + /obj/item/rig_module/vision, ) -/obj/item/clothing/head/helmet/space/rig/mask - name = "mask" - flags = THICKMATERIAL +//The cybersuit is not space-proof. It does however, have good siemens_coefficient values +/obj/item/clothing/head/lightrig/hacker + name = "HUD" + siemens_coefficient = 0.4 + flags = 0 + +/obj/item/clothing/suit/lightrig/hacker + siemens_coefficient = 0.4 + +/obj/item/clothing/shoes/lightrig/hacker + siemens_coefficient = 0.4 + flags = NOSLIP //All the other rigs have magboots anyways, hopefully gives the hacker suit something more going for it. + +/obj/item/clothing/gloves/lightrig/hacker + siemens_coefficient = 0 /obj/item/weapon/rig/light/ninja name = "ominous suit control module" @@ -92,7 +113,7 @@ name = "stealth suit control module" suit_type = "stealth" desc = "A highly advanced and expensive suit designed for covert operations." - icon_state = "ninja_rig" + icon_state = "stealth_rig" req_access = list(access_syndicate) diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index feef7d06b1a..395c9939f57 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -9,30 +9,31 @@ var/slot = "decor" var/obj/item/clothing/under/has_suit = null //the suit the tie may be attached to var/image/inv_overlay = null //overlay used when attached to clothing. - var/image/inv_overlay_mob = null + var/image/mob_overlay = null var/overlay_state = null /obj/item/clothing/accessory/proc/get_inv_overlay() if(!inv_overlay) + if(!mob_overlay) + get_mob_overlay() + var/tmp_icon_state = "[overlay_state? "[overlay_state]" : "[icon_state]"]" if(icon_override) if("[tmp_icon_state]_tie" in icon_states(icon_override)) tmp_icon_state = "[tmp_icon_state]_tie" - inv_overlay = image("icon" = icon_override, "icon_state" = "[tmp_icon_state]") - else - inv_overlay = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[tmp_icon_state]") + inv_overlay = image(icon = mob_overlay.icon, icon_state = tmp_icon_state, dir = SOUTH) return inv_overlay -/obj/item/clothing/accessory/proc/get_inv_mob_overlay() - if(!inv_overlay_mob) +/obj/item/clothing/accessory/proc/get_mob_overlay() + if(!mob_overlay) var/tmp_icon_state = "[overlay_state? "[overlay_state]" : "[icon_state]"]" if(icon_override) if("[tmp_icon_state]_mob" in icon_states(icon_override)) tmp_icon_state = "[tmp_icon_state]_mob" - inv_overlay_mob = image("icon" = icon_override, "icon_state" = "[tmp_icon_state]") + mob_overlay = image("icon" = icon_override, "icon_state" = "[tmp_icon_state]") else - inv_overlay_mob = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[tmp_icon_state]") - return inv_overlay_mob + mob_overlay = image("icon" = INV_ACCESSORIES_DEF_ICON, "icon_state" = "[tmp_icon_state]") + return mob_overlay //when user attached an accessory to S /obj/item/clothing/accessory/proc/on_attached(obj/item/clothing/under/S, mob/user as mob) diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm index c99fe6936d0..729c204f8b3 100644 --- a/code/modules/customitems/item_spawning.dm +++ b/code/modules/customitems/item_spawning.dm @@ -49,18 +49,23 @@ item.icon = CUSTOM_ITEM_OBJ item.icon_state = item_icon return - else + else if(inherit_inhands) apply_inherit_inhands(item) else item.item_state_slots = null item.item_icons = null - + item.icon = CUSTOM_ITEM_OBJ item.icon_state = item_icon item.item_state = null item.icon_override = CUSTOM_ITEM_MOB + var/obj/item/clothing/under/U = item + if(istype(U)) + U.worn_state = U.icon_state + U.update_rolldown_status() + // Kits are dumb so this is going to have to be hardcoded/snowflake. if(istype(item, /obj/item/device/kit)) var/obj/item/device/kit/K = item @@ -81,9 +86,9 @@ /datum/custom_item/proc/apply_inherit_inhands(var/obj/item/item) var/list/new_item_icons = list() var/list/new_item_state_slots = list() - + var/list/available_states = icon_states(CUSTOM_ITEM_MOB) - + //If l_hand or r_hand are not present, preserve them using item_icons/item_state_slots //Then use icon_override to make every other slot use the custom sprites by default. //This has to be done before we touch any of item's vars @@ -93,7 +98,7 @@ if(!("[item_icon]_r" in available_states)) new_item_state_slots[slot_r_hand_str] = get_state(item, slot_r_hand_str, "_r") new_item_icons[slot_r_hand_str] = get_icon(item, slot_r_hand_str, 'icons/mob/items/righthand.dmi') - + item.item_state_slots = new_item_state_slots item.item_icons = new_item_icons diff --git a/code/modules/economy/TradeDestinations.dm b/code/modules/economy/TradeDestinations.dm index 596276006d0..2f376606d7c 100644 --- a/code/modules/economy/TradeDestinations.dm +++ b/code/modules/economy/TradeDestinations.dm @@ -42,7 +42,7 @@ var/list/weighted_mundaneevent_locations = list() return null /datum/trade_destination/icarus - name = "NMV Icarus" + name = "NDV Icarus" description = "Corvette assigned to patrol NSS Exodus local space." distance = 0.1 willing_to_buy = list() diff --git a/code/modules/events/rogue_drones.dm b/code/modules/events/rogue_drones.dm index a50a98982ab..850b03a4f7b 100644 --- a/code/modules/events/rogue_drones.dm +++ b/code/modules/events/rogue_drones.dm @@ -24,11 +24,11 @@ /datum/event/rogue_drone/announce() var/msg if(prob(33)) - msg = "A combat drone wing operating out of the NMV Icarus has failed to return from a sweep of this sector, if any are sighted approach with caution." + msg = "A combat drone wing operating out of the NDV Icarus has failed to return from a sweep of this sector, if any are sighted approach with caution." else if(prob(50)) - msg = "Contact has been lost with a combat drone wing operating out of the NMV Icarus. If any are sighted in the area, approach with caution." + msg = "Contact has been lost with a combat drone wing operating out of the NDV Icarus. If any are sighted in the area, approach with caution." else - msg = "Unidentified hackers have targetted a combat drone wing deployed from the NMV Icarus. If any are sighted in the area, approach with caution." + msg = "Unidentified hackers have targetted a combat drone wing deployed from the NDV Icarus. If any are sighted in the area, approach with caution." command_announcement.Announce(msg, "Rogue drone alert") /datum/event/rogue_drone/end() diff --git a/code/modules/holodeck/HolodeckControl.dm b/code/modules/holodeck/HolodeckControl.dm index 45eaf758f94..0509bf3d86a 100644 --- a/code/modules/holodeck/HolodeckControl.dm +++ b/code/modules/holodeck/HolodeckControl.dm @@ -291,7 +291,7 @@ if(HP.ambience) linkedholodeck.forced_ambience = HP.ambience else - linkedholodeck.forced_ambience = initial(linkedholodeck.ambience) + linkedholodeck.forced_ambience = list() for(var/mob/living/M in mobs_in_area(linkedholodeck)) if(M.mind) diff --git a/code/modules/lighting/light_source.dm b/code/modules/lighting/light_source.dm index 8322e14098f..73a65f064fc 100644 --- a/code/modules/lighting/light_source.dm +++ b/code/modules/lighting/light_source.dm @@ -11,13 +11,16 @@ var/lum_g var/lum_b - var/list/effect_r - var/list/effect_g - var/list/effect_b + var/tmp/old_lum_r + var/tmp/old_lum_g + var/tmp/old_lum_b + + var/list/effect_str var/list/effect_turf var/applied + var/vis_update //Whetever we should smartly recalculate visibility. and then only update tiles that became (in) visible to us var/needs_update var/destroyed var/force_update @@ -38,9 +41,7 @@ parse_light_color() - effect_r = list() - effect_g = list() - effect_b = list() + effect_str = list() effect_turf = list() update() @@ -50,8 +51,8 @@ /datum/light_source/proc/destroy() destroyed = 1 force_update() - if(source_atom) source_atom.light_sources -= src - if(top_atom) top_atom.light_sources -= src + if(source_atom && source_atom.light_sources) source_atom.light_sources -= src + if(top_atom && top_atom.light_sources) top_atom.light_sources -= src /datum/light_source/proc/update(atom/new_top_atom) if(new_top_atom && new_top_atom != top_atom) @@ -61,15 +62,22 @@ if(!top_atom.light_sources) top_atom.light_sources = list() top_atom.light_sources += src - if(!needs_update) + if(!needs_update) //Incase we're already updating either way. lighting_update_lights += src needs_update = 1 /datum/light_source/proc/force_update() force_update = 1 - if(!needs_update) - lighting_update_lights += src + if(!needs_update) //Incase we're already updating either way. needs_update = 1 + lighting_update_lights += src + +/datum/light_source/proc/vis_update() + if(!needs_update) + needs_update = 1 + lighting_update_lights += src + + vis_update = 1 /datum/light_source/proc/check() if(!source_atom || !light_range || !light_power) @@ -96,14 +104,19 @@ light_range = source_atom.light_range . = 1 + if(light_range && light_power && !applied) + . = 1 + + if(. || source_atom.light_color != light_color)//Save the old lumcounts if we need to update, if the colour changed DO IT BEFORE we parse the colour and LOSE the old lumcounts! + old_lum_r = lum_r + old_lum_g = lum_g + old_lum_b = lum_b + if(source_atom.light_color != light_color) light_color = source_atom.light_color parse_light_color() . = 1 - if(light_range && light_power && !applied) - . = 1 - /datum/light_source/proc/parse_light_color() if(light_color) lum_r = GetRedPart(light_color) / 255 @@ -114,54 +127,57 @@ lum_g = 1 lum_b = 1 -/datum/light_source/proc/falloff(atom/movable/lighting_overlay/O) - #if LIGHTING_FALLOFF == 1 // circular - . = (O.x - source_turf.x)**2 + (O.y - source_turf.y)**2 + LIGHTING_HEIGHT - - #if LIGHTING_LAMBERTIAN == 1 - . = CLAMP01((1 - CLAMP01(sqrt(.) / light_range)) * (1 / (sqrt(. + 1)))) - #else - . = 1 - CLAMP01(sqrt(.) / light_range) - #endif - - #elif LIGHTING_FALLOFF == 2 // square - . = abs(O.x - source_turf.x) + abs(O.y - source_turf.y) + LIGHTING_HEIGHT - - #if LIGHTING_LAMBERTIAN == 1 - . = CLAMP01((1 - CLAMP01(. / light_range)) * (1 / (sqrt(.)**2 + ))) - #else - . = 1 - CLAMP01(. / light_range) - #endif +#if LIGHTING_FALLOFF == 1 //circular + #define LUM_DISTANCE(swapvar, O, T) swapvar = (O.x - T.x)**2 + (O.y - T.y)**2 + LIGHTING_HEIGHT + #if LIGHTING_LAMBERTIAN == 1 + #define LUM_ATTENUATION(swapvar) swapvar = CLAMP01((1 - CLAMP01(sqrt(swapvar) / max(1,light_range))) * (1 / sqrt(swapvar + 1))) + #else + #define LUM_ATTENUATION(swapvar) swapvar = 1 - CLAMP01(sqrt(swapvar) / max(1,light_range)) #endif +#elif LIGHTING_FALLOFF == 2 //square + #define LUM_DISTANCE(swapvar, O, T) swapvar = abs(O.x - T.x) + abs(O.y - T.y) + LIGHTING_HEIGHT + #if LIGHTING_LAMBERTIAN == 1 + #define LUM_ATTENUATION(swapvar) swapvar = CLAMP01((1 - CLAMP01(swapvar / max(1,light_range))) * (1 / sqrt(swapvar**2 + 1))) + #else + #define LUM_ATTENUATION(swapvar) swapvar = CLAMP01(swapvar / max(1,light_range)) + #endif +#endif + +#define LUM_FALLOFF(swapvar, O, T) \ + LUM_DISTANCE(swapvar, O, T); \ + LUM_ATTENUATION(swapvar); /datum/light_source/proc/apply_lum() applied = 1 if(istype(source_turf)) - for(var/turf/T in dview(light_range, source_turf, INVISIBILITY_LIGHTING)) + FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING) if(T.lighting_overlay) - var/strength = light_power * falloff(T.lighting_overlay) + var/strength + LUM_FALLOFF(strength, T, source_turf) + strength *= light_power + if(!strength) //Don't add turfs that aren't affected to the affected turfs. continue - effect_r += round(lum_r * strength, LIGHTING_ROUND_VALUE) - effect_g += round(lum_g * strength, LIGHTING_ROUND_VALUE) - effect_b += round(lum_b * strength, LIGHTING_ROUND_VALUE) + strength = round(strength, LIGHTING_ROUND_VALUE) //Screw sinking points. + + effect_str += strength T.lighting_overlay.update_lumcount( - round(lum_r * strength, LIGHTING_ROUND_VALUE), - round(lum_g * strength, LIGHTING_ROUND_VALUE), - round(lum_b * strength, LIGHTING_ROUND_VALUE) + lum_r * strength, + lum_g * strength, + lum_b * strength ) + else - effect_r += 0 - effect_g += 0 - effect_b += 0 + effect_str += 0 if(!T.affecting_lights) T.affecting_lights = list() T.affecting_lights += src effect_turf += T + END_FOR_DVIEW /datum/light_source/proc/remove_lum() applied = 0 @@ -171,11 +187,65 @@ T.affecting_lights -= src if(T.lighting_overlay) - T.lighting_overlay.update_lumcount(-effect_r[i], -effect_g[i], -effect_b[i]) + var/str = effect_str[i] + T.lighting_overlay.update_lumcount(-str * old_lum_r, -str * old_lum_g, -str * old_lum_b) i++ - effect_r.Cut() - effect_g.Cut() - effect_b.Cut() + effect_str.Cut() effect_turf.Cut() + +//Smartly updates the lighting, only removes lum from and adds lum to turfs that actually got changed. +//This is for lights that need to reconsider due to nearby opacity changes. +//Stupid dumb copy pasta because BYOND and speed. +/datum/light_source/proc/smart_vis_update() + var/list/view[0] + FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING) + view += T //Filter out turfs. + END_FOR_DVIEW + //This is the part where we calculate new turfs (if any) + var/list/new_turfs = view - effect_turf //This will result with all the tiles that are added. + for(var/turf/T in new_turfs) + if(T.lighting_overlay) + LUM_FALLOFF(., T, source_turf) + . *= light_power + + if(!.) //Don't add turfs that aren't affected to the affected turfs. + continue + + . = round(., LIGHTING_ROUND_VALUE) + + effect_str += . + + T.lighting_overlay.update_lumcount( + lum_r * ., + lum_g * ., + lum_b * . + ) + + else + effect_str += 0 + + if(!T.affecting_lights) + T.affecting_lights = list() + + T.affecting_lights += src + effect_turf += T + + var/list/old_turfs = effect_turf - view + for(var/turf/T in old_turfs) + //Insert not-so-huge copy paste from remove_lum(). + var/idx = effect_turf.Find(T) //Get the index, luckily Find() is cheap in small lists like this. (with small I mean under a couple thousand len) + if(T.affecting_lights) + T.affecting_lights -= src + + if(T.lighting_overlay) + var/str = effect_str[idx] + T.lighting_overlay.update_lumcount(-str * lum_r, -str * lum_g, -str * lum_b) + + effect_turf.Cut(idx, idx + 1) + effect_str.Cut(idx, idx + 1) + +#undef LUM_FALLOFF +#undef LUM_DISTANCE +#undef LUM_ATTENUATION diff --git a/code/modules/lighting/lighting_atom.dm b/code/modules/lighting/lighting_atom.dm index 92500ecc1d9..6968a4ed63f 100644 --- a/code/modules/lighting/lighting_atom.dm +++ b/code/modules/lighting/lighting_atom.dm @@ -46,21 +46,13 @@ T.reconsider_lights() return ..() -/atom/movable/Move() - var/turf/old_loc = loc +/atom/Entered(atom/movable/obj, atom/prev_loc) . = ..() - if(loc != old_loc) - for(var/datum/light_source/L in light_sources) + if(obj && prev_loc != src) + for(var/datum/light_source/L in obj.light_sources) L.source_atom.update_light() - var/turf/new_loc = loc - if(istype(old_loc) && opacity) - old_loc.reconsider_lights() - - if(istype(new_loc) && opacity) - new_loc.reconsider_lights() - /atom/proc/set_opacity(new_opacity) var/old_opacity = opacity opacity = new_opacity diff --git a/code/modules/lighting/lighting_overlay.dm b/code/modules/lighting/lighting_overlay.dm index a22023d9836..2dd3889e4e9 100644 --- a/code/modules/lighting/lighting_overlay.dm +++ b/code/modules/lighting/lighting_overlay.dm @@ -98,8 +98,5 @@ var/turf/T = loc if(istype(T)) T.lighting_overlay = null - - for(var/datum/light_source/D in T.affecting_lights) //Remove references to us on the light sources affecting us. - D.effect_r -= src - D.effect_g -= src - D.effect_b -= src + + ..() diff --git a/code/modules/lighting/lighting_process.dm b/code/modules/lighting/lighting_process.dm index 1571c6e388b..1c8361dbaf6 100644 --- a/code/modules/lighting/lighting_process.dm +++ b/code/modules/lighting/lighting_process.dm @@ -10,12 +10,17 @@ lighting_update_lights = list() for(var/datum/light_source/L in lighting_update_lights_old) - if(L.needs_update) - if(L.destroyed || L.check() || L.force_update) - L.remove_lum() - if(!L.destroyed) L.apply_lum() - L.force_update = 0 - L.needs_update = 0 + if(L.destroyed || L.check() || L.force_update) + L.remove_lum() + if(!L.destroyed) + L.apply_lum() + + else if(L.vis_update) //We smartly update only tiles that became (in) visible to use. + L.smart_vis_update() + + L.vis_update = 0 + L.force_update = 0 + L.needs_update = 0 scheck() @@ -24,8 +29,7 @@ lighting_update_overlays = list() for(var/atom/movable/lighting_overlay/O in lighting_update_overlays_old) - if(O.needs_update) - O.update_overlay() - O.needs_update = 0 + O.update_overlay() + O.needs_update = 0 scheck() diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index 0a438b047c3..e261931c41c 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -4,7 +4,7 @@ /turf/proc/reconsider_lights() for(var/datum/light_source/L in affecting_lights) - L.force_update() + L.vis_update() /turf/proc/lighting_clear_overlays() if(lighting_overlay) @@ -16,3 +16,13 @@ if(A.lighting_use_dynamic) var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, src) lighting_overlay = O + +/turf/Entered(atom/movable/obj) + . = ..() + if(obj && obj.opacity) + reconsider_lights() + +/turf/Exited(atom/movable/obj) + . = ..() + if(obj && obj.opacity) + reconsider_lights() diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index fb4a0723f99..c2a2b56ab7b 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -39,8 +39,13 @@ update_strings() return 1 +/obj/item/stack/material/get_material() + return material + /obj/item/stack/material/proc/update_strings() // Update from material datum. + singular_name = material.sheet_singular_name + if(amount>1) name = "[material.use_name] [material.sheet_plural_name]" desc = "A stack of [material.use_name] [material.sheet_plural_name]." @@ -187,15 +192,15 @@ /obj/item/stack/material/glass/reinforced name = "reinforced glass" icon_state = "sheet-rglass" - default_type = "reinforced glass" + default_type = "rglass" /obj/item/stack/material/glass/phoronglass name = "phoron glass" singular_name = "phoron glass sheet" icon_state = "sheet-phoronglass" - default_type = "phoron glass" + default_type = "phglass" /obj/item/stack/material/glass/phoronrglass name = "reinforced phoron glass" icon_state = "sheet-phoronrglass" - default_type = "reinforced phoron glass" + default_type = "rphglass" diff --git a/code/modules/materials/material_synth.dm b/code/modules/materials/material_synth.dm index 23b0e7e5462..86e3e16a2dd 100644 --- a/code/modules/materials/material_synth.dm +++ b/code/modules/materials/material_synth.dm @@ -34,5 +34,5 @@ /obj/item/stack/material/cyborg/glass/reinforced icon_state = "sheet-rglass" - default_type = "reinforced glass" + default_type = "rglass" charge_costs = list(500, 1000) \ No newline at end of file diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index f47a2a1394f..dd839dbbb24 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -27,6 +27,17 @@ // Assoc list containing all material datums indexed by name. var/list/name_to_material +//Returns the material the object is made of, if applicable. +//Will we ever need to return more than one value here? Or should we just return the "dominant" material. +/obj/proc/get_material() + return null + +//mostly for convenience +/obj/proc/get_material_name() + var/material/material = get_material() + if(material) + return material.name + // Builds the datum list above. /proc/populate_material_list(force_remake=0) if(name_to_material && !force_remake) return // Already set up! @@ -44,6 +55,12 @@ var/list/name_to_material populate_material_list() return name_to_material[name] +/proc/material_display_name(name) + var/material/material = get_material_by_name(name) + if(material) + return material.display_name + return null + // Material definition and procs follow. /material var/name // Unique name for use in indexing the list. @@ -312,7 +329,7 @@ var/list/name_to_material icon_colour = "#666666" /material/steel/holographic - name = "holographic " + DEFAULT_WALL_MATERIAL + name = "holo" + DEFAULT_WALL_MATERIAL display_name = DEFAULT_WALL_MATERIAL stack_type = null shard_type = SHARD_NONE @@ -422,7 +439,8 @@ var/list/name_to_material return (hardness > 35) //todo /material/glass/reinforced - name = "reinforced glass" + name = "rglass" + display_name = "reinforced glass" stack_type = /obj/item/stack/material/glass/reinforced flags = MATERIAL_BRITTLE icon_colour = "#00E1FF" @@ -440,7 +458,8 @@ var/list/name_to_material rod_product = null /material/glass/phoron - name = "phoron glass" + name = "phglass" + display_name = "phoron glass" stack_type = /obj/item/stack/material/glass/phoronglass flags = MATERIAL_BRITTLE ignition_point = PHORON_MINIMUM_BURN_TEMPERATURE+300 @@ -452,7 +471,8 @@ var/list/name_to_material rod_product = /obj/item/stack/material/glass/phoronrglass /material/glass/phoron/reinforced - name = "reinforced phoron glass" + name = "rphglass" + display_name = "reinforced phoron glass" stack_type = /obj/item/stack/material/glass/phoronrglass stack_origin_tech = "materials=4;phorontech=2" composite_material = list() //todo @@ -473,7 +493,7 @@ var/list/name_to_material stack_origin_tech = "materials=3" /material/plastic/holographic - name = "holographic plastic" + name = "holoplastic" display_name = "plastic" stack_type = null shard_type = SHARD_NONE @@ -551,7 +571,7 @@ var/list/name_to_material sheet_plural_name = "planks" /material/wood/holographic - name = "holographic wood" + name = "holowood" display_name = "wood" stack_type = null shard_type = SHARD_NONE diff --git a/code/modules/mining/alloys.dm b/code/modules/mining/alloys.dm index 9461c1e6b92..dac05badd02 100644 --- a/code/modules/mining/alloys.dm +++ b/code/modules/mining/alloys.dm @@ -12,7 +12,7 @@ metaltag = "plasteel" requires = list( "platinum" = 1, - "coal" = 2, + "carbon" = 2, "hematite" = 2 ) product_mod = 0.3 @@ -21,7 +21,7 @@ /datum/alloy/steel metaltag = DEFAULT_WALL_MATERIAL requires = list( - "coal" = 1, + "carbon" = 1, "hematite" = 1 ) product = /obj/item/stack/material/steel \ No newline at end of file diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 649dee1e1e5..b2d4f0f6a5c 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -112,16 +112,17 @@ var/sheets_per_tick = 10 var/list/ores_processing[0] var/list/ores_stored[0] - var/list/alloy_data[0] + var/static/list/alloy_data var/active = 0 /obj/machinery/mineral/processing_unit/New() - ..() - //TODO: Ore and alloy global storage datum. - for(var/alloytype in typesof(/datum/alloy)-/datum/alloy) - alloy_data += new alloytype() + // initialize static alloy_data list + if(!alloy_data) + alloy_data = list() + for(var/alloytype in typesof(/datum/alloy)-/datum/alloy) + alloy_data += new alloytype() if(!ore_data || !ore_data.len) for(var/oretype in typesof(/ore)-/ore) @@ -209,7 +210,7 @@ var/can_make = Clamp(ores_stored[metal],0,sheets_per_tick-sheets) if(can_make%2>0) can_make-- - var/material/M = name_to_material[O.compresses_to] + var/material/M = get_material_by_name(O.compresses_to) if(!istype(M) || !can_make || ores_stored[metal] < 1) continue @@ -223,7 +224,7 @@ var/can_make = Clamp(ores_stored[metal],0,sheets_per_tick-sheets) - var/material/M = name_to_material[O.smelts_to] + var/material/M = get_material_by_name(O.smelts_to) if(!istype(M) || !can_make || ores_stored[metal] < 1) continue diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm index 96f6fb480cc..99dc1956b12 100644 --- a/code/modules/mining/mint.dm +++ b/code/modules/mining/mint.dm @@ -37,26 +37,26 @@ /obj/machinery/mineral/mint/process() if ( src.input) - var/obj/item/stack/material/O - O = locate(/obj/item/stack/material, input.loc) + var/obj/item/stack/O + O = locate(/obj/item/stack, input.loc) if(O) - if (istype(O,/obj/item/stack/material/gold)) - amt_gold += 100 * O.get_amount() - qdel(O) - if (istype(O,/obj/item/stack/material/silver)) - amt_silver += 100 * O.get_amount() - qdel(O) - if (istype(O,/obj/item/stack/material/diamond)) - amt_diamond += 100 * O.get_amount() - qdel(O) - if (istype(O,/obj/item/stack/material/phoron)) - amt_phoron += 100 * O.get_amount() - qdel(O) - if (istype(O,/obj/item/stack/material/uranium)) - amt_uranium += 100 * O.get_amount() - qdel(O) - if (istype(O,/obj/item/stack/material/steel)) - amt_iron += 100 * O.get_amount() + var/processed = 1 + switch(O.get_material_name()) + if("gold") + amt_gold += 100 * O.get_amount() + if("silver") + amt_silver += 100 * O.get_amount() + if("diamond") + amt_diamond += 100 * O.get_amount() + if("phoron") + amt_phoron += 100 * O.get_amount() + if("uranium") + amt_uranium += 100 * O.get_amount() + if(DEFAULT_WALL_MATERIAL) + amt_iron += 100 * O.get_amount() + else + processed = 0 + if(processed) qdel(O) /obj/machinery/mineral/mint/attack_hand(user as mob) diff --git a/code/modules/mob/animations.dm b/code/modules/mob/animations.dm index ac4224dc436..9bff0fbbe99 100644 --- a/code/modules/mob/animations.dm +++ b/code/modules/mob/animations.dm @@ -77,10 +77,36 @@ note dizziness decrements automatically in the mob's Life() proc. pixel_y = old_y -//handles up-down floaty effect in space +//handles up-down floaty effect in space and zero-gravity /mob/var/is_floating = 0 /mob/var/floatiness = 0 +/mob/proc/update_floating(var/dense_object=0) + + if(anchored||buckled) + make_floating(0) + return + + var/turf/turf = get_turf(src) + if(!istype(turf,/turf/space)) + var/area/A = turf.loc + if(istype(A) && A.has_gravity) + make_floating(0) + return + else if (Check_Shoegrip()) + make_floating(0) + return + else + make_floating(1) + return + + if(dense_object && Check_Shoegrip()) + make_floating(0) + return + + make_floating(1) + return + /mob/proc/make_floating(var/n) floatiness = n diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 49557b9d40e..84a3e6b2c30 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -34,6 +34,7 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images /mob/dead/observer/New(mob/body) sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF see_invisible = SEE_INVISIBLE_OBSERVER + see_in_dark = 100 verbs += /mob/dead/observer/proc/dead_tele stat = DEAD @@ -565,7 +566,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp toggle_visibility(1) else user.visible_message ( \ - "[user] just tried to smash his book into that ghost! It's not very effective.", \ + "[user] just tried to smash \his book into that ghost! It's not very effective.", \ "You get the feeling that the ghost can't become any more visible." \ ) @@ -634,12 +635,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/proc/updateghostsight() if (!seedarkness) see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING - see_in_dark = 100 else see_invisible = SEE_INVISIBLE_OBSERVER if (!ghostvision) see_invisible = SEE_INVISIBLE_LIVING; - see_in_dark = 0 updateghostimages() /proc/updateallghostimages() diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm index 5341bd7616c..07cd8f19ff4 100644 --- a/code/modules/mob/death.dm +++ b/code/modules/mob/death.dm @@ -70,6 +70,7 @@ blind.layer = 0 sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + see_in_dark = 8 see_invisible = SEE_INVISIBLE_LEVEL_TWO drop_r_hand() diff --git a/code/modules/mob/freelook/ai/eye.dm b/code/modules/mob/freelook/ai/eye.dm index c0a42ace48c..93fda30055e 100644 --- a/code/modules/mob/freelook/ai/eye.dm +++ b/code/modules/mob/freelook/ai/eye.dm @@ -27,23 +27,37 @@ // The AI's "eye". Described on the top of the page. /mob/living/silicon/ai - eyeobj = new /mob/eye/aiEye() var/obj/machinery/hologram/holopad/holo = null +/mob/living/silicon/ai/proc/destroy_eyeobj(var/atom/new_eye) + if(!eyeobj) return + if(!new_eye) + new_eye = src + eyeobj.owner = null + qdel(eyeobj) // No AI, no Eye + eyeobj = null + if(client) + client.eye = new_eye + +/mob/living/silicon/ai/proc/create_eyeobj(var/newloc) + if(eyeobj) destroy_eyeobj() + if(!newloc) newloc = src.loc + eyeobj = PoolOrNew(/mob/eye/aiEye, newloc) + eyeobj.owner = src + eyeobj.name = "[src.name] (AI Eye)" // Give it a name + if(client) client.eye = eyeobj + SetName(src.name) + // Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us. /mob/living/silicon/ai/New() ..() - eyeobj.owner = src - eyeobj.name = "[src.name] (AI Eye)" // Give it a name + create_eyeobj() spawn(5) if(eyeobj) eyeobj.loc = src.loc /mob/living/silicon/ai/Destroy() - if(eyeobj) - eyeobj.owner = null - qdel(eyeobj) // No AI, no Eye - eyeobj = null + destroy_eyeobj() ..() /atom/proc/move_camera_by_click() @@ -53,23 +67,18 @@ AI.eyeobj.setLoc(src) // Return to the Core. - /mob/living/silicon/ai/proc/core() set category = "AI Commands" set name = "AI Core" view_core() - /mob/living/silicon/ai/proc/view_core() camera = null unset_machine() if(!src.eyeobj) - src << "ERROR: Eyeobj not found. Creating new eye..." - src.eyeobj = new(src.loc) - src.eyeobj.owner = src - src.SetName(src.name) + return if(client && client.eye) client.eye = src diff --git a/code/modules/mob/freelook/eye.dm b/code/modules/mob/freelook/eye.dm index e77084553de..fb2b04a4348 100644 --- a/code/modules/mob/freelook/eye.dm +++ b/code/modules/mob/freelook/eye.dm @@ -15,6 +15,7 @@ var/acceleration = 1 var/owner_follows_eye = 0 + see_in_dark = 7 status_flags = GODMODE invisibility = INVISIBILITY_EYE diff --git a/code/modules/mob/language/generic.dm b/code/modules/mob/language/generic.dm index d93edf3ac2d..17a145ae021 100644 --- a/code/modules/mob/language/generic.dm +++ b/code/modules/mob/language/generic.dm @@ -25,7 +25,7 @@ speech_verb = "says" whisper_verb = "whispers" key = "0" - flags = RESTRICTED + flags = RESTRICTED | COMMON_VERBS syllables = list("blah","blah","blah","bleh","meh","neh","nah","wah") //TODO flag certain languages to use the mob-type specific say_quote and then get rid of these. diff --git a/code/modules/mob/living/blob/blob.dm b/code/modules/mob/living/blob/blob.dm index 959e6ed379b..8bbf517e60e 100644 --- a/code/modules/mob/living/blob/blob.dm +++ b/code/modules/mob/living/blob/blob.dm @@ -4,6 +4,7 @@ icon = 'icons/mob/blob.dmi' icon_state = "blob_spore_temp" pass_flags = PASSBLOB + see_in_dark = 8 see_invisible = SEE_INVISIBLE_LEVEL_TWO var/ghost_name = "Unknown" var/creating_blob = 0 diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm index 36110c600cb..a2d60210982 100644 --- a/code/modules/mob/living/bot/bot.dm +++ b/code/modules/mob/living/bot/bot.dm @@ -16,6 +16,7 @@ var/obj/access_scanner = null var/list/req_access = list() + var/list/req_one_access = list() /mob/living/bot/New() ..() @@ -26,14 +27,17 @@ access_scanner = new /obj(src) access_scanner.req_access = req_access.Copy() + access_scanner.req_one_access = req_one_access.Copy() /mob/living/bot/Life() ..() + if(health <= 0) + death() + return weakened = 0 stunned = 0 paralysis = 0 - if(health <= 0) - death() + update_canmove() /mob/living/bot/updatehealth() if(status_flags & GODMODE) diff --git a/code/modules/mob/living/bot/floorbot.dm b/code/modules/mob/living/bot/floorbot.dm index 80d6d69df8a..5b64540f70b 100644 --- a/code/modules/mob/living/bot/floorbot.dm +++ b/code/modules/mob/living/bot/floorbot.dm @@ -249,15 +249,16 @@ target = null repairing = 0 update_icons() - else if(istype(A, /obj/item/stack/material/steel) && amount + 3 < maxAmount) - var/obj/item/stack/material/steel/M = A - visible_message("[src] begins to make tiles.") - repairing = 1 - update_icons() - if(do_after(50)) - if(M) - M.use(1) - addTiles(4) + else if(istype(A, /obj/item/stack/material) && amount + 4 <= maxAmount) + var/obj/item/stack/material/M = A + if(M.get_material_name() == DEFAULT_WALL_MATERIAL) + visible_message("[src] begins to make tiles.") + repairing = 1 + update_icons() + if(do_after(50)) + if(M) + M.use(1) + addTiles(4) /mob/living/bot/floorbot/explode() turn_off() diff --git a/code/modules/mob/living/bot/secbot.dm b/code/modules/mob/living/bot/secbot.dm index a0a7a69450a..ee4a35e15b0 100644 --- a/code/modules/mob/living/bot/secbot.dm +++ b/code/modules/mob/living/bot/secbot.dm @@ -4,7 +4,7 @@ icon_state = "secbot0" maxHealth = 50 health = 50 - req_access = list(access_security, access_forensics_lockers) + req_one_access = list(access_security, access_forensics_lockers) botcard_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court) var/mob/target diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index 672e4485310..6e206ff10ee 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -120,11 +120,13 @@ sight |= SEE_TURFS sight |= SEE_MOBS sight |= SEE_OBJS + see_in_dark = 8 see_invisible = SEE_INVISIBLE_LEVEL_TWO else if (stat != 2) sight &= ~SEE_TURFS sight &= ~SEE_MOBS sight &= ~SEE_OBJS + see_in_dark = 2 see_invisible = SEE_INVISIBLE_LIVING if (healths) diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 486916821bc..31c85d770b7 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -23,6 +23,7 @@ /obj/item/organ/brain/New() ..() + health = config.default_brain_health spawn(5) if(brainmob && brainmob.client) brainmob.client.screen.len = null //clear the hud diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm index 868dd79a0c3..dee4fe60a6c 100644 --- a/code/modules/mob/living/carbon/brain/life.dm +++ b/code/modules/mob/living/carbon/brain/life.dm @@ -204,11 +204,13 @@ sight |= SEE_TURFS sight |= SEE_MOBS sight |= SEE_OBJS + see_in_dark = 8 see_invisible = SEE_INVISIBLE_LEVEL_TWO else if (stat != 2) sight &= ~SEE_TURFS sight &= ~SEE_MOBS sight &= ~SEE_OBJS + see_in_dark = 2 see_invisible = SEE_INVISIBLE_LIVING if (healths) @@ -271,4 +273,4 @@ emp_damage += rand(10,20) if(3) emp_damage += rand(0,10) - ..()*/ + ..()*/ \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 52ba116d43b..08998b225c0 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -183,10 +183,6 @@ return valid_facial_hairstyles -/proc/q() - var/mob/living/carbon/human/H = usr - H.change_appearance(APPEARANCE_ALL) - /mob/living/carbon/human/proc/force_update_limbs() for(var/obj/item/organ/external/O in organs) O.sync_colour_to_human(src) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index a1bb3244890..e3c92f708d1 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1361,3 +1361,8 @@ ..() if(update_hud) handle_regular_hud_updates() + +/mob/living/carbon/human/Check_Shoegrip() + if(istype(shoes, /obj/item/clothing/shoes/magboots) && (shoes.flags & NOSLIP)) //magboots + dense_object = no floating + return 1 + return 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 29832ae1ecd..0de5729ec99 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -10,9 +10,11 @@ emp_act /mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone) - var/obj/item/organ/external/organ = get_organ(check_zone(def_zone)) - if(!organ) - return + def_zone = check_zone(def_zone) + if(!has_organ(def_zone)) + return PROJECTILE_FORCE_MISS //if they don't have the organ in question then the projectile just passes by. + + var/obj/item/organ/external/organ = get_organ() //Shields if(check_shields(P.damage, "the [P.name]")) @@ -37,7 +39,7 @@ emp_act // redirect the projectile P.redirect(new_x, new_y, curloc, src) - return -1 // complete projectile permutation + return PROJECTILE_CONTINUE // complete projectile permutation //Shrapnel if(P.can_embed()) diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 2fb446e1acc..c3b115e4f92 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -41,7 +41,7 @@ This saves us from having to call add_fingerprint() any time something is put in /mob/living/carbon/human/proc/has_organ(name) var/obj/item/organ/external/O = organs_by_name[name] - return (O && !(O.status & ORGAN_DESTROYED) ) + return (O && !(O.status & ORGAN_DESTROYED) && !O.is_stump()) /mob/living/carbon/human/proc/has_organ_for_slot(slot) switch(slot) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index acbafdd268f..18312abf924 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1205,7 +1205,8 @@ damageoverlay.overlays += I if( stat == DEAD ) - sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) + sight = SEE_TURFS|SEE_MOBS|SEE_OBJS|SEE_SELF + see_in_dark = 8 if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO if(healths) healths.icon_state = "health7" //DEAD healthmeter if(client) @@ -1227,36 +1228,33 @@ */ else - sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS) + sight = species.vision_flags + see_in_dark = species.darksight + see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING if(XRAY in mutations) sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + see_in_dark = 8 if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO - if(seer==1) + if(seer) var/obj/effect/rune/R = locate() in loc if(R && R.word1 == cultwords["see"] && R.word2 == cultwords["hell"] && R.word3 == cultwords["join"]) see_invisible = SEE_INVISIBLE_CULT else - see_invisible = SEE_INVISIBLE_LIVING seer = 0 - var/tmp/glasses_processed = 0 + if(!seer) + see_invisible = SEE_INVISIBLE_LIVING + + var/equipped_glasses = glasses var/obj/item/weapon/rig/rig = back if(istype(rig) && rig.visor) if(!rig.helmet || (head && rig.helmet == head)) if(rig.visor && rig.visor.vision && rig.visor.active && rig.visor.vision.glasses) - glasses_processed = 1 - process_glasses(rig.visor.vision.glasses) - - if(glasses && !glasses_processed) - glasses_processed = 1 - process_glasses(glasses) - - if(!glasses_processed && (species.vision_flags > 0)) - sight |= species.vision_flags - if(!seer && !glasses_processed) - see_invisible = SEE_INVISIBLE_LIVING + equipped_glasses = rig.visor.vision.glasses + if(equipped_glasses) + process_glasses(equipped_glasses) if(healths) if (analgesic > 100) @@ -1379,7 +1377,7 @@ if(viewflags < 0) reset_view(null, 0) else if(viewflags) - sight |= viewflags + sight = viewflags //when viewing from a machine, use only the sight flags that the machine provides else if(eyeobj) if(eyeobj.owner != src) @@ -1405,8 +1403,8 @@ sight |= G.vision_flags if(!druggy && !seer) see_invisible = SEE_INVISIBLE_MINIMUM - if(istype(G,/obj/item/clothing/glasses/night) && !seer) - see_invisible = SEE_INVISIBLE_MINIMUM + if(G.see_invisible >= 0) + see_invisible = G.see_invisible /* HUD shit goes here, as long as it doesn't modify sight flags */ // The purpose of this is to stop xray and w/e from preventing you from using huds -- Love, Doohl var/obj/item/clothing/glasses/hud/O = G diff --git a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm index cf2295a98c5..dd614bb55ba 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm @@ -8,6 +8,7 @@ language = "Sol Common" //todo? unarmed_types = list(/datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/sharp) light_dam = 2 + darksight = 8 has_organ = list() siemens_coefficient = 0 @@ -22,4 +23,4 @@ /datum/species/shadow/handle_death(var/mob/living/carbon/human/H) spawn(1) new /obj/effect/decal/cleanable/ash(H.loc) - qdel(H) + qdel(H) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 3f4432a817f..4b1b5bf2940 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -46,7 +46,7 @@ var/list/unarmed_attacks = null // For empty hand harm-intent attack var/brute_mod = 1 // Physical damage multiplier. var/burn_mod = 1 // Burn damage multiplier. - var/vision_flags = 0 // Same flags as glasses. + var/vision_flags = SEE_SELF // Same flags as glasses. // Death vars. var/meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/human @@ -99,6 +99,7 @@ var/list/inherent_verbs // Species-specific verbs. var/has_fine_manipulation = 1 // Can use small items. var/siemens_coefficient = 1 // The lower, the thicker the skin and better the insulation. + var/darksight = 2 // Native darksight distance. var/flags = 0 // Various specific features. var/slowdown = 0 // Passive movement speed malus (or boost, if negative) var/primitive_form // Lesser form, if any (ie. monkey for humans) diff --git a/code/modules/mob/living/carbon/human/species/station/slime.dm b/code/modules/mob/living/carbon/human/species/station/slime.dm index b34aaa5b8ee..6d5e918a957 100644 --- a/code/modules/mob/living/carbon/human/species/station/slime.dm +++ b/code/modules/mob/living/carbon/human/species/station/slime.dm @@ -10,6 +10,7 @@ unarmed_types = list(/datum/unarmed_attack/slime_glomp) flags = IS_RESTRICTED | NO_BLOOD | NO_SCAN | NO_SLIP | NO_BREATHE siemens_coefficient = 3 + darksight = 3 blood_color = "#05FF9B" flesh_color = "#05FFFB" diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 44536478a72..a6b39ba38b3 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -22,6 +22,7 @@ tail_animation = 'icons/mob/species/unathi/tail.dmi' unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp) primitive_form = "Stok" + darksight = 3 gluttonous = 1 blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \ @@ -72,6 +73,7 @@ tail = "tajtail" tail_animation = 'icons/mob/species/tajaran/tail.dmi' unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp) + darksight = 8 slowdown = -1 brute_mod = 1.2 diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm index ee24e3f6b7f..b48593796f4 100644 --- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm +++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm @@ -42,7 +42,7 @@ breath_type = null poison_type = null - vision_flags = SEE_MOBS + vision_flags = SEE_SELF|SEE_MOBS has_organ = list( "heart" = /obj/item/organ/heart, diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index dd118b4947e..a88bb65c24b 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -497,7 +497,7 @@ var/global/list/damage_icon_parts = list() var/obj/item/clothing/under/under = w_uniform if(under.accessories.len) for(var/obj/item/clothing/accessory/A in under.accessories) - standing.overlays |= A.get_inv_mob_overlay() + standing.overlays |= A.get_mob_overlay() overlays_standing[UNIFORM_LAYER] = standing else diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index 0b19dd2b5f3..c2e41118b5a 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -14,6 +14,7 @@ update_icon = 0 nutrition = 700 + see_in_dark = 8 update_slimes = 0 // canstun and canweaken don't affect slimes because they ignore stun and weakened variables @@ -410,4 +411,4 @@ /mob/living/carbon/slime/cannot_use_vents() if(Victim) return "You cannot ventcrawl while feeding." - ..() + ..() \ No newline at end of file diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 8919ab0952a..b1c64b91095 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -128,6 +128,7 @@ proc/get_radio_key_from_channel(var/channel) return verb /mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="") + if(client) if(client.prefs.muted & MUTE_IC) src << "\red You cannot speak in IC (Muted)." @@ -165,7 +166,6 @@ proc/get_radio_key_from_channel(var/channel) else speaking = get_default_language() - var/ending = copytext(message, length(message)) if (speaking) // This is broadcast to all mobs with the language, // irrespective of distance or anything else. @@ -173,9 +173,12 @@ proc/get_radio_key_from_channel(var/channel) speaking.broadcast(src,trim(message)) return //If we've gotten this far, keep going! - verb = speaking.get_spoken_verb(ending) + if(speaking.flags & COMMON_VERBS) + verb = say_quote(message) + else + verb = speaking.get_spoken_verb(copytext(message, length(message))) else - verb = get_speech_ending(verb, ending) + verb = say_quote(message) message = trim_left(message) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index d17a76db2f7..888622ff38e 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -49,7 +49,6 @@ var/list/ai_verbs_default = list( var/list/network = list("Exodus") var/obj/machinery/camera/camera = null var/list/connected_robots = list() - var/has_power = 0 var/aiRestorePowerRoutine = 0 var/viewalerts = 0 var/icon/holo_icon//Default is assigned when AI is created. @@ -279,7 +278,7 @@ var/list/ai_verbs_default = list( if(Entry[1] == src.ckey && Entry[2] == src.real_name) custom_sprite = 1 //They're in the list? Custom sprite time - icon = 'icons/mob/custom-synthetic.dmi' + icon = CUSTOM_ITEM_ROBOT //if(icon_state == initial(icon_state)) var/icontype = "" @@ -406,8 +405,7 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/check_eye(var/mob/user as mob) if (!camera) - return null - user.reset_view(camera) + return -1 return 0 /mob/living/silicon/ai/restrained() diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 19da6665bfa..3cdb3c802cf 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -38,18 +38,19 @@ src << "APU GENERATOR FAILURE! (System Damaged)" stop_apu(1) - has_power = 1 + var/blind = 0 var/area/loc = null if (istype(T, /turf)) loc = T.loc if (istype(loc, /area)) if (!loc.power_equip && !istype(src.loc,/obj/item) && !APU_power) - has_power = 0 + blind = 1 - if (has_power) + if (!blind) src.sight |= SEE_TURFS src.sight |= SEE_MOBS src.sight |= SEE_OBJS + src.see_in_dark = 8 src.see_invisible = SEE_INVISIBLE_LIVING if (aiRestorePowerRoutine==2) @@ -76,10 +77,12 @@ //Blind the AI src.blind.screen_loc = "1,1 to 15,15" - + if (src.blind.layer!=18) + src.blind.layer = 18 src.sight = src.sight&~SEE_TURFS src.sight = src.sight&~SEE_MOBS src.sight = src.sight&~SEE_OBJS + src.see_in_dark = 0 src.see_invisible = SEE_INVISIBLE_LIVING //Now to tell the AI why they're blind and dying slowly. diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm index 69d957fbaf9..c4a4d634488 100644 --- a/code/modules/mob/living/silicon/laws.dm +++ b/code/modules/mob/living/silicon/laws.dm @@ -39,20 +39,23 @@ laws.delete_law(law) log_and_message_admins("has deleted a law belonging to [src]: [law.law]") -/mob/living/silicon/proc/clear_inherent_laws() +/mob/living/silicon/proc/clear_inherent_laws(var/silent = 0) laws_sanity_check() laws.clear_inherent_laws() - log_and_message_admins("cleared the inherent laws of [src]") + if(!silent) + log_and_message_admins("cleared the inherent laws of [src]") -/mob/living/silicon/proc/clear_ion_laws() +/mob/living/silicon/proc/clear_ion_laws(var/silent = 0) laws_sanity_check() laws.clear_ion_laws() - log_and_message_admins("cleared the ion laws of [src]") + if(!silent) + log_and_message_admins("cleared the ion laws of [src]") -/mob/living/silicon/proc/clear_supplied_laws() +/mob/living/silicon/proc/clear_supplied_laws(var/silent = 0) laws_sanity_check() laws.clear_supplied_laws() - log_and_message_admins("cleared the supplied laws of [src]") + if(!silent) + log_and_message_admins("cleared the supplied laws of [src]") /mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws) var/prefix = "" diff --git a/code/modules/mob/living/silicon/pai/admin.dm b/code/modules/mob/living/silicon/pai/admin.dm new file mode 100644 index 00000000000..069c5d2c684 --- /dev/null +++ b/code/modules/mob/living/silicon/pai/admin.dm @@ -0,0 +1,21 @@ +// Originally a debug verb, made it a proper adminverb for ~fun~ +/client/proc/makePAI(turf/t in view(), name as text, pai_key as null|text) + set name = "Make pAI" + set category = "Admin" + + if(!check_rights(R_ADMIN)) + return + + if(!pai_key) + var/client/C = input("Select client") as null|anything in clients + if(!C) return + pai_key = C.key + + log_and_message_admins("made a pAI with key=[pai_key] at ([t.x],[t.y],[t.z])") + var/obj/item/device/paicard/card = new(t) + var/mob/living/silicon/pai/pai = new(card) + pai.key = pai_key + card.setPersonality(pai) + + if(name) + pai.SetName(name) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index c5783cfbb31..aa6ab23a949 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -119,7 +119,6 @@ /mob/living/silicon/pai/check_eye(var/mob/user as mob) if (!src.current) return -1 - user.reset_view(src.current) return 0 /mob/living/silicon/pai/blob_act() diff --git a/code/modules/mob/living/silicon/robot/custom_sprites.dm b/code/modules/mob/living/silicon/robot/custom_sprites.dm index b738787d007..360308ccec4 100644 --- a/code/modules/mob/living/silicon/robot/custom_sprites.dm +++ b/code/modules/mob/living/silicon/robot/custom_sprites.dm @@ -1,5 +1,5 @@ -//list(ckey = real_name,) +//list(ckey = real_name,) //Since the ckey is used as the icon_state, the current system will only permit a single custom robot sprite per ckey. //While it might be possible for a ckey to use that custom sprite for several real_names, it seems rather pointless to support it. var/list/robot_custom_icons @@ -14,16 +14,17 @@ var/list/robot_custom_icons var/split_idx = findtext(line, "-") //this works if ckey cannot contain dashes, and findtext starts from the beginning if(!split_idx || split_idx == length(line)) continue //bad entry - + var/ckey = copytext(line, 1, split_idx) var/real_name = copytext(line, split_idx+1) - + robot_custom_icons[ckey] = real_name + return 1 /mob/living/silicon/robot/proc/set_custom_sprite() var/rname = robot_custom_icons[ckey] if(rname && rname == real_name) custom_sprite = 1 - icon = 'icons/mob/custom-synthetic.dmi' + icon = CUSTOM_ITEM_ROBOT if(icon_state == "robot") icon_state = "[ckey]-Standard" diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index 754129ce547..d2f2fb3ddd3 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -217,9 +217,9 @@ death() /mob/living/silicon/robot/drone/proc/full_law_reset() - clear_supplied_laws() - clear_inherent_laws() - clear_ion_laws() + clear_supplied_laws(1) + clear_inherent_laws(1) + clear_ion_laws(1) laws = new law_type //Reboot procs. @@ -261,7 +261,7 @@ src << "You are a maintenance drone, a tiny-brained robotic repair machine." src << "You have no individual will, no personality, and no drives or urges other than your laws." src << "Remember, you are lawed against interference with the crew. Also remember, you DO NOT take orders from the AI." - src << "Use :d to talk to other drones and say to speak silently to your nearby fellows." + src << "Use say ;Hello to talk to other drones and say Hello to speak silently to your nearby fellows." /mob/living/silicon/robot/drone/start_pulling(var/atom/movable/AM) diff --git a/code/modules/mob/living/silicon/robot/drone/drone_say.dm b/code/modules/mob/living/silicon/robot/drone/drone_say.dm new file mode 100644 index 00000000000..71ca1c6918c --- /dev/null +++ b/code/modules/mob/living/silicon/robot/drone/drone_say.dm @@ -0,0 +1,40 @@ +/mob/living/silicon/robot/drone/say(var/message) + if(local_transmit) + if (src.client) + if(client.prefs.muted & MUTE_IC) + src << "You cannot send IC messages (muted)." + return 0 + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return 0 + + message = sanitize(message) + + if (stat == 2) + return say_dead(message) + + if(copytext(message,1,2) == "*") + return emote(copytext(message,2)) + + if(copytext(message,1,2) == ";") + var/datum/language/L = all_languages["Drone Talk"] + if(istype(L)) + return L.broadcast(src,trim(copytext(message,2))) + + //Must be concious to speak + if (stat) + return 0 + + var/list/listeners = hearers(5,src) + listeners |= src + + for(var/mob/living/silicon/D in listeners) + if(D.client && D.local_transmit) + D << "[src] transmits, \"[message]\"" + + for (var/mob/M in player_list) + if (istype(M, /mob/new_player)) + continue + else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS) + if(M.client) M << "[src] transmits, \"[message]\"" + return 1 + ..(message) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index b7e32bb931d..f13a09cf953 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -64,9 +64,9 @@ if(src.camera && !scrambledcodes) if(src.stat == 2 || wires.IsIndexCut(BORG_WIRE_CAMERA)) - src.camera.status = 0 + src.camera.set_status(0) else - src.camera.status = 1 + src.camera.set_status(1) updatehealth() @@ -162,11 +162,13 @@ see_invisible = SEE_INVISIBLE_MINIMUM else if (src.sight_mode & BORGTHERM) src.sight |= SEE_MOBS + src.see_in_dark = 8 src.see_invisible = SEE_INVISIBLE_LEVEL_TWO else if (src.stat != 2) src.sight &= ~SEE_MOBS src.sight &= ~SEE_TURFS src.sight &= ~SEE_OBJS + src.see_in_dark = 8 // see_in_dark means you can FAINTLY see in the dark, humans have a range of 3 or so, tajaran have it at 8 src.see_invisible = SEE_INVISIBLE_LIVING // This is normal vision (25), setting it lower for normal vision means you don't "see" things like darkness since darkness // has a "invisible" value of 15 diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm index 59e251e01bf..3e072d3d742 100644 --- a/code/modules/mob/living/silicon/robot/robot_items.dm +++ b/code/modules/mob/living/silicon/robot/robot_items.dm @@ -37,7 +37,7 @@ for(var/obj/I in contents) for(var/mob/M in I.contents) M.death() - if(istype(I,/obj/item/stack/material))//Only deconsturcts one sheet at a time instead of the entire stack + if(istype(I,/obj/item/stack/material))//Only deconstructs one sheet at a time instead of the entire stack var/obj/item/stack/material/S = I if(S.get_amount() > 1) S.use(1) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index a338588df09..4d7179bbfce 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -504,7 +504,7 @@ var/global/list/robot_modules = list( src.modules += L src.modules += new /obj/item/weapon/tray/robotray(src) - src.modules += new /obj/item/weapon/reagent_containers/food/drinks/shaker(src) + src.modules += new /obj/item/weapon/reagent_containers/borghypo/service(src) src.emag = new /obj/item/weapon/reagent_containers/food/drinks/cans/beer(src) var/datum/reagents/R = new/datum/reagents(50) diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 1fefa272e56..25052354ed8 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -1,3 +1,35 @@ +/mob/living/silicon/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) + log_say("[key_name(src)] : [message]") + +/mob/living/silicon/robot/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) + ..() + if(message_mode) + if(!is_component_functioning("radio")) + src << "Your radio isn't functional at this time." + return 0 + if(message_mode == "general") + message_mode = null + return radio.talk_into(src,message,message_mode,verb,speaking) + +/mob/living/silicon/ai/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) + ..() + if(message_mode == "department") + return holopad_talk(message, verb, speaking) + else if(message_mode) + if (aiRadio.disabledAi || aiRestorePowerRoutine || stat) + src << "System Error - Transceiver Disabled." + return 0 + if(message_mode == "general") + message_mode = null + return aiRadio.talk_into(src,message,message_mode,verb,speaking) + +/mob/living/silicon/pai/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) + ..() + if(message_mode) + if(message_mode == "general") + message_mode = null + return radio.talk_into(src,message,message_mode,verb,speaking) + /mob/living/silicon/say_quote(var/text) var/ending = copytext(text, length(text)) @@ -23,131 +55,6 @@ return 1 return ..() -/mob/living/silicon/say(var/message) - if (!message) - return 0 - - if (src.client) - if(client.prefs.muted & MUTE_IC) - src << "You cannot send IC messages (muted)." - return 0 - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return 0 - - message = sanitize(message) - - if (stat == 2) - return say_dead(message) - - if(copytext(message,1,2) == "*") - return emote(copytext(message,2)) - - var/bot_type = 0 //Let's not do a fuck ton of type checks, thanks. - if(istype(src, /mob/living/silicon/ai)) - bot_type = IS_AI - else if(istype(src, /mob/living/silicon/robot)) - bot_type = IS_ROBOT - else if(istype(src, /mob/living/silicon/pai)) - bot_type = IS_PAI - - var/mob/living/silicon/ai/AI = src //and let's not declare vars over and over and over for these guys. - var/mob/living/silicon/robot/R = src - var/mob/living/silicon/pai/P = src - - //Must be concious to speak - if (stat) - return 0 - - var/verb = say_quote(message) - - //parse radio key and consume it - var/message_mode = parse_message_mode(message, "general") - if (message_mode) - if (message_mode == "general") - message = trim(copytext(message,2)) - else - message = trim(copytext(message,3)) - - //parse language key and consume it - var/datum/language/speaking = parse_language(message) - if (speaking) - verb = speaking.speech_verb - message = trim(copytext(message,2+length(speaking.key))) - - if(speaking.flags & HIVEMIND) - speaking.broadcast(src,trim(message)) - return 1 - - // Currently used by drones. - if(local_transmit) - var/list/listeners = hearers(5,src) - listeners |= src - - for(var/mob/living/silicon/D in listeners) - if(D.client && istype(D,src.type)) - D << "[src] transmits, \"[message]\"" - - for (var/mob/M in player_list) - if (istype(M, /mob/new_player)) - continue - else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS) - if(M.client) M << "[src] transmits, \"[message]\"" - return 1 - - if(message_mode && bot_type == IS_ROBOT && !R.is_component_functioning("radio")) - src << "\red Your radio isn't functional at this time." - return 0 - - switch(message_mode) - if("department") - switch(bot_type) - if(IS_AI) - return AI.holopad_talk(message, verb, speaking) - if(IS_ROBOT) - log_say("[key_name(src)] : [message]") - return R.radio.talk_into(src,message,message_mode,verb,speaking) - if(IS_PAI) - log_say("[key_name(src)] : [message]") - return P.radio.talk_into(src,message,message_mode,verb,speaking) - return 0 - - if("general") - switch(bot_type) - if(IS_AI) - if (AI.aiRadio.disabledAi || AI.aiRestorePowerRoutine || AI.stat) - src << "\red System Error - Transceiver Disabled" - return 0 - else - log_say("[key_name(src)] : [message]") - return AI.aiRadio.talk_into(src,message,null,verb,speaking) - if(IS_ROBOT) - log_say("[key_name(src)] : [message]") - return R.radio.talk_into(src,message,null,verb,speaking) - if(IS_PAI) - log_say("[key_name(src)] : [message]") - return P.radio.talk_into(src,message,null,verb,speaking) - return 0 - - else - if(message_mode) - switch(bot_type) - if(IS_AI) - if (AI.aiRadio.disabledAi || AI.aiRestorePowerRoutine || AI.stat) - src << "\red System Error - Transceiver Disabled" - return 0 - else - log_say("[key_name(src)] : [message]") - return AI.aiRadio.talk_into(src,message,message_mode,verb,speaking) - if(IS_ROBOT) - log_say("[key_name(src)] : [message]") - return R.radio.talk_into(src,message,message_mode,verb,speaking) - if(IS_PAI) - log_say("[key_name(src)] : [message]") - return P.radio.talk_into(src,message,message_mode,verb,speaking) - return 0 - - return ..(message,speaking,verb) - //For holopads only. Usable by AI. /mob/living/silicon/ai/proc/holopad_talk(var/message, verb, datum/language/speaking) diff --git a/code/modules/mob/living/simple_animal/constructs/constructs.dm b/code/modules/mob/living/simple_animal/constructs/constructs.dm index 65bf148ae4d..e79b7dea738 100644 --- a/code/modules/mob/living/simple_animal/constructs/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs/constructs.dm @@ -27,6 +27,7 @@ show_stat_health = 1 faction = "cult" supernatural = 1 + see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING var/nullblock = 0 mob_swap_flags = HUMAN|SIMPLE_ANIMAL|SLIME|MONKEY @@ -150,6 +151,7 @@ attacktext = "slashed" speed = -1 environment_smash = 1 + see_in_dark = 7 attack_sound = 'sound/weapons/rapidslice.ogg' construct_spells = list(/spell/targeted/ethereal_jaunt/shift) @@ -227,6 +229,7 @@ attacktext = "violently stabbed" speed = -1 environment_smash = 1 + see_in_dark = 7 attack_sound = 'sound/weapons/pierce.ogg' construct_spells = list( diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 9c78b95522f..3197c6023cc 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -11,6 +11,7 @@ emote_see = list("shakes their head", "shivers") speak_chance = 1 turns_per_move = 5 + see_in_dark = 6 meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat response_help = "pets" response_disarm = "gently pushes aside" diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index e5a670d472e..322d08dc9ff 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -17,6 +17,7 @@ response_help = "pets" response_disarm = "bops" response_harm = "kicks" + see_in_dark = 5 mob_size = 8 var/obj/item/inventory_head diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 7427a937aa3..60ddd0638b9 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -11,6 +11,7 @@ emote_see = list("shakes its head", "stamps a foot", "glares around") speak_chance = 1 turns_per_move = 5 + see_in_dark = 6 meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat meat_amount = 4 response_help = "pets" @@ -61,7 +62,8 @@ /mob/living/simple_animal/hostile/retaliate/goat/Retaliate() ..() - src.visible_message("\red [src] gets an evil-looking gleam in their eye.") + if(stat == CONSCIOUS) + visible_message("[src] gets an evil-looking gleam in their eye.") /mob/living/simple_animal/hostile/retaliate/goat/Move() ..() @@ -94,6 +96,7 @@ emote_see = list("shakes its head") speak_chance = 1 turns_per_move = 5 + see_in_dark = 6 meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat meat_amount = 6 response_help = "pets" diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 52295248579..23b9f8a0f8f 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -13,6 +13,7 @@ small = 1 speak_chance = 1 turns_per_move = 5 + see_in_dark = 6 maxHealth = 5 health = 5 meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index b673aee9f04..73de95acee7 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -12,6 +12,7 @@ emote_see = list("stares ferociously", "stomps") speak_chance = 1 turns_per_move = 5 + see_in_dark = 6 meat_type = /obj/item/weapon/reagent_containers/food/snacks/bearmeat response_help = "pets" response_disarm = "gently pushes aside" diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index ed3d451e207..4d7a8f7e3aa 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -15,6 +15,7 @@ emote_hear = list("chitters") speak_chance = 5 turns_per_move = 5 + see_in_dark = 10 meat_type = /obj/item/weapon/reagent_containers/food/snacks/xenomeat response_help = "pets" response_disarm = "gently pushes aside" @@ -198,4 +199,4 @@ #undef SPINNING_WEB #undef LAYING_EGGS #undef MOVING_TO_TARGET -#undef SPINNING_COCOON +#undef SPINNING_COCOON \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/kobold.dm b/code/modules/mob/living/simple_animal/kobold.dm index f634bd70f1b..3e52a408747 100644 --- a/code/modules/mob/living/simple_animal/kobold.dm +++ b/code/modules/mob/living/simple_animal/kobold.dm @@ -12,6 +12,7 @@ emote_see = list("looks around suspiciously.", "scratches it's arm.","putters around a bit.") speak_chance = 15 turns_per_move = 5 + see_in_dark = 6 meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/monkey response_help = "pets" response_disarm = "gently pushes aside" diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 4ee12cad52b..109e29f0368 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -2,7 +2,6 @@ density = 1 layer = 4.0 animate_movement = 2 - see_in_dark = 0 // flags = NOREACT var/datum/mind/mind diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 0a716ded345..0911a225934 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -264,11 +264,11 @@ var/list/global/organ_rel_size = list( /proc/get_zone_with_miss_chance(zone, var/mob/target, var/miss_chance_mod = 0, var/ranged_attack=0) zone = check_zone(zone) - // you cannot miss if your target is prone or restrained - if(target.buckled || target.lying) - return zone - // if your target is being grabbed aggressively by someone you cannot miss either if(!ranged_attack) + // you cannot miss if your target is prone or restrained + if(target.buckled || target.lying) + return zone + // if your target is being grabbed aggressively by someone you cannot miss either for(var/obj/item/weapon/grab/G in target.grabbed_by) if(G.state >= GRAB_AGGRESSIVE) return zone diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 3cffc1a57a2..04041316421 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -449,17 +449,10 @@ /mob/proc/Process_Spacemove(var/check_drift = 0) if(!Check_Dense_Object()) //Nothing to push off of so end here - make_floating(1) + update_floating(0) return 0 - if(istype(src,/mob/living/carbon/human/)) - var/mob/living/carbon/human/H = src - if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP)) //magboots + dense_object = no floaty effect - make_floating(0) - else - make_floating(1) - else - make_floating(1) + update_floating(1) if(restrained()) //Check to see if we can do things return 0 @@ -477,6 +470,8 @@ /mob/proc/Check_Dense_Object() //checks for anything to push off in the vicinity. also handles magboots on gravity-less floors tiles var/dense_object = 0 + var/shoegrip + for(var/turf/turf in oview(1,src)) if(istype(turf,/turf/space)) continue @@ -484,14 +479,9 @@ if(istype(turf,/turf/simulated/floor)) // Floors don't count if they don't have gravity var/area/A = turf.loc if(istype(A) && A.has_gravity == 0) - var/can_walk = 0 - - if(ishuman(src)) // Only humans can wear magboots, so we give them a chance to. - var/mob/living/carbon/human/H = src - if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP)) - can_walk = 1 - - if(!can_walk) + if(shoegrip == null) + shoegrip = Check_Shoegrip() //Shoegrip is only ever checked when a zero-gravity floor is encountered to reduce load + if(!shoegrip) continue dense_object++ @@ -511,6 +501,8 @@ return dense_object +/mob/proc/Check_Shoegrip() + return 0 /mob/proc/Process_Spaceslipping(var/prob_slip = 5) //Setup slipage diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index f8e89746956..63f111a4f1d 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -5,7 +5,6 @@ var/spawning = 0//Referenced when you want to delete the new_player later on in the code. var/totalPlayers = 0 //Player counts for the Lobby tab var/totalPlayersReady = 0 - universal_speak = 1 invisibility = 101 @@ -134,8 +133,6 @@ if(client.prefs.be_random_name) client.prefs.real_name = random_name(client.prefs.gender) - if(client.prefs.dummy) - qdel(client.prefs.dummy) observer.real_name = client.prefs.real_name observer.name = observer.real_name if(!client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed. @@ -455,8 +452,7 @@ client.prefs.randomize_appearance_for(new_character) else client.prefs.copy_to(new_character) - if(client.prefs.dummy) - qdel(client.prefs.dummy) + src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1) // MAD JAMS cant last forever yo if(mind) diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 7157f956f3d..00b6a3b8e4a 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -178,46 +178,519 @@ datum/preferences b_skin = blue - proc/update_preview_icon() //seriously. This is horrendous. //less so now - if(!dummy) - dummy = new(null, species) - dummy.set_species(species) - dummy.flags |= GODMODE - copy_to(dummy) - for (var/obj/item/I in dummy) - dummy.drop_from_inventory(I) - if(I.loc != dummy) - qdel(I) - var/jobflag - var/dept - if (job_civilian_low & ASSISTANT) - jobflag = job_civilian_low - dept = CIVILIAN - else if(job_civilian_high) - jobflag = job_civilian_high - dept = CIVILIAN - else if (job_medsci_high) - jobflag = job_medsci_high - dept = MEDSCI - else if (job_engsec_high) - jobflag = job_engsec_high - dept = ENGSEC - if(jobflag && dept && job_master) - for (var/datum/job/J in job_master.occupations) - if((J.department_flag & dept) && (J.flag & jobflag)) - var/alt = GetPlayerAltTitle(J) - if(alt) //more hacks - if(!dummy.mind) - dummy.mind = new - dummy.mind.role_alt_title = alt - J.equip(dummy) - break - dummy.update_eyes() - dummy.force_update_limbs() - dummy.regenerate_icons() - preview_icon = icon(dummy.icon) - for(var/image/I in dummy.overlays_standing) - if(I && I.icon) - preview_icon.Blend(icon(I.icon, I.icon_state), ICON_OVERLAY) + proc/update_preview_icon() //seriously. This is horrendous. + qdel(preview_icon_front) + qdel(preview_icon_side) + qdel(preview_icon) + + var/g = "m" + if(gender == FEMALE) g = "f" + + var/icon/icobase + var/datum/species/current_species = all_species[species] + + if(current_species) + icobase = current_species.icobase + else + icobase = 'icons/mob/human_races/r_human.dmi' + + preview_icon = new /icon(icobase, "torso_[g]") + preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY) + preview_icon.Blend(new /icon(icobase, "head_[g]"), ICON_OVERLAY) + + for(var/name in list("r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand")) + if(organ_data[name] == "amputated") continue + if(organ_data[name] == "cyborg") + var/datum/robolimb/R + if(rlimb_data[name]) R = all_robolimbs[rlimb_data[name]] + if(!R) R = basic_robolimb + preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY) // This doesn't check gendered_icon. Not an issue while only limbs can be robotic. + continue + preview_icon.Blend(new /icon(icobase, "[name]"), ICON_OVERLAY) + + //Tail + if(current_species && (current_species.tail)) + var/icon/temp = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[current_species.tail]_s") + preview_icon.Blend(temp, ICON_OVERLAY) + + // Skin color + if(current_species && (current_species.flags & HAS_SKIN_COLOR)) + preview_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) + + // Skin tone + if(current_species && (current_species.flags & HAS_SKIN_TONE)) + if (s_tone >= 0) + preview_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) + else + preview_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + + var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = current_species ? current_species.eyes : "eyes_s") + if ((current_species && (current_species.flags & HAS_EYE_COLOR))) + eyes_s.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) + + var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + if(hair_style) + var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + eyes_s.Blend(hair_s, ICON_OVERLAY) + + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] + if(facial_hair_style) + var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") + facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) + eyes_s.Blend(facial_s, ICON_OVERLAY) + + var/icon/underwear_s = null + if(underwear && current_species.flags & HAS_UNDERWEAR) + underwear_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = underwear) + + var/icon/undershirt_s = null + if(undershirt && current_species.flags & HAS_UNDERWEAR) + undershirt_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = undershirt) + + var/icon/clothes_s = null + if(job_civilian_low & ASSISTANT)//This gives the preview icon clothes depending on which job(if any) is set to 'high' + clothes_s = new /icon('icons/mob/uniform.dmi', "grey_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if(backbag == 2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + else if(backbag == 3 || backbag == 4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + + else if(job_civilian_high)//I hate how this looks, but there's no reason to go through this switch if it's empty + switch(job_civilian_high) + if(HOP) + clothes_s = new /icon('icons/mob/uniform.dmi', "hop_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "ianshirt"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(BARTENDER) + clothes_s = new /icon('icons/mob/uniform.dmi', "ba_suit_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "tophat"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(BOTANIST) + clothes_s = new /icon('icons/mob/uniform.dmi', "hydroponics_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "ggloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "apron"), ICON_OVERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "nymph"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-hyd"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(CHEF) + clothes_s = new /icon('icons/mob/uniform.dmi', "chef_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "chefhat"), ICON_OVERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "apronchef"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(JANITOR) + clothes_s = new /icon('icons/mob/uniform.dmi', "janitor_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "bio_janitor"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(LIBRARIAN) + clothes_s = new /icon('icons/mob/uniform.dmi', "red_suit_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "hairflower"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(QUARTERMASTER) + clothes_s = new /icon('icons/mob/uniform.dmi', "qm_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "poncho"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(CARGOTECH) + clothes_s = new /icon('icons/mob/uniform.dmi', "cargotech_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "flat_cap"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(MINER) + clothes_s = new /icon('icons/mob/uniform.dmi', "miner_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "bearpelt"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-eng"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(LAWYER) + clothes_s = new /icon('icons/mob/uniform.dmi', "internalaffairs_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon(INV_R_HAND_DEF_ICON, "briefcase"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "suitjacket_blue"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(CHAPLAIN) + clothes_s = new /icon('icons/mob/uniform.dmi', "chapblack_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "imperium_monk"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(CLOWN) + clothes_s = new /icon('icons/mob/uniform.dmi', "clown_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "clown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/mask.dmi', "clown"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "clownpack"), ICON_OVERLAY) + if(MIME) + clothes_s = new /icon('icons/mob/uniform.dmi', "mime_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "lgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/mask.dmi', "mime"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "beret"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "suspenders"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + + else if(job_medsci_high) + switch(job_medsci_high) + if(RD) + clothes_s = new /icon('icons/mob/uniform.dmi', "director_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "petehat"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-tox"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(SCIENTIST) + clothes_s = new /icon('icons/mob/uniform.dmi', "sciencewhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_tox_open"), ICON_OVERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "metroid"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-tox"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(XENOBIOLOGIST) + clothes_s = new /icon('icons/mob/uniform.dmi', "sciencewhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_tox_open"), ICON_OVERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "metroid"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-tox"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(CHEMIST) + clothes_s = new /icon('icons/mob/uniform.dmi', "chemistrywhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labgreen"), ICON_OVERLAY) + else + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_chem_open"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-chem"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(CMO) + clothes_s = new /icon('icons/mob/uniform.dmi', "cmo_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "bio_cmo"), ICON_OVERLAY) + else + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_cmo_open"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "medicalpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-med"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(DOCTOR) + clothes_s = new /icon('icons/mob/uniform.dmi', "medical_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "surgeon"), ICON_OVERLAY) + else + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "medicalpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-med"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(GENETICIST) + clothes_s = new /icon('icons/mob/uniform.dmi', "geneticswhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "monkeysuit"), ICON_OVERLAY) + else + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_gen_open"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-gen"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(VIROLOGIST) + clothes_s = new /icon('icons/mob/uniform.dmi', "virologywhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/mask.dmi', "sterile"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_vir_open"), ICON_OVERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "plaguedoctor"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "medicalpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-vir"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(ROBOTICIST) + clothes_s = new /icon('icons/mob/uniform.dmi', "robotics_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + if(prob(1)) + clothes_s.Blend(new /icon(INV_R_HAND_DEF_ICON, "toolbox_blue"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + + else if(job_engsec_high) + switch(job_engsec_high) + if(CAPTAIN) + clothes_s = new /icon('icons/mob/uniform.dmi', "captain_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "centcomcaptain"), ICON_OVERLAY) + else + clothes_s.Blend(new /icon('icons/mob/head.dmi', "captain"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-cap"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(HOS) + clothes_s = new /icon('icons/mob/uniform.dmi', "hosred_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "hosberet"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "securitypack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-sec"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(WARDEN) + clothes_s = new /icon('icons/mob/uniform.dmi', "warden_s") + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "slippers_worn"), ICON_OVERLAY) + else + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "securitypack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-sec"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(DETECTIVE) + clothes_s = new /icon('icons/mob/uniform.dmi', "detective_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/mask.dmi', "cigaron"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "detective"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "detective"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(OFFICER) + clothes_s = new /icon('icons/mob/uniform.dmi', "secred_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "officerberet"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "securitypack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-sec"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(CHIEF) + clothes_s = new /icon('icons/mob/uniform.dmi', "chief_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "hardhat0_white"), ICON_OVERLAY) + if(prob(1)) + clothes_s.Blend(new /icon(INV_R_HAND_DEF_ICON, "blueprints"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "engiepack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-eng"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(ENGINEER) + clothes_s = new /icon('icons/mob/uniform.dmi', "engine_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "orange"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "hardhat0_yellow"), ICON_OVERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "hazard"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "engiepack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-eng"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(ATMOSTECH) + clothes_s = new /icon('icons/mob/uniform.dmi', "atmos_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + if(prob(1)) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "firesuit"), ICON_OVERLAY) + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel-norm"), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + + if(AI)//Gives AI and borgs assistant-wear, so they can still customize their character + clothes_s = new /icon('icons/mob/uniform.dmi', "grey_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "straight_jacket"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "cardborg_h"), ICON_OVERLAY) + if(backbag == 2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + else if(backbag == 3 || backbag == 4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + if(CYBORG) + clothes_s = new /icon('icons/mob/uniform.dmi', "grey_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "cardborg"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "cardborg_h"), ICON_OVERLAY) + if(backbag == 2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "backpack"), ICON_OVERLAY) + else if(backbag == 3 || backbag == 4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + + if(disabilities & NEARSIGHTED) + preview_icon.Blend(new /icon('icons/mob/eyes.dmi', "glasses"), ICON_OVERLAY) + + preview_icon.Blend(eyes_s, ICON_OVERLAY) + if(underwear_s) + preview_icon.Blend(underwear_s, ICON_OVERLAY) + if(undershirt_s) + preview_icon.Blend(undershirt_s, ICON_OVERLAY) + if(clothes_s) + preview_icon.Blend(clothes_s, ICON_OVERLAY) preview_icon_front = new(preview_icon, dir = SOUTH) - preview_icon_side = new(preview_icon, dir = WEST) \ No newline at end of file + preview_icon_side = new(preview_icon, dir = WEST) + + qdel(eyes_s) + qdel(underwear_s) + qdel(undershirt_s) + qdel(clothes_s) diff --git a/code/modules/mob/update_icons.dm b/code/modules/mob/update_icons.dm index 627fb1dc53f..a6ae6dc4a09 100644 --- a/code/modules/mob/update_icons.dm +++ b/code/modules/mob/update_icons.dm @@ -1,15 +1,6 @@ //Most of these are defined at this level to reduce on checks elsewhere in the code. //Having them here also makes for a nice reference list of the various overlay-updating procs available -//default item on-mob icons -#define INV_HEAD_DEF_ICON 'icons/mob/head.dmi' -#define INV_BACK_DEF_ICON 'icons/mob/back.dmi' -#define INV_L_HAND_DEF_ICON 'icons/mob/items/lefthand.dmi' -#define INV_R_HAND_DEF_ICON 'icons/mob/items/righthand.dmi' -#define INV_W_UNIFORM_DEF_ICON 'icons/mob/uniform.dmi' -#define INV_ACCESSORIES_DEF_ICON 'icons/mob/ties.dmi' - - /mob/proc/regenerate_icons() //TODO: phase this out completely if possible return diff --git a/code/modules/nano/interaction/default.dm b/code/modules/nano/interaction/default.dm index aa692e0a236..79c08227d5a 100644 --- a/code/modules/nano/interaction/default.dm +++ b/code/modules/nano/interaction/default.dm @@ -15,7 +15,7 @@ return STATUS_UPDATE // Ghosts can view updates /mob/living/silicon/pai/default_can_use_topic(var/src_object) - if(src_object == src && !stat) + if((src_object == src || src_object == radio) && !stat) return STATUS_INTERACTIVE else return ..() diff --git a/code/modules/nano/modules/law_manager.dm b/code/modules/nano/modules/law_manager.dm index 37913485ebd..503f914d2ac 100644 --- a/code/modules/nano/modules/law_manager.dm +++ b/code/modules/nano/modules/law_manager.dm @@ -188,7 +188,7 @@ /obj/nano_module/law_manager/proc/package_laws(var/list/data, var/field, var/list/datum/ai_law/laws) var/packaged_laws[0] for(var/datum/ai_law/AL in laws) - packaged_laws[++packaged_laws.len] = list("law" = sanitize(AL.law), "index" = AL.get_index(), "state" = owner.laws.get_state_law(AL), "ref" = "\ref[AL]") + packaged_laws[++packaged_laws.len] = list("law" = AL.law, "index" = AL.get_index(), "state" = owner.laws.get_state_law(AL), "ref" = "\ref[AL]") data[field] = packaged_laws data["has_[field]"] = packaged_laws.len diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index b767292511a..bbafd2e53bc 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -95,7 +95,7 @@ var/list/organ_cache = list() if(B && prob(40)) reagents.remove_reagent("blood",0.1) blood_splatter(src,B,1) - damage += rand(1,3) + if(config.organs_decay) damage += rand(1,3) if(damage >= max_damage) die() diff --git a/code/modules/organs/organ_stump.dm b/code/modules/organs/organ_stump.dm index 728f9cd1bc1..ab808f4c488 100644 --- a/code/modules/organs/organ_stump.dm +++ b/code/modules/organs/organ_stump.dm @@ -22,3 +22,6 @@ /obj/item/organ/external/stump/removed() ..() qdel(src) + +/obj/item/organ/external/stump/is_usable() + return 0 diff --git a/code/modules/organs/wound.dm b/code/modules/organs/wound.dm index 8f39b91555a..850f5114c03 100644 --- a/code/modules/organs/wound.dm +++ b/code/modules/organs/wound.dm @@ -36,9 +36,8 @@ var/list/stages // internal wounds can only be fixed through surgery var/internal = 0 - // maximum stage at which bleeding should still happen, counted from the right rather than the left of the list - // 1 means all stages except the last should bleed - var/max_bleeding_stage = 1 + // maximum stage at which bleeding should still happen. Beyond this stage bleeding is prevented. + var/max_bleeding_stage = 0 // one of CUT, BRUISE, BURN var/damage_type = CUT // whether this wound needs a bandage/salve to heal at all @@ -64,8 +63,6 @@ src.damage = damage - max_bleeding_stage = src.desc_list.len - max_bleeding_stage - // initialize with the appropriate stage src.init_stage(damage) @@ -248,7 +245,9 @@ /** CUTS **/ /datum/wound/cut/small // link wound descriptions to amounts of damage - max_bleeding_stage = 2 + // Minor cuts have max_bleeding_stage set to the stage that bears the wound type's name. + // The major cut types have the max_bleeding_stage set to the clot stage (which is accordingly given the "blood soaked" descriptor). + max_bleeding_stage = 3 stages = list("ugly ripped cut" = 20, "ripped cut" = 10, "cut" = 5, "healing cut" = 2, "small scab" = 0) damage_type = CUT @@ -263,25 +262,25 @@ damage_type = CUT /datum/wound/cut/gaping - max_bleeding_stage = 2 - stages = list("gaping wound" = 50, "large blood soaked clot" = 25, "large clot" = 15, "small angry scar" = 5, "small straight scar" = 0) + max_bleeding_stage = 3 + stages = list("gaping wound" = 50, "large blood soaked clot" = 25, "blood soaked clot" = 15, "small angry scar" = 5, "small straight scar" = 0) damage_type = CUT /datum/wound/cut/gaping_big - max_bleeding_stage = 2 - stages = list("big gaping wound" = 60, "healing gaping wound" = 40, "large angry scar" = 10, "large straight scar" = 0) + max_bleeding_stage = 3 + stages = list("big gaping wound" = 60, "healing gaping wound" = 40, "large blood soaked clot" = 25, "large angry scar" = 10, "large straight scar" = 0) damage_type = CUT datum/wound/cut/massive - max_bleeding_stage = 2 - stages = list("massive wound" = 70, "massive healing wound" = 50, "massive angry scar" = 10, "massive jagged scar" = 0) + max_bleeding_stage = 3 + stages = list("massive wound" = 70, "massive healing wound" = 50, "massive blood soaked clot" = 25, "massive angry scar" = 10, "massive jagged scar" = 0) damage_type = CUT /** BRUISES **/ /datum/wound/bruise - stages = list("monumental bruise" = 80, "huge bruise" = 50, "large bruise" = 30,\ + stages = list("monumental bruise" = 80, "huge bruise" = 50, "large bruise" = 30, "moderate bruise" = 20, "small bruise" = 10, "tiny bruise" = 5) - max_bleeding_stage = 3 + max_bleeding_stage = 3 //only large bruise and above can bleed. autoheal_cutoff = 30 damage_type = BRUISE @@ -311,7 +310,7 @@ datum/wound/cut/massive internal = 1 stages = list("severed artery" = 30, "cut artery" = 20, "damaged artery" = 10, "bruised artery" = 5) autoheal_cutoff = 5 - max_bleeding_stage = 0 //all stages bleed. It's called internal bleeding after all. + max_bleeding_stage = 4 //all stages bleed. It's called internal bleeding after all. /** EXTERNAL ORGAN LOSS **/ /datum/wound/lost_limb @@ -323,7 +322,7 @@ datum/wound/cut/massive switch(losstype) if(DROPLIMB_EDGE, DROPLIMB_BLUNT) damage_type = CUT - max_bleeding_stage = 3 + max_bleeding_stage = 3 //clotted stump and above can bleed. stages = list( "ripped stump" = damage_amt*1.3, "bloody stump" = damage_amt, @@ -332,7 +331,6 @@ datum/wound/cut/massive ) if(DROPLIMB_BURN) damage_type = BURN - max_bleeding_stage = 1 stages = list( "ripped charred stump" = damage_amt*1.3, "charred stump" = damage_amt, diff --git a/code/modules/overmap/ships/computers/helm.dm b/code/modules/overmap/ships/computers/helm.dm index a0611c68669..e15de319698 100644 --- a/code/modules/overmap/ships/computers/helm.dm +++ b/code/modules/overmap/ships/computers/helm.dm @@ -53,11 +53,10 @@ /obj/machinery/computer/helm/check_eye(var/mob/user as mob) if (!manual_control) - return null + return -1 if (!get_dist(user, src) > 1 || user.blinded || !linked ) - return null - user.reset_view(linked) - return 1 + return -1 + return 0 /obj/machinery/computer/helm/attack_hand(var/mob/user as mob) if(..()) @@ -67,6 +66,8 @@ if(!isAI(user)) user.set_machine(src) + if(linked) + user.reset_view(linked) ui_interact(user) diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index eb8bb66b72a..a355e169571 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -251,7 +251,7 @@ var/list/solars_list = list() playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) return 1 - if(istype(W, /obj/item/stack/material/glass)) + if(istype(W, /obj/item/stack/material) && (W.get_material_name() == "glass" || W.get_material_name() == "rglass")) var/obj/item/stack/material/S = W if(S.use(2)) glass_type = W.type diff --git a/code/modules/projectiles/guns/launcher/crossbow.dm b/code/modules/projectiles/guns/launcher/crossbow.dm index b199d4ad8b4..e11844293e1 100644 --- a/code/modules/projectiles/guns/launcher/crossbow.dm +++ b/code/modules/projectiles/guns/launcher/crossbow.dm @@ -254,9 +254,9 @@ else user << "You need at least five segments of cable coil to complete this task." return - else if(istype(W,/obj/item/stack/material/plastic)) + else if(istype(W,/obj/item/stack/material) && W.get_material_name() == "plastic") if(buildstate == 3) - var/obj/item/stack/material/plastic/P = W + var/obj/item/stack/material/P = W if(P.use(3)) user << "You assemble and install a heavy plastic lath onto the crossbow." buildstate++ diff --git a/code/modules/projectiles/guns/launcher/pneumatic.dm b/code/modules/projectiles/guns/launcher/pneumatic.dm index e7c3870ed07..b20e9521e60 100644 --- a/code/modules/projectiles/guns/launcher/pneumatic.dm +++ b/code/modules/projectiles/guns/launcher/pneumatic.dm @@ -167,9 +167,9 @@ buildstate++ update_icon() return - else if(istype(W,/obj/item/stack/material/steel)) + else if(istype(W,/obj/item/stack/material) && W.get_material_name() == DEFAULT_WALL_MATERIAL) if(buildstate == 2) - var/obj/item/stack/material/steel/M = W + var/obj/item/stack/material/M = W if(M.use(5)) user << "You assemble a chassis around the cannon frame." buildstate++ diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index f13ad242873..6d8c40c16c2 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -165,14 +165,17 @@ //roll to-hit miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier, 0) - var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1)) - if(!hit_zone) + var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1 || original != target_mob)) //if the projectile hits a target we weren't originally aiming at then retain the chance to miss + + var/result = PROJECTILE_FORCE_MISS + if(hit_zone) + def_zone = hit_zone //set def_zone, so if the projectile ends up hitting someone else later (to be implemented), it is more likely to hit the same part + result = target_mob.bullet_act(src, def_zone) + + if(result == PROJECTILE_FORCE_MISS) visible_message("\The [src] misses [target_mob] narrowly!") return 0 - //set def_zone, so if the projectile ends up hitting someone else later (to be implemented), it is more likely to hit the same part - def_zone = hit_zone - //hit messages if(silenced) target_mob << "You've been hit in the [parse_zone(def_zone)] by \the [src]!" @@ -193,7 +196,7 @@ msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with \a [src] (JMP)") //sometimes bullet_act() will want the projectile to continue flying - if (target_mob.bullet_act(src, def_zone) == -1) + if (result == PROJECTILE_CONTINUE) return 0 return 1 @@ -227,7 +230,7 @@ else passthrough = 1 //so ghosts don't stop bullets else - passthrough = (A.bullet_act(src, def_zone) == -1) //backwards compatibility + passthrough = (A.bullet_act(src, def_zone) == PROJECTILE_CONTINUE) //backwards compatibility if(isturf(A)) for(var/obj/O in A) O.bullet_act(src) diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 495046362ac..166cda695ef 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -7,14 +7,14 @@ /datum/reagents/New(var/max = 100, atom/A = null) maximum_volume = max my_atom = A - + //I dislike having these here but map-objects are initialised before world/New() is called. >_> if(!chemical_reagents_list) //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id var/paths = typesof(/datum/reagent) - /datum/reagent chemical_reagents_list = list() for(var/path in paths) - var/datum/reagent/D = new path() + var/datum/reagent/D = new path() if(!D.name) continue chemical_reagents_list[D.id] = D @@ -41,16 +41,16 @@ for(var/id in reaction_ids) if(!chemical_reactions_list[id]) chemical_reactions_list[id] = list() - chemical_reactions_list[id] += D - break // Don't bother adding ourselves to other reagent ids, it is redundant. - -/datum/reagents/Destroy() - ..() - for(var/datum/reagent/R in reagent_list) - qdel(R) - reagent_list.Cut() - reagent_list = null - if(my_atom && my_atom.reagents == src) + chemical_reactions_list[id] += D + break // Don't bother adding ourselves to other reagent ids, it is redundant. + +/datum/reagents/Destroy() + ..() + for(var/datum/reagent/R in reagent_list) + qdel(R) + reagent_list.Cut() + reagent_list = null + if(my_atom && my_atom.reagents == src) my_atom.reagents = null /* Internal procs */ @@ -170,7 +170,7 @@ if(!isnull(data)) // For all we know, it could be zero or empty string and meaningful current.mix_data(data, amount) update_total() - if(!safety) + if(!safety) handle_reactions() if(my_atom) my_atom.on_reagent_change() @@ -184,7 +184,7 @@ R.initialize_data(data) update_total() if(!safety) - handle_reactions() + handle_reactions() if(my_atom) my_atom.on_reagent_change() return 1 @@ -219,7 +219,7 @@ /datum/reagents/proc/has_reagent(var/id, var/amount = 0) for(var/datum/reagent/current in reagent_list) if(current.id == id) - if(current.volume >= amount) + if(current.volume >= amount) return 1 else return 0 @@ -235,12 +235,12 @@ if(current.id == id) return current.volume return 0 - + /datum/reagents/proc/get_data(var/id) for(var/datum/reagent/current in reagent_list) if(current.id == id) return current.get_data() - return 0 + return 0 /datum/reagents/proc/get_reagents() . = list() @@ -254,14 +254,14 @@ amount = min(amount, total_volume) if(!amount) - return + return var/part = amount / total_volume - + for(var/datum/reagent/current in reagent_list) var/amount_to_remove = current.volume * part remove_reagent(current.id, amount_to_remove, 1) - + update_total() handle_reactions() return amount @@ -270,7 +270,7 @@ if(!target || !istype(target)) return - amount = min(amount, total_volume, target.get_free_space() / multiplier) + amount = max(0, min(amount, total_volume, target.get_free_space() / multiplier)) if(!amount) return @@ -290,9 +290,9 @@ /* Holder-to-atom and similar procs */ -//The general proc for applying reagents to things. This proc assumes the reagents are being applied externally, +//The general proc for applying reagents to things. This proc assumes the reagents are being applied externally, //not directly injected into the contents. It first calls touch, then the appropriate trans_to_*() or splash_mob(). -//If for some reason touch effects are bypassed (e.g. injecting stuff directly into a reagent container or person), +//If for some reason touch effects are bypassed (e.g. injecting stuff directly into a reagent container or person), //call the appropriate trans_to_*() proc. /datum/reagents/proc/trans_to(var/atom/target, var/amount = 1, var/multiplier = 1, var/copy = 0) touch(target) //First, handle mere touch effects @@ -418,5 +418,5 @@ /* Atom reagent creation - use it all the time */ -/atom/proc/create_reagents(var/max_vol) - reagents = new/datum/reagents(max_vol, src) +/atom/proc/create_reagents(var/max_vol) + reagents = new/datum/reagents(max_vol, src) diff --git a/code/modules/reagents/Chemistry-Logging.dm b/code/modules/reagents/Chemistry-Logging.dm new file mode 100644 index 00000000000..1432b18a2e8 --- /dev/null +++ b/code/modules/reagents/Chemistry-Logging.dm @@ -0,0 +1,28 @@ + +/var/list/chemical_reaction_logs = list() + +/proc/log_chemical_reaction(atom/A, datum/chemical_reaction/R, multiplier) + if(!A || !R) + return + + var/turf/T = get_turf(A) + var/logstr = "[usr ? key_name(usr) : "EVENT"] mixed [R.name] ([R.result]) (x[multiplier]) in \the [A] at [T ? "[T.x],[T.y],[T.z]" : "*null*"]" + + chemical_reaction_logs += "\[[time_stamp()]\] [logstr]" + + if(R.log_is_important) + message_admins(logstr) + log_admin(logstr) + +/client/proc/view_chemical_reaction_logs() + set name = "Show Chemical Reactions" + set category = "Admin" + + if(!check_rights(R_ADMIN)) + return + + var/html = "" + for(var/entry in chemical_reaction_logs) + html += "[entry]
" + + usr << browse(html, "window=chemlogs") diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index 7f6da07d671..2048968d949 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -123,7 +123,7 @@ if(href_list["amount"]) var/id = href_list["add"] - var/amount = text2num(href_list["amount"]) + var/amount = isgoodnumber(text2num(href_list["amount"])) R.trans_id_to(src, id, amount) else if (href_list["addcustom"]) @@ -137,7 +137,7 @@ if(href_list["amount"]) var/id = href_list["remove"] - var/amount = text2num(href_list["amount"]) + var/amount = isgoodnumber(text2num(href_list["amount"])) if(mode) reagents.trans_id_to(beaker, id, amount) else @@ -301,18 +301,10 @@ /obj/machinery/chem_master/proc/isgoodnumber(var/num) if(isnum(num)) - if(num > 200) - num = 200 - else if(num < 0) - num = 1 - else - num = round(num) - return num + return Clamp(round(num), 0, 200) else return 0 - - /obj/machinery/chem_master/condimaster name = "CondiMaster 3000" condi = 1 diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index 6da341198db..829dcf19dc6 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -9,6 +9,7 @@ var/result_amount = 0 var/mix_message = "The solution begins to bubble." + var/log_is_important = 0 // If this reaction should be considered important for logging. Important recipes message admins when mixed, non-important ones just log to file. /datum/chemical_reaction/proc/can_happen(var/datum/reagents/holder) return 1 @@ -146,6 +147,7 @@ result = "kelotane" required_reagents = list("silicon" = 1, "carbon" = 1) result_amount = 2 + log_is_important = 1 /datum/chemical_reaction/peridaxon name = "Peridaxon" @@ -392,6 +394,7 @@ result = "coolant" required_reagents = list("tungsten" = 1, "oxygen" = 1, "water" = 1) result_amount = 3 + log_is_important = 1 /datum/chemical_reaction/rezadone name = "Rezadone" @@ -527,6 +530,7 @@ result = "nitroglycerin" required_reagents = list("glycerol" = 1, "pacid" = 1, "sacid" = 1) result_amount = 2 + log_is_important = 1 /datum/chemical_reaction/nitroglycerin/on_reaction(var/datum/reagents/holder, var/created_volume) var/datum/effect/effect/system/reagents_explosion/e = new() diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 985ed3d9d27..47c80d42a14 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -1,5 +1,5 @@ /obj/item/weapon/reagent_containers/borghypo - name = "Cyborg Hypospray" + name = "cyborg hypospray" desc = "An advanced chemical synthesizer and injection system, designed for heavy-duty medical equipment." icon = 'icons/obj/syringe.dmi' item_state = "hypo" @@ -7,13 +7,15 @@ amount_per_transfer_from_this = 5 volume = 30 possible_transfer_amounts = null + var/mode = 1 var/charge_cost = 50 var/charge_tick = 0 var/recharge_time = 5 //Time it takes for shots to recharge (in seconds) - var/list/datum/reagents/reagent_list = list() var/list/reagent_ids = list("tricordrazine", "inaprovaline", "spaceacillin") + var/list/reagent_volumes = list() + var/list/reagent_names = list() /obj/item/weapon/reagent_containers/borghypo/surgeon reagent_ids = list("bicaridine", "inaprovaline", "dexalin") @@ -23,79 +25,114 @@ /obj/item/weapon/reagent_containers/borghypo/New() ..() - for(var/R in reagent_ids) - add_reagent(R) + + for(var/T in reagent_ids) + reagent_volumes[T] = volume + var/datum/reagent/R = chemical_reagents_list[T] + reagent_names += R.name processing_objects.Add(src) - /obj/item/weapon/reagent_containers/borghypo/Destroy() processing_objects.Remove(src) ..() -/obj/item/weapon/reagent_containers/borghypo/process() //Every [recharge_time] seconds, recharge some reagents for the cyborg - charge_tick++ - if(charge_tick < recharge_time) return 0 +/obj/item/weapon/reagent_containers/borghypo/process() //Every [recharge_time] seconds, recharge some reagents for the cyborg+ + if(++charge_tick < recharge_time) + return 0 charge_tick = 0 if(isrobot(loc)) var/mob/living/silicon/robot/R = loc if(R && R.cell) - var/datum/reagents/RG = reagent_list[mode] - if(RG.total_volume < RG.maximum_volume) //Don't recharge reagents and drain power if the storage is full. - R.cell.use(charge_cost) //Take power from borg... - RG.add_reagent(reagent_ids[mode], 5) //And fill hypo with reagent. + for(var/T in reagent_ids) + if(reagent_volumes[T] < volume) + R.cell.use(charge_cost) + reagent_volumes[T] = min(reagent_volumes[T] + 5, volume) return 1 -// Use this to add more chemicals for the borghypo to produce. -/obj/item/weapon/reagent_containers/borghypo/proc/add_reagent(var/reagent) - reagent_ids |= reagent - var/datum/reagents/RG = new(30) - RG.my_atom = src - reagent_list += RG +/obj/item/weapon/reagent_containers/borghypo/attack(var/mob/living/M, var/mob/user) + if(!istype(M)) + return - var/datum/reagents/R = reagent_list[reagent_list.len] - R.add_reagent(reagent, 30) - -/obj/item/weapon/reagent_containers/borghypo/attack(mob/living/M as mob, mob/user as mob) - var/datum/reagents/R = reagent_list[mode] - if(!R.total_volume) + if(!reagent_volumes[reagent_ids[mode]]) user << "The injector is empty." return - if (!istype(M)) - return - if (R.total_volume && M.can_inject(user, 1)) + if(M.can_inject(user, 1)) user << "You inject [M] with the injector." M << "You feel a tiny prick!" if(M.reagents) - var/trans = R.trans_to_mob(M, amount_per_transfer_from_this, CHEM_BLOOD) - user << "[trans] units injected. [R.total_volume] units remaining." + var/t = min(amount_per_transfer_from_this, reagent_volumes[reagent_ids[mode]]) + M.reagents.add_reagent(reagent_ids[mode], t) + reagent_volumes[reagent_ids[mode]] -= t + admin_inject_log(user, M, src, reagent_ids[mode], t) + user << "[t] units injected. [reagent_volumes[reagent_ids[mode]]] units remaining." return -/obj/item/weapon/reagent_containers/borghypo/attack_self(mob/user as mob) - playsound(src.loc, 'sound/effects/pop.ogg', 50, 0) //Change the mode - mode++ - if(mode > reagent_list.len) - mode = 1 +/obj/item/weapon/reagent_containers/borghypo/attack_self(mob/user as mob) //Change the mode + var/t = "" + for(var/i = 1 to reagent_ids.len) + if(t) + t += ", " + if(mode == i) + t += "[reagent_names[i]]" + else + t += "[reagent_names[i]]" + t = "Available reagents: [t]." + user << t - charge_tick = 0 //Prevents wasted chems/cell charge if you're cycling through modes. - var/datum/reagent/R = chemical_reagents_list[reagent_ids[mode]] - user << "Synthesizer is now producing '[R.name]'." return +/obj/item/weapon/reagent_containers/borghypo/Topic(var/href, var/list/href_list) + if(href_list["reagent"]) + var/t = reagent_ids.Find(href_list["reagent"]) + if(t) + playsound(loc, 'sound/effects/pop.ogg', 50, 0) + mode = t + var/datum/reagent/R = chemical_reagents_list[reagent_ids[mode]] + usr << "Synthesizer is now producing '[R.name]'." + /obj/item/weapon/reagent_containers/borghypo/examine(mob/user) if(!..(user, 2)) return - var/empty = 1 + var/datum/reagent/R = chemical_reagents_list[reagent_ids[mode]] - for(var/datum/reagents/RS in reagent_list) - var/datum/reagent/R = locate() in RS.reagent_list - if(R) - user << "It currently has [R.volume] units of [R.name] stored." - empty = 0 + user << "It is currently producing [R.name] and has [reagent_volumes[reagent_ids[mode]]] out of [volume] units left." - if(empty) - user << "It is currently empty. Allow some time for the internal syntheszier to produce more." +/obj/item/weapon/reagent_containers/borghypo/service + name = "cyborg drink synthesizer" + desc = "A portable drink dispencer." + icon = 'icons/obj/drinks.dmi' + icon_state = "shaker" + charge_cost = 20 + recharge_time = 3 + volume = 60 + possible_transfer_amounts = list(5, 10, 20, 30) + reagent_ids = list("beer", "kahlua", "whiskey", "wine", "vodka", "gin", "rum", "tequilla", "vermouth", "cognac", "ale", "mead", "water", "sugar", "ice", "tea", "icetea", "cola", "spacemountainwind", "dr_gibb", "space_up", "tonic", "sodawater", "lemon_lime", "orangejuice", "limejuice", "watermelonjuice") + +/obj/item/weapon/reagent_containers/borghypo/service/attack(var/mob/M, var/mob/user) + return + +/obj/item/weapon/reagent_containers/borghypo/service/afterattack(var/obj/target, var/mob/user, var/proximity) + if(!proximity) + return + + if(!target.is_open_container() || !target.reagents) + return + + if(!reagent_volumes[reagent_ids[mode]]) + user << "[src] is out of this reagent, give it some time to refill." + return + + if(!target.reagents.get_free_space()) + user << "[target] is full." + return + + var/t = min(amount_per_transfer_from_this, reagent_volumes[reagent_ids[mode]]) + target.reagents.add_reagent(reagent_ids[mode], t) + reagent_volumes[reagent_ids[mode]] -= t + user << "You transfer [t] units of the solution to [target]." + return diff --git a/code/modules/reagents/reagent_containers/food/drinks.dm b/code/modules/reagents/reagent_containers/food/drinks.dm index 43a406153c1..f70e06f421a 100644 --- a/code/modules/reagents/reagent_containers/food/drinks.dm +++ b/code/modules/reagents/reagent_containers/food/drinks.dm @@ -18,7 +18,6 @@ attack(mob/M as mob, mob/user as mob, def_zone) if(standard_feed_mob(user, M)) - robot_refill(user) return return 0 @@ -29,22 +28,10 @@ if(standard_dispenser_refill(user, target)) return if(standard_pour_into(user, target)) - robot_refill(user) return return ..() - proc/robot_refill(var/mob/living/silicon/robot/user) - if(!istype(user)) - return 0 - - user.cell.use(30) - var/refill = reagents.get_master_reagent_id() - user << "Now synthesizing [amount_per_transfer_from_this] units of [refill]..." - spawn(300) - reagents.add_reagent(refill, amount_per_transfer_from_this) - user << "Cyborg [src] refilled." - self_feed_message(var/mob/user) user << "You swallow a gulp from \the [src]." diff --git a/code/modules/recycling/disposal-construction.dm b/code/modules/recycling/disposal-construction.dm index d88d5cb5947..3ee774e0123 100644 --- a/code/modules/recycling/disposal-construction.dm +++ b/code/modules/recycling/disposal-construction.dm @@ -83,7 +83,7 @@ ///// Z-Level stuff - if(ptype<6 || ptype>8 && !(ptype==11 || ptype==12)) + if(!(ptype in list(6, 7, 8, 11, 12, 13, 14))) ///// Z-Level stuff icon_state = "con[base_state]" else diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index fd1e53ae0a7..9dd8d1f9560 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -46,7 +46,7 @@ eject() if(trunk) trunk.linked = null - ..() + return ..() // attack by item places it in to disposal /obj/machinery/disposal/attackby(var/obj/item/I, var/mob/user) @@ -636,7 +636,7 @@ /obj/structure/disposalholder/Destroy() qdel(gas) active = 0 - ..() + return ..() // Disposal pipes diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index f5191fb37f1..1eaf9ba97e0 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -104,16 +104,13 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). return 1 if(O.is_open_container()) return 0 -// if(!istype(O, /obj/item/stack/material/glass) && !istype(O, /obj/item/stack/material/gold) && !istype(O, /obj/item/stack/material/diamond) && !istype(O, /obj/item/stack/material/uranium)) -// user << "You cannot insert this item into \the [src]!" -// return 1 if(stat) return 1 if(busy) user << "\The [src] is busy. Please wait for completion of previous operation." return 1 - if(istype(O, /obj/item/stack/material/glass) || istype(O, /obj/item/stack/material/gold) || istype(O, /obj/item/stack/material/diamond) || istype(O, /obj/item/stack/material/uranium)) + if(istype(O, /obj/item/stack/material) && O.get_material_name() in list("glass", "gold", "diamond", "uranium")) var/obj/item/stack/material/stack = O if((TotalMaterials() + stack.perunit) > max_material_amount) diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index c35d820372c..409a0f7424e 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -144,28 +144,27 @@ Note: Must be placed west/left of and R&D console to function. icon_state = "protolathe" busy = 1 use_power(max(1000, (3750 * amount / 10))) - var/stacktype = stack.type - stack.use(amount) - if(do_after(user, 16)) + var/material/material = stack.get_material() + if(istype(material) && do_after(user, 16) && stack.use(amount)) user << "You add [amount] sheets to \the [src]." icon_state = "protolathe" - switch(stacktype) - if(/obj/item/stack/material/steel) - m_amount += amount * 3750 - if(/obj/item/stack/material/glass) - g_amount += amount * 3750 - if(/obj/item/stack/material/gold) - gold_amount += amount * 2000 - if(/obj/item/stack/material/silver) - silver_amount += amount * 2000 - if(/obj/item/stack/material/phoron) - phoron_amount += amount * 2000 - if(/obj/item/stack/material/uranium) - uranium_amount += amount * 2000 - if(/obj/item/stack/material/diamond) - diamond_amount += amount * 2000 - else - new stacktype(loc, amount) + + var/amount_to_add = amount * material.stack_per_sheet + switch(material.name) + if(DEFAULT_WALL_MATERIAL) + m_amount += amount_to_add + if("glass") + g_amount += amount_to_add + if("gold") + gold_amount += amount_to_add + if("silver") + silver_amount += amount_to_add + if("phoron") + phoron_amount += amount_to_add + if("uranium") + uranium_amount += amount_to_add + if("diamond") + diamond_amount += amount_to_add busy = 0 updateUsrDialog() return diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 4f0178ed3d7..37814e58556 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -439,25 +439,24 @@ won't update every console in existence) but it's more of a hassle to do. Also, else if(href_list["lathe_ejectsheet"] && linked_lathe) //Causes the protolathe to eject a sheet of material var/desired_num_sheets = text2num(href_list["amount"]) var/res_amount, type - var/material/M = name_to_material[href_list["lathe_ejectsheet"]] + var/material/M = get_material_by_name(href_list["lathe_ejectsheet"]) if(istype(M)) type = M.stack_type - - switch(name_to_material[href_list["lathe_ejectsheet"]]) - if(DEFAULT_WALL_MATERIAL) - res_amount = "m_amount" - if("glass") - res_amount = "g_amount" - if("gold") - res_amount = "gold_amount" - if("silver") - res_amount = "silver_amount" - if("phoron") - res_amount = "phoron_amount" - if("uranium") - res_amount = "uranium_amount" - if("diamond") - res_amount = "diamond_amount" + switch(M.name) + if(DEFAULT_WALL_MATERIAL) + res_amount = "m_amount" + if("glass") + res_amount = "g_amount" + if("gold") + res_amount = "gold_amount" + if("silver") + res_amount = "silver_amount" + if("phoron") + res_amount = "phoron_amount" + if("uranium") + res_amount = "uranium_amount" + if("diamond") + res_amount = "diamond_amount" if(ispath(type) && hasvar(linked_lathe, res_amount)) var/obj/item/stack/material/sheet = new type(linked_lathe.loc) diff --git a/code/modules/spells/spellbook.dm b/code/modules/spells/spellbook.dm index 6013ebfa14b..958fb4f64ae 100644 --- a/code/modules/spells/spellbook.dm +++ b/code/modules/spells/spellbook.dm @@ -242,6 +242,7 @@ if (!(XRAY in H.mutations)) H.mutations.Add(XRAY) H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) + H.see_in_dark = 8 H.see_invisible = SEE_INVISIBLE_LEVEL_TWO H << "span class='notice'>The walls suddenly disappear.
" temp = "You have purchased a scrying orb, and gained x-ray vision." diff --git a/code/modules/tables/presets.dm b/code/modules/tables/presets.dm index 60d45f1ede5..933f54ea8b7 100644 --- a/code/modules/tables/presets.dm +++ b/code/modules/tables/presets.dm @@ -63,11 +63,11 @@ icon_state = "holo_preview" color = "#EEEEEE" New() - material = get_material_by_name("holographic [DEFAULT_TABLE_MATERIAL]") + material = get_material_by_name("holo[DEFAULT_TABLE_MATERIAL]") ..() woodentable/holotable icon_state = "holo_preview" New() - material = get_material_by_name("holographic wood") + material = get_material_by_name("holowood") ..() diff --git a/code/modules/tables/tables.dm b/code/modules/tables/tables.dm index 11fc798d330..a496e32c81f 100644 --- a/code/modules/tables/tables.dm +++ b/code/modules/tables/tables.dm @@ -200,7 +200,7 @@ // Returns the material to set the table to. /obj/structure/table/proc/common_material_add(obj/item/stack/material/S, mob/user, verb) // Verb is actually verb without 'e' or 'ing', which is added. Works for 'plate'/'plating' and 'reinforce'/'reinforcing'. - var/material/M = name_to_material[S.default_type] + var/material/M = S.get_material() if(!istype(M)) user << "You cannot [verb]e \the [src] with \the [S]." return null diff --git a/code/setup.dm b/code/setup.dm index 6d49d591b34..a21e9f60426 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -662,8 +662,8 @@ var/list/be_special_flags = list( #define NONGLOBAL 32 // Do not add to general languages list. #define INNATE 64 // All mobs can be assumed to speak and understand this language. (audible emotes) #define NO_TALK_MSG 128 // Do not show the "\The [speaker] talks into \the [radio]" message -#define NO_STUTTER 256 // No stuttering, slurring, or other speech problems - +#define NO_STUTTER 256 // No stuttering, slurring, or other speech problems +#define COMMON_VERBS 512 // Robots will apply regular verbs to this. //Flags for zone sleeping #define ZONE_ACTIVE 1 #define ZONE_SLEEPING 0 @@ -720,6 +720,10 @@ var/list/be_special_flags = list( #define FILE_DRM 16 // Some files want to not be copied/moved. This is them complaining that you tried. #define NETWORK_FAILURE 32 +// Special return values from bullet_act(). Positive return values are already used to indicate the blocked level of the projectile. +#define PROJECTILE_CONTINUE -1 //if the projectile should continue flying after calling bullet_act() +#define PROJECTILE_FORCE_MISS -2 //if the projectile should treat the attack as a miss (suppresses attack and admin logs) - only applies to mobs. + // Some on_mob_life() procs check for alien races. #define IS_DIONA 1 #define IS_VOX 2 @@ -873,8 +877,8 @@ var/list/be_special_flags = list( #define DOOR_OPEN_LAYER 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6 #define DOOR_CLOSED_LAYER 3.1 //Above most items if closed #define LIGHTING_LAYER 11 -#define OBFUSCATION_LAYER 14 //Where images covering the view for eyes are put -#define SCREEN_LAYER 17 //Mob HUD/effects layer +#define OBFUSCATION_LAYER 21 //Where images covering the view for eyes are put +#define SCREEN_LAYER 22 //Mob HUD/effects layer ///////////////// @@ -973,6 +977,17 @@ var/list/be_special_flags = list( #ifndef CUSTOM_ITEM_MOB #define CUSTOM_ITEM_MOB 'icons/mob/custom_items_mob.dmi' #endif +#ifndef CUSTOM_ITEM_ROBOT +#define CUSTOM_ITEM_ROBOT 'icons/mob/custom_synthetic.dmi' +#endif + +//default item on-mob icons +#define INV_HEAD_DEF_ICON 'icons/mob/head.dmi' +#define INV_BACK_DEF_ICON 'icons/mob/back.dmi' +#define INV_L_HAND_DEF_ICON 'icons/mob/items/lefthand.dmi' +#define INV_R_HAND_DEF_ICON 'icons/mob/items/righthand.dmi' +#define INV_W_UNIFORM_DEF_ICON 'icons/mob/uniform.dmi' +#define INV_ACCESSORIES_DEF_ICON 'icons/mob/ties.dmi' #define SHARD_SHARD "shard" #define SHARD_SHRAPNEL "shrapnel" @@ -986,3 +1001,8 @@ var/list/be_special_flags = list( #define TABLE_BRITTLE_MATERIAL_MULTIPLIER 4 // Amount table damage is multiplied by if it is made of a brittle material (e.g. glass) +#define FOR_DVIEW(type, range, center, invis_flags) \ + dview_mob.loc = center; \ + dview_mob.see_invisible = invis_flags; \ + for(type in view(range, dview_mob)) +#define END_FOR_DVIEW dview_mob.loc = null diff --git a/code/world.dm b/code/world.dm index fb9aabdc544..9adfe9968a5 100644 --- a/code/world.dm +++ b/code/world.dm @@ -102,7 +102,8 @@ var/world_topic_spam_protect_time = world.timeofday n++ return n - else if (T == "status") + else if (copytext(T,1,7) == "status") + var/input[] = params2list(T) var/list/s = list() s["version"] = game_version s["mode"] = master_mode @@ -111,21 +112,37 @@ var/world_topic_spam_protect_time = world.timeofday s["vote"] = config.allow_vote_mode s["ai"] = config.allow_ai s["host"] = host ? host : null - s["players"] = list() s["stationtime"] = worldtime2text() - var/n = 0 - var/admins = 0 - for(var/client/C in clients) - if(C.holder) - if(C.holder.fakekey) - continue //so stealthmins aren't revealed by the hub - admins++ - s["player[n]"] = C.key - n++ - s["players"] = n + if(input["status"] == "2") + var/list/players = list() + var/list/admins = list() - s["admins"] = admins + for(var/client/C in clients) + if(C.holder) + if(C.holder.fakekey) + continue + admins[C.key] = C.holder.rank + players += C.key + + s["players"] = players.len + s["playerlist"] = list2params(players) + s["admins"] = admins.len + s["adminlist"] = list2params(admins) + else + var/n = 0 + var/admins = 0 + + for(var/client/C in clients) + if(C.holder) + if(C.holder.fakekey) + continue //so stealthmins aren't revealed by the hub + admins++ + s["player[n]"] = C.key + n++ + + s["players"] = n + s["admins"] = admins return list2params(s) diff --git a/config/example/config.txt b/config/example/config.txt index 7b090d4b387..7f94edde443 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -362,7 +362,11 @@ STARLIGHT 0 ## Enable asteroid tunnel/cave generation. Will behave strangely if turned off with a map that expects it on. # GENERATE_ASTEROID - +## Uncomment to enable organ decay outside of a body or storage item. +#ORGANS_CAN_DECAY ## Uncomment to have the changelog file automatically open when a user connects and hasn't seen the latest changelog #AGGRESSIVE_CHANGELOG + +## Uncomment to override default brain health. +#DEFAULT_BRAIN_HEALTH 400 \ No newline at end of file diff --git a/html/changelog.html b/html/changelog.html index b1fb843f989..0f347f664fe 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,26 @@ -->
+

31 July 2015

+

HarpyEagle updated:

+ + +

29 July 2015

+

Karolis2011 updated:

+ + +

27 July 2015

+

Kelenius updated:

+ +

14 July 2015

HarpyEagle updated:

{{if data.listening}} - {{:helper.link("On", '', {"stopic":"radio", "talk":1}, 'selected')}} - {{:helper.link("Off", '', {"stopic":"radio", "talk":1})}} + {{:helper.link("On", '', {"stopic":"radio", "talk":1, "nowindow":1}, 'selected')}} + {{:helper.link("Off", '', {"stopic":"radio", "talk":1, "nowindow":1})}} {{else}} - {{:helper.link("On", '', {"stopic":"radio", "talk":1})}} - {{:helper.link("Off", '', {"stopic":"radio", "talk":1}, 'selected')}} + {{:helper.link("On", '', {"stopic":"radio", "talk":1, "nowindow":1})}} + {{:helper.link("Off", '', {"stopic":"radio", "talk":1, "nowindow":1}, 'selected')}} {{/if}}
@@ -22,11 +22,11 @@ code/modules/mob/living/silicon/pai/software_modules.dm Frequency:
- {{:helper.link("--", '', {"stopic":"radio", "freq":-10})}} - {{:helper.link("-", '', {"stopic":"radio", "freq": -2})}} + {{:helper.link("--", '', {"stopic":"radio", "freq":-10, "nowindow":1})}} + {{:helper.link("-", '', {"stopic":"radio", "freq": -2, "nowindow":1})}}
{{:data.frequency}}
- {{:helper.link("+", '', {"stopic":"radio", "freq": 2})}} - {{:helper.link("++", '', {"stopic":"radio", "freq": 10})}} + {{:helper.link("+", '', {"stopic":"radio", "freq": 2, "nowindow":1})}} + {{:helper.link("++", '', {"stopic":"radio", "freq": 10, "nowindow":1})}}
@@ -37,12 +37,12 @@ code/modules/mob/living/silicon/pai/software_modules.dm
{{if value.listening}} - {{:helper.link("On", '', {"stopic":"radio", "channel":value.name, "listen":1}, 'selected')}} - {{:helper.link("Off", '', {"stopic":"radio", "channel":value.name, "listen":1})}} + {{:helper.link("On", '', {"stopic":"radio", "channel":value.name, "listen":1, "nowindow":1}, 'selected')}} + {{:helper.link("Off", '', {"stopic":"radio", "channel":value.name, "listen":1, "nowindow":1})}} {{else}} - {{:helper.link("On", '', {"stopic":"radio", "channel":value.name, "listen":1})}} - {{:helper.link("Off", '', {"stopic":"radio", "channel":value.name, "listen":1}, 'selected')}} + {{:helper.link("On", '', {"stopic":"radio", "channel":value.name, "listen":1, "nowindow":1})}} + {{:helper.link("Off", '', {"stopic":"radio", "channel":value.name, "listen":1, "nowindow":1}, 'selected')}} {{/if}}
-{{/for}} \ No newline at end of file +{{/for}} diff --git a/tools/dmitool/dmitool.jar b/tools/dmitool/dmitool.jar index c7df4d8b7fd..4cfa49f36de 100644 Binary files a/tools/dmitool/dmitool.jar and b/tools/dmitool/dmitool.jar differ