diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index 34d3fef31be..ac212377724 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -265,6 +265,7 @@ CREATE TABLE `player` ( `ghost_anonsay` tinyint(1) NOT NULL DEFAULT '0', `exp` mediumtext, `clientfps` smallint(4) DEFAULT '0', + `atklog` smallint(4) DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index afc730af8c9..15dccc0a805 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -264,6 +264,7 @@ CREATE TABLE `SS13_player` ( `ghost_anonsay` tinyint(1) NOT NULL DEFAULT '0', `exp` mediumtext, `clientfps` smallint(4) DEFAULT '0', + `atklog` smallint(4) DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; diff --git a/SQL/updates/3-4.sql b/SQL/updates/3-4.sql new file mode 100644 index 00000000000..25b6f9007cd --- /dev/null +++ b/SQL/updates/3-4.sql @@ -0,0 +1,4 @@ +#Updating the SQL from version 3 to version 4. -Kyep +#Adding new column to contain the atklog value. +ALTER TABLE `player` + ADD `atklog` smallint(4) DEFAULT '0' AFTER `clientfps`; \ No newline at end of file diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 4c2708bf9dd..c244dc0c7a7 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -39,8 +39,7 @@ #define IGNORESLOWDOWN 256 #define GODMODE 4096 #define FAKEDEATH 8192 //Replaces stuff like changeling.changeling_fakedeath -#define DISFIGURED 16384 //I'll probably move this elsewhere if I ever get wround to writing a bitflag mob-damage system -#define XENO_HOST 32768 //Tracks whether we're gonna be a baby alien's mummy. +#define XENO_HOST 16384 //Tracks whether we're gonna be a baby alien's mummy. //Grab levels diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index 58e2be31b01..3ad2900bfa1 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -7,23 +7,35 @@ #define PLANE_SPACE_PARALLAX -90 #define GAME_PLANE 0 + #define SPACE_LAYER 1.8 //#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define #define MID_TURF_LAYER 2.02 #define HIGH_TURF_LAYER 2.03 +#define TURF_PLATING_DECAL_LAYER 2.031 +#define TURF_DECAL_LAYER 2.039 //Makes turf decals appear in DM how they will look inworld. #define ABOVE_OPEN_TURF_LAYER 2.04 #define CLOSED_TURF_LAYER 2.05 +#define BULLET_HOLE_LAYER 2.06 #define ABOVE_NORMAL_TURF_LAYER 2.08 #define LATTICE_LAYER 2.2 #define DISPOSAL_PIPE_LAYER 2.3 -#define GAS_PIPE_LAYER 2.35 +#define GAS_PIPE_HIDDEN_LAYER 2.35 #define WIRE_LAYER 2.4 #define WIRE_TERMINAL_LAYER 2.45 +#define GAS_SCRUBBER_LAYER 2.46 +#define GAS_PIPE_VISIBLE_LAYER 2.47 +#define GAS_FILTER_LAYER 2.48 +#define GAS_PUMP_LAYER 2.49 #define LOW_OBJ_LAYER 2.5 +#define LOW_SIGIL_LAYER 2.52 +#define SIGIL_LAYER 2.54 +#define HIGH_SIGIL_LAYER 2.56 #define BELOW_OPEN_DOOR_LAYER 2.6 #define BLASTDOOR_LAYER 2.65 #define OPEN_DOOR_LAYER 2.7 +#define DOOR_HELPER_LAYER 2.71 //keep this above OPEN_DOOR_LAYER #define PROJECTILE_HIT_THRESHHOLD_LAYER 2.75 //projectiles won't hit objects at or below this layer if possible #define TABLE_LAYER 2.8 #define BELOW_OBJ_LAYER 2.9 @@ -52,9 +64,13 @@ #define SPACEVINE_LAYER 4.8 #define SPACEVINE_MOB_LAYER 4.9 //#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define +#define GASFIRE_LAYER 5.05 #define RIPPLE_LAYER 5.1 #define GHOST_LAYER 6 +#define LOW_LANDMARK_LAYER 9 +#define MID_LANDMARK_LAYER 9.1 +#define HIGH_LANDMARK_LAYER 9.2 #define AREA_LAYER 10 #define MASSIVE_OBJ_LAYER 11 #define POINT_LAYER 12 @@ -62,6 +78,26 @@ #define LIGHTING_PLANE 15 #define LIGHTING_LAYER 15 +#define ABOVE_LIGHTING_PLANE 16 +#define ABOVE_LIGHTING_LAYER 16 + +#define BYOND_LIGHTING_PLANE 17 +#define BYOND_LIGHTING_LAYER 17 + //HUD layer defines + +#define FULLSCREEN_PLANE 18 +#define FLASH_LAYER 18 +#define FULLSCREEN_LAYER 18.1 +#define UI_DAMAGE_LAYER 18.2 +#define BLIND_LAYER 18.3 +#define CRIT_LAYER 18.4 +#define CURSE_LAYER 18.5 + +#define HUD_PLANE 19 #define HUD_LAYER 19 -#define HUD_PLANE 90 \ No newline at end of file +#define ABOVE_HUD_PLANE 20 +#define ABOVE_HUD_LAYER 20 + +#define SPLASHSCREEN_LAYER 21 +#define SPLASHSCREEN_PLANE 21 \ No newline at end of file diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index 160fa30a5c6..5b38b592ac6 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -7,6 +7,11 @@ #define STATIC_LIGHT 6 #define STATIC_ENVIRON 7 +//Power use +#define NO_POWER_USE 0 +#define IDLE_POWER_USE 1 +#define ACTIVE_POWER_USE 2 + //computer3 error codes, move lower in the file when it passes dev -Sayu #define PROG_CRASH 1 // Generic crash #define MISSING_PERIPHERAL 2 // Missing hardware diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index b59b2a94182..f465317db9c 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -15,7 +15,6 @@ #define CHAT_GHOSTSIGHT 8 #define CHAT_PRAYER 16 #define CHAT_RADIO 32 -#define CHAT_ATTACKLOGS 64 #define CHAT_DEBUGLOGS 128 #define CHAT_LOOC 256 #define CHAT_GHOSTRADIO 512 @@ -27,7 +26,14 @@ #define DONATOR_PUBLIC 32768 #define CHAT_NO_TICKETLOGS 65536 -#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC) +#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC) + +// Admin attack logs filter system, see /proc/add_attack_logs and /proc/msg_admin_attack +#define ATKLOG_ALL 0 +#define ATKLOG_ALMOSTALL 1 +#define ATKLOG_MOST 2 +#define ATKLOG_FEW 3 +#define ATKLOG_NONE 4 // Playtime tracking system, see jobs_exp.dm #define EXP_TYPE_LIVING "Living" diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index 3acd09a1a81..22e13f87f8a 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -18,4 +18,5 @@ #define VV_NEW_LIST "New List" #define VV_NULL "NULL" #define VV_RESTORE_DEFAULT "Restore to Default" -#define VV_MARKED_DATUM "Marked Datum" \ No newline at end of file +#define VV_MARKED_DATUM "Marked Datum" +#define VV_REGEX "Regex" \ No newline at end of file diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 5c483b310fe..b62f32c2da9 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -490,19 +490,26 @@ proc/pollCandidates(Question, be_special_type, antag_age_check = 0, poll_time = return candidates -/proc/pollCandidatesByKeyWithVeto(adminclient, adminusr, max_slots, Question, be_special_type, antag_age_check = 0, poll_time = 300, ignore_respawnability = 0, min_hours = 0, flashwindow = TRUE, check_antaghud = TRUE) +/proc/pollCandidatesWithVeto(adminclient, adminusr, max_slots, Question, be_special_type, antag_age_check = 0, poll_time = 300, ignore_respawnability = 0, min_hours = 0, flashwindow = TRUE, check_antaghud = TRUE) var/list/willing_ghosts = pollCandidates(Question, be_special_type, antag_age_check, poll_time, ignore_respawnability, min_hours, flashwindow, check_antaghud) - var/list/candidate_ckeys = list() - var/list/selected_ckeys = list() + var/list/selected_ghosts = list() if(!willing_ghosts.len) - return selected_ckeys - for(var/mob/dead/observer/G in willing_ghosts) - candidate_ckeys += G.key - for(var/i = max_slots, (i > 0 && candidate_ckeys.len), i--) - var/this_ckey = input("Pick players. This will go on until there either no more ghosts to pick from or the slots are full.", "Candidates") as null|anything in candidate_ckeys - candidate_ckeys -= this_ckey - selected_ckeys += this_ckey - return selected_ckeys + return selected_ghosts + + var/list/candidate_ghosts = willing_ghosts.Copy() + + to_chat(adminusr, "Candidate Ghosts:"); + for(var/mob/dead/observer/G in candidate_ghosts) + if(G.key && G.client) + to_chat(adminusr, "- [G] ([G.key])"); + else + candidate_ghosts -= G + + for(var/i = max_slots, (i > 0 && candidate_ghosts.len), i--) + var/this_ghost = input("Pick players. This will go on until there either no more ghosts to pick from or the [i] remaining slot(s) are full.", "Candidates") as null|anything in candidate_ghosts + candidate_ghosts -= this_ghost + selected_ghosts += this_ghost + return selected_ghosts /proc/window_flash(client/C) if(ismob(C)) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index a8a6307e70c..95afa6244d3 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -248,11 +248,11 @@ Proc for attack log creation, because really why not This is always put in the attack log. */ -/proc/add_attack_logs(mob/user, mob/target, what_done, admin_notify = TRUE) +/proc/add_attack_logs(mob/user, mob/target, what_done, custom_level) if(islist(target)) // Multi-victim adding var/list/targets = target for(var/mob/M in targets) - add_attack_logs(user, M, what_done, admin_notify) + add_attack_logs(user, M, what_done, custom_level) return var/user_str = key_name_log(user) @@ -263,8 +263,20 @@ This is always put in the attack log. if(istype(target)) target.create_attack_log("Attacked by [user_str]: [what_done]") log_attack(user_str, target_str, what_done) - if(admin_notify) - msg_admin_attack("[key_name_admin(user)] vs [key_name_admin(target)]: [what_done]") + + var/loglevel = ATKLOG_MOST + + if(custom_level) + loglevel = custom_level + else if(istype(target)) + if(isLivingSSD(target)) // Attacks on SSDs are shown to admins with any log level except ATKLOG_NONE + loglevel = ATKLOG_FEW + else if(!user.ckey && !target.ckey) // Attacks between NPCs are only shown to admins with ATKLOG_ALL + loglevel = ATKLOG_ALL + else if(!target.ckey) // Attacks by players on NPCs are only shown to admins with ATKLOG_ALL or ATKLOG_ALMOSTALL + loglevel = ATKLOG_ALMOSTALL + + msg_admin_attack("[key_name_admin(user)] vs [key_name_admin(target)]: [what_done]", loglevel) /proc/do_mob(var/mob/user, var/mob/target, var/time = 30, var/uninterruptible = 0, progress = 1, datum/callback/extra_checks = null) if(!user || !target) diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 54c79d26a7f..5fb559651d5 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -547,3 +547,5 @@ proc/checkhtml(var/t) text = replacetext(text, "", "\[cell\]") text = replacetext(text, "", "\[logo\]") return text + +#define string2charlist(string) (splittext(string, regex("(\\x0A|.)")) - splittext(string, "")) \ No newline at end of file diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index bf01bca6e3c..ddd6e14a5b0 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -65,7 +65,8 @@ user.do_attack_animation(M) M.attacked_by(src, user, def_zone) - add_attack_logs(user, M, "Attacked with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])", admin_notify = (force > 0 && damtype != STAMINA)) + add_attack_logs(user, M, "Attacked with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])", (M.ckey && force > 0 && damtype != STAMINA) ? null : ATKLOG_ALMOSTALL) + add_fingerprint(user) diff --git a/code/controllers/Processes/nanoui.dm b/code/controllers/Processes/nanoui.dm deleted file mode 100644 index 1667af943da..00000000000 --- a/code/controllers/Processes/nanoui.dm +++ /dev/null @@ -1,19 +0,0 @@ -/datum/controller/process/nanoui/setup() - name = "nanoui" - schedule_interval = 20 // every 2 seconds - -/datum/controller/process/nanoui/statProcess() - ..() - stat(null, "[nanomanager.processing_uis.len] UIs") - -/datum/controller/process/nanoui/doWork() - for(last_object in nanomanager.processing_uis) - var/datum/nanoui/NUI = last_object - if(istype(NUI) && isnull(NUI.gcDestroyed)) - try - NUI.process() - catch(var/exception/e) - catchException(e, NUI) - else - catchBadType(NUI) - nanomanager.processing_uis -= NUI diff --git a/code/controllers/Processes/weather.dm b/code/controllers/Processes/weather.dm deleted file mode 100644 index 919352313c6..00000000000 --- a/code/controllers/Processes/weather.dm +++ /dev/null @@ -1,54 +0,0 @@ -//Used for all kinds of weather, ex. lavaland ash storms. -// TODO: This could probably be better-integrated with the space manager -var/global/datum/controller/process/weather/weather_master - -/datum/controller/process/weather - var/list/processing_weather = list() - var/list/existing_weather = list() - var/list/eligible_zlevels = list() - -/datum/controller/process/weather/setup() - name = "weather" - schedule_interval = 10 - - for(var/V in subtypesof(/datum/weather)) - var/datum/weather/W = V - existing_weather |= new W - -/datum/controller/process/weather/statProcess() - ..() - stat(null, "[processing_weather.len] weather") - -/datum/controller/process/weather/doWork() - for(var/V in processing_weather) - var/datum/weather/W = V - if(W.aesthetic) - continue - for(var/mob/living/L in mob_list) - if(W.can_impact(L)) - W.impact(L) - SCHECK - for(var/Z in eligible_zlevels) - var/list/possible_weather_for_this_z = list() - for(var/V in existing_weather) - var/datum/weather/WE = V - if(WE.target_z == Z && WE.probability) //Another check so that it doesn't run extra weather - possible_weather_for_this_z[WE] = WE.probability - var/datum/weather/W = pickweight(possible_weather_for_this_z) - run_weather(W.name) - eligible_zlevels -= Z - addtimer(CALLBACK(src, .proc/make_z_eligible, Z), rand(3000, 6000) + W.weather_duration_upper, TIMER_UNIQUE) //Around 5-10 minutes between weathers - -DECLARE_GLOBAL_CONTROLLER(weather, weather_master) - -/datum/controller/process/weather/proc/run_weather(weather_name) - if(!weather_name) - return - for(var/V in existing_weather) - var/datum/weather/W = V - if(W.name == weather_name) - W.telegraph() - SCHECK - -/datum/controller/process/weather/proc/make_z_eligible(zlevel) - eligible_zlevels |= zlevel diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm new file mode 100644 index 00000000000..4f5798e4ae4 --- /dev/null +++ b/code/controllers/subsystem/weather.dm @@ -0,0 +1,83 @@ +#define STARTUP_STAGE 1 +#define MAIN_STAGE 2 +#define WIND_DOWN_STAGE 3 +#define END_STAGE 4 + +//Used for all kinds of weather, ex. lavaland ash storms. +SUBSYSTEM_DEF(weather) + name = "Weather" + flags = SS_BACKGROUND + wait = 10 + runlevels = RUNLEVEL_GAME + var/list/processing = list() + var/list/eligible_zlevels = list() + var/list/next_hit_by_zlevel = list() //Used by barometers to know when the next storm is coming + +/datum/controller/subsystem/weather/fire() + // process active weather + for(var/V in processing) + var/datum/weather/W = V + if(W.aesthetic || W.stage != MAIN_STAGE) + continue + for(var/i in living_mob_list) + var/mob/living/L = i + if(W.can_weather_act(L)) + W.weather_act(L) + + // start random weather on relevant levels + for(var/z in eligible_zlevels) + var/possible_weather = eligible_zlevels[z] + var/datum/weather/W = pickweight(possible_weather) + run_weather(W, list(text2num(z))) + eligible_zlevels -= z + var/randTime = rand(3000, 6000) + addtimer(CALLBACK(src, .proc/make_eligible, z, possible_weather), randTime + initial(W.weather_duration_upper), TIMER_UNIQUE) //Around 5-10 minutes between weathers + next_hit_by_zlevel["[z]"] = world.time + randTime + initial(W.telegraph_duration) + +/datum/controller/subsystem/weather/Initialize(start_timeofday) + for(var/V in subtypesof(/datum/weather)) + var/datum/weather/W = V + var/probability = initial(W.probability) + var/target_trait = initial(W.target_trait) + + // any weather with a probability set may occur at random + if(probability) + for(var/z in levels_by_trait(target_trait)) + LAZYINITLIST(eligible_zlevels["[z]"]) + eligible_zlevels["[z]"][W] = probability + ..() + +/datum/controller/subsystem/weather/proc/run_weather(datum/weather/weather_datum_type, z_levels) + if(istext(weather_datum_type)) + for(var/V in subtypesof(/datum/weather)) + var/datum/weather/W = V + if(initial(W.name) == weather_datum_type) + weather_datum_type = V + break + if(!ispath(weather_datum_type, /datum/weather)) + CRASH("run_weather called with invalid weather_datum_type: [weather_datum_type || "null"]") + return + + if(isnull(z_levels)) + z_levels = levels_by_trait(initial(weather_datum_type.target_trait)) + else if(isnum(z_levels)) + z_levels = list(z_levels) + else if(!islist(z_levels)) + CRASH("run_weather called with invalid z_levels: [z_levels || "null"]") + return + + var/datum/weather/W = new weather_datum_type(z_levels) + W.telegraph() + +/datum/controller/subsystem/weather/proc/make_eligible(z, possible_weather) + eligible_zlevels[z] = possible_weather + next_hit_by_zlevel["[z]"] = null + +/datum/controller/subsystem/weather/proc/get_weather(z, area/active_area) + var/datum/weather/A + for(var/V in processing) + var/datum/weather/W = V + if((z in W.impacted_z_levels) && W.area_type == active_area.type) + A = W + break + return A \ No newline at end of file diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index 3315cafb399..4e9380e2fed 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -94,7 +94,7 @@ debug_variables(SStimer) feedback_add_details("admin_verb","DTimer") if("Weather") - debug_variables(weather_master) + debug_variables(SSweather) feedback_add_details("admin_verb","DWeather") if("Space") debug_variables(space_manager) diff --git a/code/datums/looping_sounds/weather.dm b/code/datums/looping_sounds/weather.dm new file mode 100644 index 00000000000..d355bc59c14 --- /dev/null +++ b/code/datums/looping_sounds/weather.dm @@ -0,0 +1,47 @@ +/datum/looping_sound/active_outside_ashstorm + mid_sounds = list( + 'sound/weather/ashstorm/outside/active_mid1.ogg' = 1, + 'sound/weather/ashstorm/outside/active_mid1.ogg' = 1, + 'sound/weather/ashstorm/outside/active_mid1.ogg' = 1 + ) + mid_length = 80 + start_sound = 'sound/weather/ashstorm/outside/active_start.ogg' + start_length = 130 + end_sound = 'sound/weather/ashstorm/outside/active_end.ogg' + volume = 80 + +/datum/looping_sound/active_inside_ashstorm + mid_sounds = list( + 'sound/weather/ashstorm/inside/active_mid1.ogg' = 1, + 'sound/weather/ashstorm/inside/active_mid2.ogg' = 1, + 'sound/weather/ashstorm/inside/active_mid3.ogg' = 1 + ) + mid_length = 80 + start_sound = 'sound/weather/ashstorm/inside/active_start.ogg' + start_length = 130 + end_sound = 'sound/weather/ashstorm/inside/active_end.ogg' + volume = 60 + +/datum/looping_sound/weak_outside_ashstorm + mid_sounds = list( + 'sound/weather/ashstorm/outside/weak_mid1.ogg' = 1, + 'sound/weather/ashstorm/outside/weak_mid2.ogg' = 1, + 'sound/weather/ashstorm/outside/weak_mid3.ogg' = 1 + ) + mid_length = 80 + start_sound = 'sound/weather/ashstorm/outside/weak_start.ogg' + start_length = 130 + end_sound = 'sound/weather/ashstorm/outside/weak_end.ogg' + volume = 50 + +/datum/looping_sound/weak_inside_ashstorm + mid_sounds = list( + 'sound/weather/ashstorm/inside/weak_mid1.ogg' = 1, + 'sound/weather/ashstorm/inside/weak_mid2.ogg' = 1, + 'sound/weather/ashstorm/inside/weak_mid3.ogg' = 1 + ) + mid_length = 80 + start_sound = 'sound/weather/ashstorm/inside/weak_start.ogg' + start_length = 130 + end_sound = 'sound/weather/ashstorm/inside/weak_end.ogg' + volume = 30 diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 5094ff4e8d7..3f62c8ffaed 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -483,9 +483,11 @@ var/new_memo = copytext(input("Write new memory", "Memory", memory) as null|message,1,MAX_MESSAGE_LEN) if(isnull(new_memo)) return - memory = new_memo - log_admin("[key_name(usr)] has edited [key_name(current)]'s memory") - message_admins("[key_name_admin(usr)] has edited [key_name_admin(current)]'s memory") + var/confirmed = alert(usr, "Are you sure?", "Edit Memory", "Yes", "No") + if(confirmed == "Yes") // Because it is too easy to accidentally wipe someone's memory + memory = new_memo + log_admin("[key_name(usr)] has edited [key_name(current)]'s memory") + message_admins("[key_name_admin(usr)] has edited [key_name_admin(current)]'s memory") else if(href_list["obj_edit"] || href_list["obj_add"]) var/datum/objective/objective @@ -1217,12 +1219,8 @@ message_admins("[key_name_admin(usr)] has given [key_name_admin(current)] an uplink") else if(href_list["obj_announce"]) - var/obj_count = 1 - to_chat(current, "
Your current objectives:") - for(var/datum/objective/objective in objectives) - to_chat(current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - current << 'sound/ambience/alarm4.ogg' + announce_objectives() + SEND_SOUND(current, sound('sound/ambience/alarm4.ogg')) log_admin("[key_name(usr)] has announced [key_name(current)]'s objectives") message_admins("[key_name_admin(usr)] has announced [key_name_admin(current)]'s objectives") @@ -1282,6 +1280,14 @@ else if(A.type == datum_type) return A +/datum/mind/proc/announce_objectives() + var/obj_count = 1 + to_chat(current, "Your current objectives:") + for(var/objective in objectives) + var/datum/objective/O = objective + to_chat(current, "Objective #[obj_count]: [O.explanation_text]") + obj_count++ + /datum/mind/proc/find_syndicate_uplink() var/list/L = current.get_contents() for(var/obj/item/I in L) @@ -1294,7 +1300,7 @@ if(H) qdel(H) -/datum/mind/proc/make_Tratior() +/datum/mind/proc/make_Traitor() if(!(src in ticker.mode.traitors)) ticker.mode.traitors += src special_role = SPECIAL_ROLE_TRAITOR @@ -1334,7 +1340,16 @@ ticker.mode.equip_syndicate(current) -/datum/mind/proc/make_Changling() +/datum/mind/proc/make_Vampire() + if(!(src in ticker.mode.vampires)) + ticker.mode.vampires += src + ticker.mode.grant_vampire_powers(current) + special_role = SPECIAL_ROLE_VAMPIRE + ticker.mode.forge_vampire_objectives(src) + ticker.mode.greet_vampire(src) + ticker.mode.update_change_icons_added(src) + +/datum/mind/proc/make_Changeling() if(!(src in ticker.mode.changelings)) ticker.mode.changelings += src ticker.mode.grant_changeling_powers(current) @@ -1363,42 +1378,6 @@ ticker.mode.greet_wizard(src) ticker.mode.update_wiz_icons_added(src) - -/datum/mind/proc/make_Cultist() - if(!(src in ticker.mode.cult)) - ticker.mode.cult += src - ticker.mode.update_cult_icons_added(src) - special_role = SPECIAL_ROLE_CULTIST - to_chat(current, "You catch a glimpse of the Realm of [ticker.cultdat.entity_name], [ticker.cultdat.entity_title2]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.cultdat.entity_name].") - to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") - var/datum/game_mode/cult/cult = ticker.mode - if(GAMEMODE_IS_CULT) - cult.memorize_cult_objectives(src) - else - var/explanation = "Summon [ticker.cultdat.entity_name] via the use of the appropriate rune. It will only work if nine cultists stand on and around it." - to_chat(current, "Objective #1: [explanation]") - current.memory += "Objective #1: [explanation]
" - - - var/mob/living/carbon/human/H = current - if(istype(H)) - var/obj/item/tome/T = new(H) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = H.equip_in_one_of_slots(T, slots) - if(!where) - else - to_chat(H, "A tome, a message from your new master, appears in your [where].") - - if(!ticker.mode.equip_cultist(current)) - to_chat(H, "Summoning an amulet from your Master failed.") - /datum/mind/proc/make_Rev() if(ticker.mode.head_revolutionaries.len>0) // copy targets diff --git a/code/datums/spell.dm b/code/datums/spell.dm index cc3b85bf94e..e46ad460490 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -171,10 +171,13 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin /obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount switch(invocation_type) if("shout") - if(prob(50))//Auto-mute? Fuck that noise - user.say(invocation) + if(!user.IsVocal()) + user.emote("makes frantic gestures!") else - user.say(replacetext(invocation," ","`")) + if(prob(50))//Auto-mute? Fuck that noise + user.say(invocation) + else + user.say(replacetext(invocation," ","`")) if("whisper") if(prob(50)) user.whisper(invocation) diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm index 320cc137806..7ee152648c2 100644 --- a/code/datums/weather/weather.dm +++ b/code/datums/weather/weather.dm @@ -1,10 +1,5 @@ //The effects of weather occur across an entire z-level. For instance, lavaland has periodic ash storms that scorch most unprotected creatures. -#define STARTUP_STAGE 1 -#define MAIN_STAGE 2 -#define WIND_DOWN_STAGE 3 -#define END_STAGE 4 - /datum/weather var/name = "space wind" var/desc = "Heavy gusts of wind blanket the area, periodically knocking down anyone caught in the open." @@ -29,24 +24,25 @@ var/area_type = /area/space //Types of area to affect var/list/impacted_areas = list() //Areas to be affected by the weather, calculated when the weather begins - var/target_z = MAIN_STATION //The z-level to affect var/list/protected_areas = list()//Areas that are protected and excluded from the affected areas. + var/impacted_z_levels // The list of z-levels that this weather is actively affecting - var/overlay_layer = 10 //Since it's above everything else, this is the layer used by default. 2 is below mobs and walls if you need to use that. + var/overlay_layer = AREA_LAYER //Since it's above everything else, this is the layer used by default. TURF_LAYER is below mobs and walls if you need to use that. var/aesthetic = FALSE //If the weather has no purpose other than looks var/immunity_type = "storm" //Used by mobs to prevent them from being affected by the weather var/stage = END_STAGE //The stage of the weather, from 1-4 - var/probability = FALSE //Percent chance to happen if there are other possible weathers on the z-level + // These are read by the weather subsystem and used to determine when and where to run the weather. + var/probability = 0 // Weight amongst other eligible weather. If zero, will never happen randomly. + var/target_trait = STATION_LEVEL // The z-level trait to affect when run randomly or when not overridden. -/datum/weather/New() + var/barometer_predictable = FALSE + var/next_hit_time = 0 //For barometers to know when the next storm will hit + +/datum/weather/New(z_levels) ..() - weather_master.existing_weather |= src - -/datum/weather/Destroy() - weather_master.existing_weather -= src - return ..() + impacted_z_levels = z_levels /datum/weather/proc/telegraph() if(stage == STARTUP_STAGE) @@ -59,17 +55,18 @@ affectareas -= get_areas(V) for(var/V in affectareas) var/area/A = V - if(is_on_level_name(A,target_z)) + if(A.z in impacted_z_levels) impacted_areas |= A weather_duration = rand(weather_duration_lower, weather_duration_upper) + START_PROCESSING(SSweather, src) update_areas() - for(var/V in player_list) - var/mob/M = V - if(is_on_level_name(M,target_z)) + for(var/M in player_list) + var/turf/mob_turf = get_turf(M) + if(mob_turf && (mob_turf.z in impacted_z_levels)) if(telegraph_message) to_chat(M, telegraph_message) if(telegraph_sound) - M << sound(telegraph_sound) + SEND_SOUND(M, sound(telegraph_sound)) addtimer(CALLBACK(src, .proc/start), telegraph_duration) /datum/weather/proc/start() @@ -77,14 +74,13 @@ return stage = MAIN_STAGE update_areas() - for(var/V in player_list) - var/mob/M = V - if(is_on_level_name(M,target_z)) + for(var/M in player_list) + var/turf/mob_turf = get_turf(M) + if(mob_turf && (mob_turf.z in impacted_z_levels)) if(weather_message) to_chat(M, weather_message) if(weather_sound) - M << sound(weather_sound) - weather_master.processing_weather |= src + SEND_SOUND(M, sound(weather_sound)) addtimer(CALLBACK(src, .proc/wind_down), weather_duration) /datum/weather/proc/wind_down() @@ -92,24 +88,25 @@ return stage = WIND_DOWN_STAGE update_areas() - for(var/V in player_list) - var/mob/M = V - if(is_on_level_name(M,target_z)) + for(var/M in player_list) + var/turf/mob_turf = get_turf(M) + if(mob_turf && (mob_turf.z in impacted_z_levels)) if(end_message) to_chat(M, end_message) if(end_sound) - M << sound(end_sound) - weather_master.processing_weather -= src + SEND_SOUND(M, sound(end_sound)) addtimer(CALLBACK(src, .proc/end), end_duration) /datum/weather/proc/end() if(stage == END_STAGE) - return + return 1 stage = END_STAGE + STOP_PROCESSING(SSweather, src) update_areas() -/datum/weather/proc/can_impact(mob/living/L) //Can this weather impact a mob? - if(!is_on_level_name(L,target_z)) +/datum/weather/proc/can_weather_act(mob/living/L) //Can this weather impact a mob? + var/turf/mob_turf = get_turf(L) + if(mob_turf && !(mob_turf.z in impacted_z_levels)) return if(immunity_type in L.weather_immunities) return @@ -117,7 +114,7 @@ return return 1 -/datum/weather/proc/impact(mob/living/L) //What effect does this weather have on the hapless mob? +/datum/weather/proc/weather_act(mob/living/L) //What effect does this weather have on the hapless mob? return /datum/weather/proc/update_areas() @@ -136,8 +133,8 @@ N.icon_state = end_overlay if(END_STAGE) N.color = null - N.icon_state = initial(N.icon_state) + N.icon_state = "" N.icon = 'icons/turf/areas.dmi' - N.layer = 10 //Just default back to normal area stuff since I assume setting a var is faster than initial + N.layer = AREA_LAYER //Just default back to normal area stuff since I assume setting a var is faster than initial N.invisibility = INVISIBILITY_MAXIMUM - N.opacity = 0 + N.set_opacity(FALSE) diff --git a/code/datums/weather/weather_types.dm b/code/datums/weather/weather_types.dm deleted file mode 100644 index 1581938bd96..00000000000 --- a/code/datums/weather/weather_types.dm +++ /dev/null @@ -1,118 +0,0 @@ -//Different types of weather. - -/datum/weather/floor_is_lava //The Floor is Lava: Makes all turfs damage anyone on them unless they're standing on a solid object. - name = "the floor is lava" - desc = "The ground turns into surprisingly cool lava, lightly damaging anything on the floor." - - telegraph_message = "Waves of heat emanate from the ground..." - telegraph_duration = 150 - - weather_message = "The floor is lava! Get on top of something!" - weather_duration_lower = 300 - weather_duration_upper = 600 - weather_overlay = "lava" - - end_message = "The ground cools and returns to its usual form." - end_duration = 0 - - area_type = /area - target_z = MAIN_STATION - - overlay_layer = 2 //Covers floors only - immunity_type = "lava" - -/datum/weather/floor_is_lava/impact(mob/living/L) - for(var/obj/structure/O in L.loc) - if(O.density) - return - if(L.loc.density) - return - if(!L.client) //Only sentient people are going along with it! - return - L.adjustFireLoss(3) - -/datum/weather/floor_is_lava/fake - name = "fake lava" - aesthetic = TRUE - -/datum/weather/advanced_darkness //Advanced Darkness: Restricts the vision of all affected mobs to a single tile in the cardinal directions. - name = "advanced darkness" - desc = "Everything in the area is effectively blinded, unable to see more than a foot or so around itself." - - telegraph_message = "The lights begin to dim... is the power going out?" - telegraph_duration = 150 - - weather_message = "This isn't your everyday darkness... this is advanced darkness!" - weather_duration_lower = 300 - weather_duration_upper = 300 - - end_message = "At last, the darkness recedes." - end_duration = 0 - - area_type = /area - target_z = MAIN_STATION - -/datum/weather/advanced_darkness/update_areas() - for(var/V in impacted_areas) - var/area/A = V - if(stage == MAIN_STAGE) - A.invisibility = 0 - A.opacity = 1 - A.layer = overlay_layer - A.icon = 'icons/effects/weather_effects.dmi' - A.icon_state = "darkness" - else - A.invisibility = INVISIBILITY_MAXIMUM - A.opacity = 0 - - -/datum/weather/ash_storm //Ash Storms: Common happenings on lavaland. Heavily obscures vision and deals heavy fire damage to anyone caught outside. - name = "ash storm" - desc = "An intense atmospheric storm lifts ash off of the planet's surface and billows it down across the area, dealing intense fire damage to the unprotected." - - telegraph_message = "An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter." - telegraph_duration = 300 - telegraph_sound = 'sound/lavaland/ash_storm_windup.ogg' - telegraph_overlay = "light_ash" - - weather_message = "Smoldering clouds of scorching ash billow down around you! Get inside!" - weather_duration_lower = 600 - weather_duration_upper = 1500 - weather_sound = 'sound/lavaland/ash_storm_start.ogg' - weather_overlay = "ash_storm" - - end_message = "The shrieking wind whips away the last of the ash falls to its usual murmur. It should be safe to go outside now." - end_duration = 300 - end_sound = 'sound/lavaland/ash_storm_end.ogg' - end_overlay = "light_ash" - - area_type = /area/mine/dangerous - target_z = MINING - - immunity_type = "ash" - - probability = 90 - -/datum/weather/ash_storm/impact(mob/living/L) - if(istype(L.loc, /obj/mecha)) - return - if(ishuman(L)) - var/mob/living/carbon/human/H = L - var/thermal_protection = H.get_thermal_protection() - if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT) - return - L.adjustFireLoss(4) - -/datum/weather/ash_storm/emberfall //Emberfall: An ash storm passes by, resulting in harmless embers falling like snow. 10% to happen in place of an ash storm. - name = "emberfall" - desc = "A passing ash storm blankets the area in harmless embers." - - weather_message = "Gentle embers waft down around you like grotesque snow. The storm seems to have passed you by..." - weather_sound = 'sound/lavaland/ash_storm_windup.ogg' - weather_overlay = "light_ash" - - end_message = "The emberfall slows, stops. Another layer of hardened soot to the basalt beneath your feet." - - aesthetic = TRUE - - probability = 10 diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm new file mode 100644 index 00000000000..3f4c57c4196 --- /dev/null +++ b/code/datums/weather/weather_types/ash_storm.dm @@ -0,0 +1,108 @@ +//Ash storms happen frequently on lavaland. They heavily obscure vision, and cause high fire damage to anyone caught outside. +/datum/weather/ash_storm + name = "ash storm" + desc = "An intense atmospheric storm lifts ash off of the planet's surface and billows it down across the area, dealing intense fire damage to the unprotected." + + telegraph_message = "An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter." + telegraph_duration = 300 + telegraph_overlay = "light_ash" + + weather_message = "Smoldering clouds of scorching ash billow down around you! Get inside!" + weather_duration_lower = 600 + weather_duration_upper = 1200 + weather_overlay = "ash_storm" + + end_message = "The shrieking wind whips away the last of the ash and falls to its usual murmur. It should be safe to go outside now." + end_duration = 300 + end_overlay = "light_ash" + + area_type = /area/mine/dangerous // /area/lavaland/surface/outdoors + target_trait = ORE_LEVEL + + immunity_type = "ash" + +// probability = 90 + + barometer_predictable = TRUE + + var/datum/looping_sound/active_outside_ashstorm/sound_ao = new(list(), FALSE, TRUE) + var/datum/looping_sound/active_inside_ashstorm/sound_ai = new(list(), FALSE, TRUE) + var/datum/looping_sound/weak_outside_ashstorm/sound_wo = new(list(), FALSE, TRUE) + var/datum/looping_sound/weak_inside_ashstorm/sound_wi = new(list(), FALSE, TRUE) + +/datum/weather/ash_storm/telegraph() + . = ..() + var/list/inside_areas = list() + var/list/outside_areas = list() + var/list/eligible_areas = list() + for(var/z in impacted_z_levels) + eligible_areas += space_manager.areas_in_z["[z]"] + for(var/i in 1 to eligible_areas.len) + var/area/place = eligible_areas[i] + if(place.outdoors) + outside_areas += place + else + inside_areas += place + CHECK_TICK + + sound_ao.output_atoms = outside_areas + sound_ai.output_atoms = inside_areas + sound_wo.output_atoms = outside_areas + sound_wi.output_atoms = inside_areas + + sound_wo.start() + sound_wi.start() + +/datum/weather/ash_storm/start() + . = ..() + sound_wo.stop() + sound_wi.stop() + + sound_ao.start() + sound_ai.start() + +/datum/weather/ash_storm/wind_down() + . = ..() + sound_ao.stop() + sound_ai.stop() + + sound_wo.start() + sound_wi.start() + +/datum/weather/ash_storm/end() + . = ..() + sound_wo.stop() + sound_wi.stop() + +/datum/weather/ash_storm/proc/is_ash_immune(atom/L) + while(L && !isturf(L)) + if(ismecha(L)) //Mechs are immune + return TRUE + if(ishuman(L)) //Are you immune? + var/mob/living/carbon/human/H = L + var/thermal_protection = H.get_thermal_protection() + if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT) + return TRUE + L = L.loc //Matryoshka check + return FALSE //RIP you + +/datum/weather/ash_storm/weather_act(mob/living/L) + if(is_ash_immune(L)) + return + L.adjustFireLoss(4) + + +//Emberfalls are the result of an ash storm passing by close to the playable area of lavaland. They have a 10% chance to trigger in place of an ash storm. +/datum/weather/ash_storm/emberfall + name = "emberfall" + desc = "A passing ash storm blankets the area in harmless embers." + + weather_message = "Gentle embers waft down around you like grotesque snow. The storm seems to have passed you by..." + weather_overlay = "light_ash" + + end_message = "The emberfall slows, stops. Another layer of hardened soot to the basalt beneath your feet." + end_sound = null + + aesthetic = TRUE + +// probability = 10 \ No newline at end of file diff --git a/code/datums/weather/weather_types/floor_is_lava.dm b/code/datums/weather/weather_types/floor_is_lava.dm new file mode 100644 index 00000000000..fe7391ec9f0 --- /dev/null +++ b/code/datums/weather/weather_types/floor_is_lava.dm @@ -0,0 +1,39 @@ +//Causes fire damage to anyone not standing on a dense object. +/datum/weather/floor_is_lava + name = "the floor is lava" + desc = "The ground turns into surprisingly cool lava, lightly damaging anything on the floor." + + telegraph_message = "You feel the ground beneath you getting hot. Waves of heat distort the air." + telegraph_duration = 150 + + weather_message = "The floor is lava! Get on top of something!" + weather_duration_lower = 300 + weather_duration_upper = 600 + weather_overlay = "lava" + + end_message = "The ground cools and returns to its usual form." + end_duration = 0 + + area_type = /area + protected_areas = list(/area/space) + target_trait = STATION_LEVEL + + overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only + immunity_type = "lava" + + +/datum/weather/floor_is_lava/weather_act(mob/living/L) + if(issilicon(L)) + return + for(var/obj/structure/O in L.loc) + if(O.density || O.buckled_mob && istype(O, /obj/structure/stool/bed)) + return + if(L.loc.density) + return + if(!L.client) //Only sentient people are going along with it! + return + L.adjustFireLoss(3) + +/datum/weather/floor_is_lava/fake + name = "the floor is lava (fake)" + aesthetic = TRUE \ No newline at end of file diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm new file mode 100644 index 00000000000..acd155e7560 --- /dev/null +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -0,0 +1,61 @@ +//Radiation storms occur when the station passes through an irradiated area, and irradiate anyone not standing in protected areas (maintenance, emergency storage, etc.) +/datum/weather/rad_storm + name = "radiation storm" + desc = "A cloud of intense radiation passes through the area dealing rad damage to those who are unprotected." + + telegraph_duration = 400 + telegraph_message = "The air begins to grow warm." + + weather_message = "You feel waves of heat wash over you! Find shelter!" + weather_overlay = "ash_storm" + weather_duration_lower = 600 + weather_duration_upper = 1500 + weather_color = "green" + weather_sound = 'sound/misc/bloblarm.ogg' + + end_duration = 100 + end_message = "The air seems to be cooling off again." + + area_type = /area + protected_areas = list(/area/maintenance, /area/turret_protected/ai_upload, /area/turret_protected/ai_upload_foyer, + /area/turret_protected/ai, /area/storage/emergency, /area/storage/emergency2, /area/crew_quarters/sleep, /area/security/brig, /area/shuttle) + target_trait = STATION_LEVEL + + immunity_type = "rad" + +/datum/weather/rad_storm/telegraph() + ..() + status_alarm(TRUE) + make_maint_all_access() + + +/datum/weather/rad_storm/weather_act(mob/living/L) + var/resist = L.getarmor(null, "rad") + if(prob(40)) + if(ishuman(L)) + var/mob/living/carbon/human/H = L + if(!(RADIMMUNE in H.species.species_traits)) + if(prob(max(0, 100 - resist))) + randmuti(H) // Applies bad mutation + if(prob(50)) + if(prob(90)) + randmutb(H) + else + randmutg(H) + domutcheck(H, null, 1) + + L.apply_effect(20, IRRADIATE, resist) + +/datum/weather/rad_storm/end() + if(..()) + return + priority_announcement.Announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert") + status_alarm(FALSE) + revoke_maint_all_access() + +/datum/weather/rad_storm/proc/status_alarm(active) //Makes the status displays show the radiation warning for those who missed the announcement. + if(active) + post_status("alert", "radiation") + else + post_status("blank") + post_status("shuttle") \ No newline at end of file diff --git a/code/datums/weather/weather_types/snow_storm.dm b/code/datums/weather/weather_types/snow_storm.dm new file mode 100644 index 00000000000..39ad0e8fa5d --- /dev/null +++ b/code/datums/weather/weather_types/snow_storm.dm @@ -0,0 +1,28 @@ +/datum/weather/snow_storm + name = "snow storm" + desc = "Harsh snowstorms roam the topside of this arctic planet, burying any area unfortunate enough to be in its path." + probability = 90 + + telegraph_message = "Drifting particles of snow begin to dust the surrounding area.." + telegraph_duration = 300 + telegraph_overlay = "light_snow" + + weather_message = "Harsh winds pick up as dense snow begins to fall from the sky! Seek shelter!" + weather_overlay = "snow_storm" + weather_duration_lower = 600 + weather_duration_upper = 1500 + + end_duration = 100 + end_message = "The snowfall dies down, it should be safe to go outside again." + +// area_type = /area/awaymission/snowdin/outside + target_trait = AWAY_LEVEL + + immunity_type = "snow" + + barometer_predictable = TRUE + + +/datum/weather/snow_storm/weather_act(mob/living/L) + L.adjust_bodytemperature(-rand(5, 15)) + diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 6434bdf92b5..f0524485357 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -20,13 +20,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station var/atmosalm = ATMOS_ALARM_NONE var/poweralm = 1 var/party = null - var/radalert = 0 var/report_alerts = 1 // Should atmos alerts notify the AI/computers level = null name = "Space" icon = 'icons/turf/areas.dmi' icon_state = "unknown" - layer = 10 + layer = AREA_LAYER luminosity = 0 mouse_opacity = 0 invisibility = INVISIBILITY_LIGHTING @@ -141,9 +140,6 @@ var/list/ghostteleportlocs = list() /area/space/readyalert() return -/area/space/radiation_alert() - return - /area/space/partyalert() return diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 8a9a108c7b3..44a9ae7e522 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -22,7 +22,7 @@ ..() icon_state = "" - layer = 10 + layer = AREA_LAYER uid = ++global_uid all_areas += src map_name = name // Save the initial (the name set in the map) name of the area. @@ -45,7 +45,24 @@ blend_mode = BLEND_MULTIPLY // Putting this in the constructor so that it stops the icons being screwed up in the map editor. /area/Initialize() - ..() + . = ..() + + if(contents.len) + var/list/areas_in_z = space_manager.areas_in_z + var/z + for(var/i in 1 to contents.len) + var/atom/thing = contents[i] + if(!thing) + continue + z = thing.z + break + if(!z) + WARNING("No z found for [src]") + return + if(!areas_in_z["[z]"]) + areas_in_z["[z]"] = list() + areas_in_z["[z]"] += src + return INITIALIZE_HINT_LATELOAD /area/LateInitialize() @@ -160,16 +177,6 @@ eject = 0 updateicon() -/area/proc/radiation_alert() - if(!radalert) - radalert = 1 - updateicon() - -/area/proc/reset_radiation_alert() - if(radalert) - radalert = 0 - updateicon() - /area/proc/partyalert() if(!party) party = 1 @@ -183,11 +190,8 @@ updateicon() /area/proc/updateicon() - if(radalert) // always show the radiation alert, regardless of power - icon_state = "radiation" - invisibility = INVISIBILITY_LIGHTING - else if((fire || eject || party) && (!requires_power||power_environ))//If it doesn't require power, can still activate this proc. - if(fire && !radalert && !eject && !party) + if((fire || eject || party) && (!requires_power||power_environ))//If it doesn't require power, can still activate this proc. + if(fire && !eject && !party) icon_state = "red" else if(!fire && eject && !party) icon_state = "red" @@ -197,9 +201,15 @@ icon_state = "blue-red" invisibility = INVISIBILITY_LIGHTING else - // new lighting behaviour with obj lights - icon_state = null - invisibility = INVISIBILITY_MAXIMUM + var/weather_icon + for(var/V in SSweather.processing) + var/datum/weather/W = V + if(W.stage != END_STAGE && (src in W.impacted_areas)) + W.update_areas() + weather_icon = TRUE + if(!weather_icon) + icon_state = null + invisibility = INVISIBILITY_MAXIMUM /area/space/updateicon() icon_state = null @@ -384,4 +394,4 @@ for(var/obj/machinery/door/airlock/temp_airlock in src) temp_airlock.prison_open() for(var/obj/machinery/door/window/temp_windoor in src) - temp_windoor.open() + temp_windoor.open() \ No newline at end of file diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm index 93fe05ffa10..eb32bed006d 100644 --- a/code/game/gamemodes/autotraitor/autotraitor.dm +++ b/code/game/gamemodes/autotraitor/autotraitor.dm @@ -191,7 +191,7 @@ //message_admins("The probability of a new traitor is [traitor_prob]%") if(prob(traitor_prob)) message_admins("New traitor roll passed. Making a new Traitor.") - character.mind.make_Tratior() //TEMP: Add proper checks for loyalty here. uc_guy + character.mind.make_Traitor() //TEMP: Add proper checks for loyalty here. uc_guy //else //message_admins("New traitor roll failed. No new traitor.") //else diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm index d690f095236..a7af2b94482 100644 --- a/code/game/gamemodes/changeling/evolution_menu.dm +++ b/code/game/gamemodes/changeling/evolution_menu.dm @@ -20,7 +20,7 @@ var/list/sting_paths /obj/effect/proc_holder/changeling/evolution_menu/proc/create_menu(var/datum/changeling/changeling) var/dat - dat +="Changling Evolution Menu" + dat +="Changeling Evolution Menu" //javascript, the part that does most of the work~ dat += {" diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 23efc38b403..b3881ee54fb 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -24,13 +24,13 @@ user.CureNearsighted() user.reagents.clear_reagents() user.germ_level = 0 - user.next_pain_time = 0 user.timeofdeath = 0 if(ishuman(user)) var/mob/living/carbon/human/H = user H.restore_blood() H.traumatic_shock = 0 H.shock_stage = 0 + H.next_pain_time = 0 H.species.create_organs(H) // Now that recreating all organs is necessary, the rest of this organ stuff probably // isn't, but I don't want to remove it, just in case. diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index d8d7d03b6c4..84941f4d7a7 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -161,7 +161,7 @@ var/obj/item/organ/external/head/head = C.get_organ("head") if(head) C.apply_damage(30, BURN, "head") //30 fire damage because it's FUCKING LAVA - head.disfigure("burn") //Your face is unrecognizable because it's FUCKING LAVA + head.disfigure() //Your face is unrecognizable because it's FUCKING LAVA return 1 else ..() diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index e014fa07785..087bfbb4008 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -1,4 +1,4 @@ -/var/list/sacrificed = list() +var/list/sacrificed = list() var/list/non_revealed_runes = (subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed) /* @@ -153,7 +153,10 @@ structure_check() searches for nearby cultist structures required for the invoca for(var/M in invokers) var/mob/living/L = M if(invocation) - L.say(invocation) + if(!L.IsVocal()) + L.emote("gestures ominously.") + else + L.say(invocation) L.changeNext_move(CLICK_CD_MELEE)//THIS IS WHY WE CAN'T HAVE NICE THINGS if(invoke_damage) L.apply_damage(invoke_damage, BRUTE) @@ -473,7 +476,6 @@ var/list/teleport_runes = list() rune_in_use = 0 - //Ritual of Dimensional Rending: Calls forth the avatar of Nar-Sie upon the station. /obj/effect/rune/narsie cultist_name = "Tear Reality (God)" @@ -875,7 +877,7 @@ var/list/teleport_runes = list() fail_invoke() log_game("Summon Cultist rune failed - target in away mission") return - if((cultist_to_summon.reagents.has_reagent("holywater") || cultist_to_summon.restrained()) && invokers < 3) + if((cultist_to_summon.reagents.has_reagent("holywater") || cultist_to_summon.restrained()) && invokers.len < 3) to_chat(user, "The summoning of [cultist_to_summon] is being blocked somehow! You need 3 chanters to counter it!") fail_invoke() new /obj/effect/temp_visual/cult/sparks(get_turf(cultist_to_summon)) //observer warning diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm index ae9b8e3945a..14ba6fb9dd0 100644 --- a/code/game/gamemodes/vampire/vampire.dm +++ b/code/game/gamemodes/vampire/vampire.dm @@ -279,7 +279,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha to_chat(owner, "[owner.wear_mask] prevents you from biting [H]!") draining = null return - add_attack_logs(owner, H, "vampirebit & is draining their blood.", FALSE) + add_attack_logs(owner, H, "vampirebit & is draining their blood.", ATKLOG_ALMOSTALL) owner.visible_message("[owner] grabs [H]'s neck harshly and sinks in [owner.p_their()] fangs!", "You sink your fangs into [H] and begin to drain [owner.p_their()] blood.", "You hear a soft puncture and a wet sucking noise.") if(!iscarbon(owner)) H.LAssailant = null diff --git a/code/game/jobs/job_scaling.dm b/code/game/jobs/job_scaling.dm new file mode 100644 index 00000000000..7d8804783f1 --- /dev/null +++ b/code/game/jobs/job_scaling.dm @@ -0,0 +1,11 @@ +/hook/roundstart/proc/jobscaling() + sleep(10 SECONDS) // give everyone time to finish spawning, and the lag to die down + var/playercount = length(clients) + var/highpop_trigger = 80 + + if(playercount >= highpop_trigger) + log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - loading highpop job config"); + job_master.LoadJobs("config/jobs_highpop.txt") + else + log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - keeping standard job config"); + return 1 \ No newline at end of file diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index dd0231982d3..f24197009bd 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -118,6 +118,8 @@ var/report_danger_level = 1 + var/automatic_emergency = 1 //Does the alarm automaticly respond to an emergency condition + /obj/machinery/alarm/monitor report_danger_level = 0 @@ -306,7 +308,7 @@ if(old_danger_level!=danger_level) apply_danger_level() - if(mode == AALARM_MODE_SCRUBBING && danger_level == ATMOS_ALARM_DANGER) + if(automatic_emergency && mode == AALARM_MODE_SCRUBBING && danger_level == ATMOS_ALARM_DANGER) if(pressure_dangerlevel == ATMOS_ALARM_DANGER) mode = AALARM_MODE_OFF if(temperature_dangerlevel == ATMOS_ALARM_DANGER && cur_tlv.max2 <= environment.temperature) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index fa582362308..054d4d441a3 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -528,7 +528,8 @@ if("alert") status_signal.data["picture_state"] = data1 - frequency.post_signal(src, status_signal) + spawn(0) + frequency.post_signal(src, status_signal) /obj/machinery/computer/communications/Destroy() diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index 98d14c8ac30..4cbf105c100 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -205,8 +205,8 @@ if(href_list["dstele"]) var/choices = list(0) var/list/reachable_levels = levels_by_trait(REACHABLE) - for(var/datum/space_level/S in reachable_levels) - choices += S.zpos + for(var/z in reachable_levels) + choices += z var/obj/machinery/computer/pod/deathsquad/D = src var/input = input("Enter the destination Z-Level. The mechs will arrive from the East. Leave 0 if you don't want to set a specific ZLevel", "Mass Driver Controls", 0) in choices D.teleporter_dest = input diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 678e29d3ae0..db508b9288f 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -10,8 +10,6 @@ usesound = 'sound/items/Deconstruct.ogg' var/list/conf_access = null var/one_access = 0 //if set to 1, door would receive req_one_access instead of req_access - var/last_configurator = null - var/locked = TRUE var/const/max_brain_damage = 60 // Maximum brain damage a mob can have until it can't use the electronics /obj/item/airlock_electronics/attack_self(mob/user) @@ -26,31 +24,23 @@ var/t1 = text("Access control
\n") - if(last_configurator) - t1 += "Operator: [last_configurator]
" + t1 += "Access requirement is set to " + t1 += one_access ? "ONE
" : "ALL
" - if(locked) - t1 += "Swipe ID
" - else - t1 += "Block
" + t1 += conf_access == null ? "All
" : "All
" - t1 += "Access requirement is set to " - t1 += one_access ? "ONE
" : "ALL
" + t1 += "
" - t1 += conf_access == null ? "All
" : "All
" + var/list/accesses = get_all_accesses() + for(var/acc in accesses) + var/aname = get_access_desc(acc) - t1 += "
" - - var/list/accesses = get_all_accesses() - for(var/acc in accesses) - var/aname = get_access_desc(acc) - - if(!conf_access || !conf_access.len || !(acc in conf_access)) - t1 += "[aname]
" - else if(one_access) - t1 += "[aname]
" - else - t1 += "[aname]
" + if(!conf_access || !conf_access.len || !(acc in conf_access)) + t1 += "[aname]
" + else if(one_access) + t1 += "[aname]
" + else + t1 += "[aname]
" t1 += "

Close

\n" @@ -66,20 +56,9 @@ return 1 if(href_list["close"]) - usr << browse(null, "window=airlock") + usr << browse(null, "window=airlock_electronics") return - if(href_list["login"]) - if(allowed(usr)) - locked = FALSE - last_configurator = usr.name - - if(locked) - return - - if(href_list["logout"]) - locked = TRUE - if(href_list["one_access"]) one_access = !one_access diff --git a/code/game/machinery/poolcontroller.dm b/code/game/machinery/poolcontroller.dm index 6c10129c6ea..de5552e6a75 100644 --- a/code/game/machinery/poolcontroller.dm +++ b/code/game/machinery/poolcontroller.dm @@ -100,7 +100,7 @@ if(drownee.losebreath > 20) //You've probably got bigger problems than drowning at this point, so we won't add to it until you get that under control. return - add_attack_logs(src, drownee, "Drowned", isLivingSSD(drownee)) + add_attack_logs(src, drownee, "Drowned", isLivingSSD(drownee) ? null : ATKLOG_ALL) if(drownee.stat) //Mob is in critical. drownee.AdjustLoseBreath(3, bound_lower = 0, bound_upper = 20) drownee.visible_message("\The [drownee] appears to be drowning!","You're quickly drowning!") //inform them that they are fucked. diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index c640d5d5554..247a40a3425 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -230,7 +230,7 @@ var/turf/bombturf = get_turf(src) var/area/A = get_area(bombturf) if(payload && !istype(payload, /obj/item/bombcore/training)) - msg_admin_attack("[key_name_admin(user)] has primed a [name] ([payload]) for detonation at [A.name] (JMP).") + msg_admin_attack("[key_name_admin(user)] has primed a [name] ([payload]) for detonation at [A.name] (JMP).", ATKLOG_FEW) log_game("[key_name(user)] has primed a [name] ([payload]) for detonation at [A.name] [COORD(bombturf)]") investigate_log("[key_name(user)] has has primed a [name] ([payload]) for detonation at [A.name] [COORD(bombturf)]", INVESTIGATE_BOMB) payload.adminlog = "\The [src] that [key_name(user)] had primed detonated!" diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 48384f78f1e..64e387fb731 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -156,8 +156,26 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency, signal.data["verb"], signal.data["language"]) - - +#define CREW_RADIO_TYPE 0 +#define CENTCOMM_RADIO_TYPE 1 +#define SYNDICATE_RADIO_TYPE 2 +/proc/Is_Bad_Connection(old_freq, new_freq) //Makes sure players cant read radios of a higher level than they are + var/old_type = CREW_RADIO_TYPE + var/new_type = CREW_RADIO_TYPE + for(var/antag_freq in ANTAG_FREQS) + if(old_freq == antag_freq) + old_type = SYNDICATE_RADIO_TYPE + if(new_freq == antag_freq) + new_type = SYNDICATE_RADIO_TYPE + + for(var/cent_freq in CENT_FREQS) + if(old_freq == cent_freq) + old_type = CENTCOMM_RADIO_TYPE + if(new_freq == cent_freq) + new_type = CENTCOMM_RADIO_TYPE + + return new_type > old_type + /** Here is the big, bad function that broadcasts a message given the appropriate @@ -226,21 +244,28 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept var/display_freq = freq + var/bad_connection = FALSE + var/datum/radio_frequency/new_connection = connection + + if(connection.frequency != display_freq) + bad_connection = Is_Bad_Connection(connection.frequency, display_freq) + new_connection = radio_controller.return_frequency(display_freq) + var/list/obj/item/radio/radios = list() // --- Broadcast only to intercom devices --- - if(data == 1) + if(data == 1 && !bad_connection) - for(var/obj/item/radio/intercom/R in connection.devices["[RADIO_CHAT]"]) + for(var/obj/item/radio/intercom/R in new_connection.devices["[RADIO_CHAT]"]) if(R.receive_range(display_freq, level) > -1) radios += R // --- Broadcast only to intercoms and station-bounced radios --- - else if(data == 2) + else if(data == 2 && !bad_connection) - for(var/obj/item/radio/R in connection.devices["[RADIO_CHAT]"]) + for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"]) if(istype(R, /obj/item/radio/headset)) continue @@ -259,9 +284,9 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept // --- Broadcast to ALL radio devices --- - else + else if(!bad_connection) - for(var/obj/item/radio/R in connection.devices["[RADIO_CHAT]"]) + for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"]) if(R.receive_range(display_freq, level) > -1) radios += R diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 9dc30edf61e..0b9b1449137 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -436,7 +436,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() var/totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes) var/list/memory = list() // stored memory - var/rawcode = "" // the code to compile (raw text) + var/list/rawcode = list() // the code to compile (list of characters) var/datum/TCS_Compiler/Compiler // the compiler that compiles and runs the code var/autoruncode = 0 // 1 if the code is set to run every time a signal is picked up @@ -516,10 +516,9 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() relay_information(signal, "/obj/machinery/telecomms/broadcaster") -/obj/machinery/telecomms/server/proc/setcode(var/t) - if(t) - if(istext(t)) - rawcode = t +/obj/machinery/telecomms/server/proc/setcode(var/list/code) + if(istype(code)) + rawcode = code /obj/machinery/telecomms/server/proc/compile(mob/user as mob) if(Compiler) @@ -548,8 +547,8 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() /obj/machinery/telecomms/server/proc/admin_log(var/mob/mob) var/msg="[key_name(mob)] has compiled a script to server [src]:" log_game("NTSL: [msg]") - log_game("NTSL: [rawcode]") - src.investigate_log("[msg]
[rawcode]", "ntsl") + log_game("NTSL: [rawcode.Join("")]") + src.investigate_log("[msg]
[rawcode.Join("")]", "ntsl") if(length(rawcode)) // Let's not bother the admins for empty code. message_admins("[key_name_admin(mob)] has compiled and uploaded a NTSL script to [src.id] (JMP)") diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm index a2580285a38..45f0817ef55 100644 --- a/code/game/machinery/telecomms/traffic_control.dm +++ b/code/game/machinery/telecomms/traffic_control.dm @@ -117,6 +117,7 @@ function compileCode() { var codeText = cMirror_fSubmit.getValue(); document.getElementById("cMirrorPost").value = codeText; + document.getElementById("cMirrorPostList").value = JSON.stringify(codeText.split('')); document.getElementById("theform").submit(); } @@ -135,6 +136,7 @@ + "} else @@ -189,6 +191,10 @@ if(code) storedcode = code + var/list/codelist = href_list["cMirrorList"] + if(istext(codelist)) + codelist = json_decode(codelist) + add_fingerprint(user) user.set_machine(src) @@ -198,14 +204,14 @@ switch(href_list["choice"]) if("Compile") - if(!code) + if(!istype(codelist)) return 0 if(user != editingcode) return 0 //only one editor if(SelectedServer) var/obj/machinery/telecomms/server/Server = SelectedServer - Server.setcode(code) + Server.setcode(codelist) spawn(0) // Output all the compile-time errors @@ -234,7 +240,7 @@ updateUsrDialog() for(var/obj/machinery/telecomms/server/Server in servers) - Server.setcode(code) + Server.setcode(codelist) var/list/compileerrors = Server.compile(user) if(!telecomms_check(user)) return diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index fb8b8fb0f32..f7b2e8bbd05 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -836,6 +836,9 @@ /obj/item/reagent_containers/food/drinks/chicken_soup = 30,/obj/item/reagent_containers/food/drinks/weightloss = 50, /obj/item/reagent_containers/food/drinks/mug = 50) refill_canister = /obj/item/vending_refill/coffee +/obj/machinery/vending/coffee/free + prices = list() + /obj/machinery/vending/coffee/New() ..() component_parts = list() @@ -888,6 +891,9 @@ /obj/item/reagent_containers/food/snacks/pistachios = 35, /obj/item/reagent_containers/food/snacks/spacetwinkie = 30,/obj/item/reagent_containers/food/snacks/cheesiehonkers = 25,/obj/item/reagent_containers/food/snacks/tastybread = 30) refill_canister = /obj/item/vending_refill/snack +/obj/machinery/vending/snack/free + prices = list() + /obj/machinery/vending/snack/New() ..() component_parts = list() @@ -909,6 +915,9 @@ /obj/item/reagent_containers/food/snacks/chinese/rice = 50) refill_canister = /obj/item/vending_refill/chinese +/obj/machinery/vending/chinese/free + prices = list() + /obj/machinery/vending/chinese/New() ..() component_parts = list() @@ -934,6 +943,9 @@ /obj/item/reagent_containers/food/drinks/cans/space_up = 20,/obj/item/reagent_containers/food/drinks/cans/grape_juice = 20) refill_canister = /obj/item/vending_refill/cola +/obj/machinery/vending/cola/free + prices = list() + /obj/machinery/vending/cola/New() ..() component_parts = list() @@ -961,6 +973,9 @@ /obj/item/cartridge/signal = 75) armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0) +/obj/machinery/vending/cart/free + prices = list() + /obj/machinery/vending/liberationstation name = "\improper Liberation Station" desc = "An overwhelming amount of ancient patriotism washes over you just by looking at the machine." @@ -990,6 +1005,9 @@ prices = list(/obj/item/storage/fancy/cigarettes = 60,/obj/item/storage/fancy/cigarettes/cigpack_uplift = 60,/obj/item/storage/fancy/cigarettes/cigpack_robust = 60,/obj/item/storage/fancy/cigarettes/cigpack_carp = 60,/obj/item/storage/fancy/cigarettes/cigpack_midori = 60,/obj/item/storage/fancy/cigarettes/cigpack_random = 150, /obj/item/reagent_containers/food/pill/patch/nicotine = 15, /obj/item/storage/box/matches = 10,/obj/item/lighter/random = 60, /obj/item/storage/fancy/rollingpapers = 20) refill_canister = /obj/item/vending_refill/cigarette +/obj/machinery/vending/cigarette/free + prices = list() + /obj/machinery/vending/cigarette/New() ..() component_parts = list() @@ -1429,6 +1447,9 @@ premium = list(/obj/item/toy/pet_rock/fred = 1, /obj/item/toy/pet_rock/roxie = 1) refill_canister = /obj/item/vending_refill/crittercare +/obj/machinery/vending/crittercare/free + prices = list() + /obj/machinery/vending/crittercare/New() ..() component_parts = list() diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm index 217b1e70165..248514179af 100644 --- a/code/game/machinery/wishgranter.dm +++ b/code/game/machinery/wishgranter.dm @@ -1,62 +1,42 @@ /obj/machinery/wish_granter - name = "Wish Granter" + name = "wish granter" desc = "You're not so sure about this, anymore..." icon = 'icons/obj/device.dmi' icon_state = "syndbeacon" - use_power = 0 - anchored = 1 - density = 1 - var/datum/mind/target - var/list/types = list() - var/inuse = 0 + use_power = NO_POWER_USE + anchored = TRUE + density = TRUE -/obj/machinery/wish_granter/New() - for(var/supname in all_superheroes) - types |= supname - ..() + var/charges = 1 + var/insisting = FALSE -/obj/machinery/wish_granter/attack_hand(var/mob/user as mob) - usr.set_machine(src) +/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user) + . = ..() + if(.) + return + if(charges <= 0) + to_chat(user, "The Wish Granter lies silent.") + return - if(!istype(user, /mob/living/carbon/human)) + else if(!ishuman(user)) to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.") return - if(is_special_character(user)) + else if(is_special_character(user)) to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.") - return - if(inuse) - to_chat(user, "Someone is already communing with the Wish Granter.") - return + else if(!insisting) + to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?") + insisting = TRUE - to_chat(user, "The power of the Wish Granter have turned you into the superhero the station deserves. You are a masked vigilante, and answer to no man. Will you use your newfound strength to protect the innocent, or will you hunt the guilty?") - - inuse = 1 - var/wish - if(types.len == 1) - wish = pick(types) else - wish = input("You want to become...","Wish") as null|anything in types - if(!wish) - inuse=0 - return - types -= wish - var/mob/living/carbon/human/M = user - var/datum/superheroes/S = all_superheroes[wish] - if(S) - S.create(M) - inuse=0 + to_chat(user, "You speak. [pick("I want the station to disappear", "Humanity is corrupt, mankind must be destroyed", "I want to be rich", "I want to rule the world", "I want immortality.")]. The Wish Granter answers.") + to_chat(user, "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.") - //Remove the wishgranter or teleport it randomly on the station - if(!types.len) - to_chat(user, "The wishgranter slowly fades into mist...") - qdel(src) - return - else - var/impact_area = findEventArea() - var/turf/T = pick(get_area_turfs(impact_area)) - if(T) - src.loc = T - return \ No newline at end of file + charges-- + insisting = FALSE + + user.mind.add_antag_datum(/datum/antagonist/wishgranter) + + to_chat(user, "You have a very bad feeling about this.") \ No newline at end of file diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm index 385067e0611..1df0166260e 100644 --- a/code/game/objects/effects/effect_system/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/effects_smoke.dm @@ -263,13 +263,13 @@ var/more = "" if(M) more = " " - msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1) + msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", ATKLOG_FEW) log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].") else - msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", 0, 1) + msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", ATKLOG_FEW) log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.") else - msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key. CODERS: carry.my_atom may be null.", 0, 1) + msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key. CODERS: carry.my_atom may be null.", ATKLOG_FEW) log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key. CODERS: carry.my_atom may be null.") /datum/effect_system/smoke_spread/chem/start(effect_range = 2) diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 291f0fd7b2a..737abd10bb1 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -83,7 +83,7 @@ if(href_list["wipe"]) var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No") if(confirm == "Yes" && (CanUseTopic(user, state) == STATUS_INTERACTIVE)) - msg_admin_attack("[key_name_admin(user)] wiped [key_name_admin(AI)] with \the [src].") + msg_admin_attack("[key_name_admin(user)] wiped [key_name_admin(AI)] with \the [src].", ATKLOG_FEW) add_attack_logs(user, AI, "Wiped with [src].") flush = 1 AI.suiciding = 1 diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 2a8e155dd06..9912957c2bb 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -313,6 +313,9 @@ REAGENT SCANNER throw_range = 7 materials = list(MAT_METAL=30, MAT_GLASS=20) origin_tech = "magnets=1;engineering=1" + var/cooldown = FALSE + var/cooldown_time = 250 + var/accuracy // 0 is the best accuracy. /obj/item/analyzer/attack_self(mob/user as mob) @@ -366,6 +369,69 @@ REAGENT SCANNER src.add_fingerprint(user) return +/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens + ..() + + if(!user.incapacitated() && Adjacent(user)) + + if(cooldown) + to_chat(user, "[src]'s barometer function is prepraring itself.") + return + + var/turf/T = get_turf(user) + if(!T) + return + + playsound(src, 'sound/effects/pop.ogg', 100) + var/area/user_area = T.loc + var/datum/weather/ongoing_weather = null + + if(!user_area.outdoors) + to_chat(user, "[src]'s barometer function won't work indoors!") + return + + for(var/V in SSweather.processing) + var/datum/weather/W = V + if(W.barometer_predictable && (T.z in W.impacted_z_levels) && W.area_type == user_area.type && !(W.stage == END_STAGE)) + ongoing_weather = W + break + + if(ongoing_weather) + if((ongoing_weather.stage == MAIN_STAGE) || (ongoing_weather.stage == WIND_DOWN_STAGE)) + to_chat(user, "[src]'s barometer function can't trace anything while the storm is [ongoing_weather.stage == MAIN_STAGE ? "already here!" : "winding down."]") + return + + to_chat(user, "The next [ongoing_weather] will hit in [butchertime(ongoing_weather.next_hit_time - world.time)].") + if(ongoing_weather.aesthetic) + to_chat(user, "[src]'s barometer function says that the next storm will breeze on by.") + else + var/next_hit = SSweather.next_hit_by_zlevel["[T.z]"] + var/fixed = next_hit ? next_hit - world.time : -1 + if(fixed < 0) + to_chat(user, "[src]'s barometer function was unable to trace any weather patterns.") + else + to_chat(user, "[src]'s barometer function says a storm will land in approximately [butchertime(fixed)].") + cooldown = TRUE + addtimer(CALLBACK(src,/obj/item/analyzer/proc/ping), cooldown_time) + +/obj/item/analyzer/proc/ping() + if(isliving(loc)) + var/mob/living/L = loc + to_chat(L, "[src]'s barometer function is ready!") + playsound(src, 'sound/machines/click.ogg', 100) + cooldown = FALSE + +/obj/item/analyzer/proc/butchertime(amount) + if(!amount) + return + if(accuracy) + var/inaccurate = round(accuracy * (1 / 3)) + if(prob(50)) + amount -= inaccurate + if(prob(50)) + amount += inaccurate + return DisplayTimeText(max(1, amount)) + /obj/item/mass_spectrometer desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample. Inject sample with syringe." name = "mass-spectrometer" diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index 84bad81c015..dbd7701ce93 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -64,7 +64,7 @@ A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb). investigate_log("[key_name(user)] attached a [A] to a transfer valve.", INVESTIGATE_BOMB) - msg_admin_attack("[key_name_admin(user)]attached [A] to a transfer valve.") + msg_admin_attack("[key_name_admin(user)]attached [A] to a transfer valve.", ATKLOG_FEW) log_game("[key_name_admin(user)] attached [A] to a transfer valve.") attacher = user SSnanoui.update_uis(src) // update all UIs attached to src diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index d120fb4e1cd..3a8bf12b143 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -142,7 +142,7 @@ else to_chat(user, "You inject yourself with [src].") - add_attack_logs(user, M, attack_log, FALSE) + add_attack_logs(user, M, attack_log, ATKLOG_ALL) if(!iscarbon(user)) M.LAssailant = null else diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index 9bf760aee29..4896f2cfb60 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -403,6 +403,7 @@ icon_state = "AquaticKit" throw_speed = 2 throw_range = 8 + med_bot_skin = "fish" /obj/item/storage/firstaid/aquatic_kit/full desc = "It's a starter kit for an acquarium; includes 1 tank brush, 1 egg scoop, 1 fish net, and 1 container of fish food." diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index 34e350e3d50..ddc8b79012f 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -21,6 +21,8 @@ var/treatment_fire = "salglu_solution" var/treatment_tox = "charcoal" var/treatment_virus = "spaceacillin" + var/med_bot_skin = null + var/syndicate_aligned = FALSE /obj/item/storage/firstaid/fire @@ -28,6 +30,7 @@ desc = "A medical kit that contains several medical patches and pills for treating burns. Contains one epinephrine syringe for emergency use and a health analyzer." icon_state = "ointment" item_state = "firstaid-ointment" + med_bot_skin = "ointment" New() ..() @@ -68,6 +71,7 @@ desc = "A medical kit designed to counter poisoning by common toxins. Contains three pills and syringes, and a health analyzer to determine the health of the patient." icon_state = "antitoxin" item_state = "firstaid-toxin" + med_bot_skin = "tox" New() ..() @@ -92,6 +96,7 @@ desc = "A first aid kit that contains four pills of salbutamol, which is able to counter injuries caused by suffocation. Also contains a health analyzer to determine the health of the patient." icon_state = "o2" item_state = "firstaid-o2" + med_bot_skin = "o2" New() ..() @@ -111,6 +116,7 @@ desc = "A medical kit that contains several medical patches and pills for treating brute injuries. Contains one epinephrine syringe for emergency use and a health analyzer." icon_state = "brute" item_state = "firstaid-brute" + med_bot_skin = "brute" New() ..() @@ -135,6 +141,7 @@ desc = "Contains advanced medical treatments." icon_state = "advfirstaid" item_state = "firstaid-advanced" + med_bot_skin = "adv" /obj/item/storage/firstaid/adv/New() ..() @@ -157,10 +164,12 @@ desc = "I hope you've got insurance." max_w_class = WEIGHT_CLASS_NORMAL treatment_oxy = "perfluorodecalin" - treatment_brute = "styptic_powder" - treatment_fire = "silver_sulfadiazine" + treatment_brute = "bicaridine" + treatment_fire = "kelotane" treatment_tox = "charcoal" req_one_access =list(access_syndicate) + med_bot_skin = "bezerk" + syndicate_aligned = TRUE /obj/item/storage/firstaid/tactical/New() ..() diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 953536f1149..8de83f6344a 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -23,19 +23,20 @@ * Twohanded */ /obj/item/twohanded - var/wielded = 0 + var/wielded = FALSE var/force_unwielded = 0 var/force_wielded = 0 var/wieldsound = null var/unwieldsound = null /obj/item/twohanded/proc/unwield(mob/living/carbon/user) - if(!wielded || !user) return - wielded = 0 + if(!wielded || !user) + return + wielded = FALSE force = force_unwielded var/sf = findtext(name," (Wielded)") if(sf) - name = copytext(name,1,sf) + name = copytext(name, 1, sf) else //something wrong name = "[initial(name)]" update_icon() @@ -45,16 +46,16 @@ if(isrobot(user)) to_chat(user, "You free up your module.") else - to_chat(user, "You are now carrying the [name] with one hand.") + to_chat(user, "You are now carrying [name] with one hand.") if(unwieldsound) playsound(loc, unwieldsound, 50, 1) var/obj/item/twohanded/offhand/O = user.get_inactive_hand() if(O && istype(O)) O.unwield() - return /obj/item/twohanded/proc/wield(mob/living/carbon/user) - if(wielded) return + if(wielded) + return if(ishuman(user)) var/mob/living/carbon/human/H = user if(H.species.is_small) @@ -63,7 +64,7 @@ if(user.get_inactive_hand()) to_chat(user, "You need your other hand to be empty!") return - wielded = 1 + wielded = TRUE force = force_wielded name = "[name] (Wielded)" update_icon() @@ -80,7 +81,6 @@ O.name = "[name] - offhand" O.desc = "Your second grip on the [name]" user.put_in_inactive_hand(O) - return /obj/item/twohanded/dropped(mob/user) ..() @@ -124,22 +124,22 @@ ///////////Two hand required objects/////////////// //This is for objects that require two hands to even pick up -/obj/item/twohanded/required/ +/obj/item/twohanded/required w_class = WEIGHT_CLASS_HUGE /obj/item/twohanded/required/attack_self() return -/obj/item/twohanded/required/mob_can_equip(M as mob, slot) +/obj/item/twohanded/required/mob_can_equip(mob/M, slot) if(wielded && !slot_flags) to_chat(M, "[src] is too cumbersome to carry with anything but your hands!") - return 0 + return FALSE return ..() /obj/item/twohanded/required/attack_hand(mob/user)//Can't even pick it up without both hands empty var/obj/item/twohanded/required/H = user.get_inactive_hand() - if(get_dist(src,user) > 1) - return 0 + if(get_dist(src, user) > 1) + return FALSE if(H != null) to_chat(user, "[src] is too cumbersome to carry in one hand!") return @@ -163,7 +163,7 @@ desc = "Truly, the weapon of a madman. Who would think to fight fire with an axe?" force = 5 throwforce = 15 - sharp = 1 + sharp = TRUE w_class = WEIGHT_CLASS_BULKY slot_flags = SLOT_BACK force_unwielded = 5 @@ -174,12 +174,11 @@ /obj/item/twohanded/fireaxe/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "fireaxe[wielded]" - return /obj/item/twohanded/fireaxe/afterattack(atom/A, mob/user, proximity) if(!proximity) return - if(wielded) + if(wielded) //destroys windows and grilles in one hit if(istype(A, /obj/structure/window)) var/obj/structure/window/W = A W.take_damage(200, BRUTE, "melee", 0) @@ -191,13 +190,13 @@ * Double-Bladed Energy Swords - Cheridan */ /obj/item/twohanded/dualsaber - var/hacked = 0 + var/hacked = FALSE var/blade_color icon_state = "dualsaber0" name = "double-bladed energy sword" desc = "Handle with care." force = 3 - throwforce = 5.0 + throwforce = 5 throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_SMALL @@ -209,7 +208,7 @@ origin_tech = "magnets=4;syndicate=5" attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 75 - sharp = 1 + sharp = TRUE light_power = 2 var/brightness_on = 2 var/colormap = list(red=LIGHT_COLOR_RED, blue=LIGHT_COLOR_LIGHTBLUE, green=LIGHT_COLOR_GREEN, purple=LIGHT_COLOR_PURPLE, rainbow=LIGHT_COLOR_WHITE) @@ -226,26 +225,30 @@ icon_state = "dualsaber0" set_light(0) -/obj/item/twohanded/dualsaber/attack(target as mob, mob/living/user as mob) +/obj/item/twohanded/dualsaber/attack(mob/target, mob/living/user) if(HULK in user.mutations) to_chat(user, "You grip the blade too hard and accidentally close it!") unwield() return ..() - if((CLUMSY in user.mutations) && (wielded) &&prob(40)) + if((CLUMSY in user.mutations) && (wielded) && prob(40)) to_chat(user, "You twirl around a bit before losing your balance and impaling yourself on the [src].") - user.take_organ_damage(20,25) + user.take_organ_damage(20, 25) return if((wielded) && prob(50)) - spawn(0) - for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2)) - user.dir = i - sleep(1) + INVOKE_ASYNC(src, .proc/jedi_spin, user) + +/obj/item/twohanded/dualsaber/proc/jedi_spin(mob/living/user) + for(var/i in list(NORTH, SOUTH, EAST, WEST, EAST, SOUTH, NORTH, SOUTH, EAST, WEST, EAST, SOUTH)) + user.setDir(i) + if(i == WEST) + user.SpinAnimation(7, 1) + sleep(1) /obj/item/twohanded/dualsaber/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) if(wielded) return ..() - return 0 + return FALSE /obj/item/twohanded/dualsaber/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) //In case thats just so happens that it is still activated on the groud, prevents hulk from picking it up if(wielded) @@ -270,7 +273,7 @@ /obj/item/twohanded/dualsaber/IsReflect() if(wielded) - return 1 + return TRUE /obj/item/twohanded/dualsaber/wield(mob/living/carbon/M) //Specific wield () hulk checks due to reflection chance for balance issues and switches hitsounds. if(HULK in M.mutations) @@ -279,16 +282,17 @@ ..() hitsound = 'sound/weapons/blade1.ogg' -/obj/item/twohanded/dualsaber/attackby(obj/item/W as obj, mob/user as mob, params) - ..() - if(istype(W, /obj/item/multitool)) - if(hacked == 0) - hacked = 1 +/obj/item/twohanded/dualsaber/attackby(obj/item/W, mob/user, params) + if(ismultitool(W)) + if(!hacked) + hacked = TRUE to_chat(user, "2XRNBW_ENGAGE") blade_color = "rainbow" update_icon() else to_chat(user, "It's starting to look like a triple rainbow - no, nevermind.") + else + return ..() //spears /obj/item/twohanded/spear @@ -303,11 +307,11 @@ throwforce = 20 throw_speed = 4 armour_penetration = 10 - materials = list(MAT_METAL=1150, MAT_GLASS=2075) + materials = list(MAT_METAL = 1150, MAT_GLASS = 2075) hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "poked", "jabbed", "torn", "gored") - sharp = 1 - no_spin_thrown = 1 + sharp = TRUE + no_spin_thrown = TRUE var/obj/item/grenade/explosive = null var/war_cry = "AAAAARGH!!!" @@ -338,8 +342,8 @@ ..() if(!explosive) return - if(ismob(loc)) - var/mob/M = loc + if(ishuman(loc)) + var/mob/living/carbon/human/M = loc var/input = stripped_input(M, "What do you want your war cry to be? You will shout it when you hit someone in melee.", ,"", 50) if(input) war_cry = input @@ -386,48 +390,47 @@ M.GiveTarget(L) //Putting heads on spears -/obj/item/organ/external/head/attackby(var/obj/item/W, var/mob/living/user, params) - if(istype(W, /obj/item/twohanded/spear)) - to_chat(user, "You stick the head onto the spear and stand it upright on the ground.") - var/obj/structure/headspear/HS = new /obj/structure/headspear(user.loc) - var/matrix/M = matrix() - src.transform = M - user.drop_item() - src.loc = HS - var/image/IM = image(src.icon,src.icon_state) - IM.overlays = src.overlays.Copy() - HS.overlays += IM - qdel(W) - return - return ..() - -/obj/item/twohanded/spear/attackby(var/obj/item/I, var/mob/living/user) +/obj/item/twohanded/spear/attackby(obj/item/I, mob/living/user) if(istype(I, /obj/item/organ/external/head)) - to_chat(user, "You stick the head onto the spear and stand it upright on the ground.") - var/obj/structure/headspear/HS = new /obj/structure/headspear(user.loc) - var/matrix/M = matrix() - I.transform = M - usr.drop_item() - I.loc = HS - var/image/IM = image(I.icon,I.icon_state) - IM.overlays = I.overlays.Copy() - HS.overlays += IM - qdel(src) - return - return ..() + if(user.unEquip(src) && user.drop_item()) + to_chat(user, "You stick [I] onto the spear and stand it upright on the ground.") + var/obj/structure/headspear/HS = new /obj/structure/headspear(get_turf(src)) + var/matrix/M = matrix() + I.transform = M + var/image/IM = image(I.icon, I.icon_state) + IM.overlays = I.overlays.Copy() + HS.overlays += IM + I.forceMove(HS) + HS.mounted_head = I + forceMove(HS) + HS.contained_spear = src + else + return ..() /obj/structure/headspear name = "head on a spear" desc = "How barbaric." icon_state = "headspear" - density = 0 - anchored = 1 + density = FALSE + anchored = TRUE + var/obj/item/organ/external/head/mounted_head = null + var/obj/item/twohanded/spear/contained_spear = null + +/obj/structure/headspear/Destroy() + QDEL_NULL(mounted_head) + QDEL_NULL(contained_spear) + return ..() /obj/structure/headspear/attack_hand(mob/living/user) - user.visible_message("[user] kicks over \the [src]!", "You kick down \the [src]!") - new /obj/item/twohanded/spear(user.loc) - for(var/obj/item/organ/external/head/H in src) - H.loc = user.loc + user.visible_message("[user] kicks over [src]!", "You kick down [src]!") + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + var/turf/T = get_turf(src) + if(contained_spear) + contained_spear.forceMove(T) + contained_spear = null + if(mounted_head) + mounted_head.forceMove(T) + mounted_head = null qdel(src) /obj/item/twohanded/spear/kidan @@ -442,18 +445,18 @@ icon_state = "gchainsaw_off" flags = CONDUCT force = 13 - var/force_on = 21 + var/force_on = 24 w_class = WEIGHT_CLASS_HUGE throwforce = 13 throw_speed = 2 throw_range = 4 - materials = list(MAT_METAL=13000) + materials = list(MAT_METAL = 13000) origin_tech = "materials=3;engineering=4;combat=2" attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered") hitsound = "swing_hit" - sharp = 1 + sharp = TRUE actions_types = list(/datum/action/item_action/startchainsaw) - var/on = 0 + var/on = FALSE /obj/item/twohanded/required/chainsaw/attack_self(mob/user) on = !on @@ -486,8 +489,8 @@ if(attack_type == PROJECTILE_ATTACK) owner.visible_message("Ranged attacks just make [owner] angrier!") playsound(src, pick('sound/weapons/bulletflyby.ogg','sound/weapons/bulletflyby2.ogg','sound/weapons/bulletflyby3.ogg'), 75, 1) - return 1 - return 0 + return TRUE + return FALSE ///CHAINSAW/// @@ -507,7 +510,7 @@ armour_penetration = 35 origin_tech = "materials=6;syndicate=4" attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered") - sharp = 1 + sharp = TRUE /obj/item/twohanded/chainsaw/update_icon() if(wielded) @@ -515,7 +518,7 @@ else icon_state = "chainsaw0" -/obj/item/twohanded/chainsaw/attack(mob/target as mob, mob/living/user as mob) +/obj/item/twohanded/chainsaw/attack(mob/target, mob/living/user) if(wielded) playsound(loc, 'sound/weapons/chainsaw.ogg', 100, 1, -1) //incredibly loud; you ain't goin' for stealth with this thing. Credit to Lonemonk of Freesound for this sound. if(isrobot(target)) @@ -567,43 +570,41 @@ /obj/item/twohanded/singularityhammer/process() if(charged < 5) charged++ - return /obj/item/twohanded/singularityhammer/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "mjollnir[wielded]" - return -/obj/item/twohanded/singularityhammer/proc/vortex(var/turf/pull as turf, mob/wielder as mob) - for(var/atom/X in orange(5,pull)) - if(istype(X, /atom/movable)) - if(X == wielder) continue - if((X) &&(!X:anchored) && (!istype(X,/mob/living/carbon/human))) - step_towards(X,pull) - step_towards(X,pull) - step_towards(X,pull) - else if(istype(X,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = X - if(istype(H.shoes,/obj/item/clothing/shoes/magboots)) - var/obj/item/clothing/shoes/magboots/M = H.shoes - if(M.magpulse) - continue - H.apply_effect(1, WEAKEN, 0) - step_towards(H,pull) - step_towards(H,pull) - step_towards(H,pull) - return +/obj/item/twohanded/singularityhammer/proc/vortex(turf/pull, mob/wielder) + for(var/atom/movable/X in orange(5, pull)) + if(X == wielder) + continue + if((X) && (!X.anchored) && (!ishuman(X))) + step_towards(X, pull) + step_towards(X, pull) + step_towards(X, pull) + else if(ishuman(X)) + var/mob/living/carbon/human/H = X + if(istype(H.shoes, /obj/item/clothing/shoes/magboots)) + var/obj/item/clothing/shoes/magboots/M = H.shoes + if(M.magpulse) + continue + H.apply_effect(1, WEAKEN, 0) + step_towards(H, pull) + step_towards(H, pull) + step_towards(H, pull) -/obj/item/twohanded/singularityhammer/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity) - if(!proximity) return +/obj/item/twohanded/singularityhammer/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return if(wielded) if(charged == 5) charged = 0 - if(istype(A, /mob/living/)) + if(isliving(A)) var/mob/living/Z = A - Z.take_organ_damage(20,0) + Z.take_organ_damage(20, 0) playsound(user, 'sound/weapons/marauder.ogg', 50, 1) var/turf/target = get_turf(A) - vortex(target,user) + vortex(target, user) /obj/item/twohanded/mjollnir name = "Mjolnir" @@ -620,37 +621,35 @@ //var/charged = 5 origin_tech = "combat=4;powerstorage=7" -/obj/item/twohanded/mjollnir/proc/shock(mob/living/target as mob) +/obj/item/twohanded/mjollnir/proc/shock(mob/living/target) var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread() s.set_up(5, 1, target.loc) s.start() - target.visible_message("[target.name] was shocked by the [src.name]!", \ + target.visible_message("[target.name] was shocked by the [name]!", \ "You feel a powerful shock course through your body sending you flying!", \ "You hear a heavy electrical crack!") var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src))) target.throw_at(throw_target, 200, 4) - return -/obj/item/twohanded/mjollnir/attack(mob/M as mob, mob/user as mob) +/obj/item/twohanded/mjollnir/attack(mob/M, mob/user) ..() if(wielded) //if(charged == 5) //charged = 0 - playsound(src.loc, "sparks", 50, 1) - if(istype(M, /mob/living)) + playsound(loc, "sparks", 50, 1) + if(isliving(M)) M.Stun(3) shock(M) /obj/item/twohanded/mjollnir/throw_impact(atom/target) . = ..() - if(istype(target, /mob/living)) + if(isliving(target)) var/mob/living/L = target L.Stun(3) shock(L) /obj/item/twohanded/mjollnir/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "mjollnir[wielded]" - return /obj/item/twohanded/knighthammer name = "singuloth knight's hammer" @@ -678,27 +677,26 @@ /obj/item/twohanded/knighthammer/process() if(charged < 5) charged++ - return /obj/item/twohanded/knighthammer/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "knighthammer[wielded]" - return -/obj/item/twohanded/knighthammer/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity) - if(!proximity) return +/obj/item/twohanded/knighthammer/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return if(charged == 5) charged = 0 - if(istype(A, /mob/living/)) + if(isliving(A)) var/mob/living/Z = A if(Z.health >= 1) - Z.visible_message("[Z.name] was sent flying by a blow from the [src.name]!", \ + Z.visible_message("[Z.name] was sent flying by a blow from the [name]!", \ "You feel a powerful blow connect with your body and send you flying!", \ "You hear something heavy impact flesh!.") var/atom/throw_target = get_edge_target_turf(Z, get_dir(src, get_step_away(Z, src))) Z.throw_at(throw_target, 200, 4) playsound(user, 'sound/weapons/marauder.ogg', 50, 1) else if(wielded && Z.health < 1) - Z.visible_message("[Z.name] was blown to peices by the power of [src.name]!", \ + Z.visible_message("[Z.name] was blown to pieces by the power of [name]!", \ "You feel a powerful blow rip you apart!", \ "You hear a heavy impact and the sound of ripping flesh!.") Z.gib() @@ -709,7 +707,7 @@ Z.ex_act(2) charged = 3 playsound(user, 'sound/weapons/marauder.ogg', 50, 1) - else if(istype(A, /obj/structure) || istype(A, /obj/mecha/)) + else if(istype(A, /obj/structure) || istype(A, /obj/mecha)) var/obj/Z = A Z.ex_act(2) charged = 3 @@ -722,7 +720,7 @@ icon_state = "fireaxe0" force = 5 throwforce = 15 - sharp = 1 + sharp = TRUE w_class = WEIGHT_CLASS_HUGE armour_penetration = 20 slot_flags = SLOT_BACK @@ -742,11 +740,11 @@ if(!proximity) return if(wielded) - if(istype(A, /mob/living)) + if(isliving(A)) var/mob/living/Z = A if(charged) charged-- - Z.take_organ_damage(0,30) + Z.take_organ_damage(0, 30) user.visible_message("[user] slams the charged axe into [Z.name] with all [user.p_their()] might!") playsound(loc, 'sound/magic/lightningbolt.ogg', 5, 1) var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread @@ -764,4 +762,4 @@ qdel(A) if(prob(4)) charged++ - user.visible_message("The axe starts to emit an electric buzz!") + user.visible_message("The axe starts to emit an electric buzz!") \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index e5c7c2b27fb..551a8b30d9d 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -262,6 +262,7 @@ new /obj/item/sensor_device(src) new /obj/item/key/ambulance(src) new /obj/item/pinpointer/crew(src) + new /obj/item/clothing/shoes/magboots(src) /obj/structure/closet/secure_closet/reagents name = "chemical storage closet" diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm index 611ff1656f3..2831894e3ea 100644 --- a/code/game/turfs/space/transit.dm +++ b/code/game/turfs/space/transit.dm @@ -94,8 +94,7 @@ var/max = world.maxx-TRANSITIONEDGE var/min = 1+TRANSITIONEDGE - var/datum/space_level/dest = pick(levels_by_trait(REACHABLE)) - var/_z = dest.zpos //select a random space zlevel + var/_z = pick(levels_by_trait(REACHABLE)) //select a random space zlevel //now select coordinates for a border turf var/_x diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index b155ddc13dd..051f450179b 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -9,15 +9,17 @@ var/global/nologevent = 0 if(C.prefs && !(C.prefs.toggles & CHAT_NO_ADMINLOGS)) to_chat(C, msg) -/proc/msg_admin_attack(var/text) //Toggleable Attack Messages +/proc/msg_admin_attack(var/text, var/loglevel) if(!nologevent) var/rendered = "ATTACK: [text]" for(var/client/C in admins) if(R_ADMIN & C.holder.rights) - if(C.prefs.toggles & CHAT_ATTACKLOGS) - if(!istype(C, /mob/living)) - var/msg = rendered - to_chat(C, msg) + if(C.prefs.atklog == ATKLOG_NONE) + continue + var/msg = rendered + if(C.prefs.atklog <= loglevel) + to_chat(C, msg) + /proc/message_adminTicket(var/msg) msg = "ADMIN TICKET: [msg]" diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index c162a59fb82..91c237a0328 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -902,12 +902,27 @@ var/list/admin_verbs_ticket = list( if(!check_rights(R_ADMIN)) return - prefs.toggles ^= CHAT_ATTACKLOGS - prefs.save_preferences(src) - if(prefs.toggles & CHAT_ATTACKLOGS) - to_chat(usr, "You now will get attack log messages") + if(prefs.atklog == ATKLOG_ALL) + prefs.atklog = ATKLOG_ALMOSTALL + to_chat(usr, "Your attack logs preference is now: show ALMOST ALL attack logs (notable exceptions: NPCs attacking other NPCs, vampire bites, equipping/stripping, people pushing each other over)") + else if(prefs.atklog == ATKLOG_ALMOSTALL) + prefs.atklog = ATKLOG_MOST + to_chat(usr, "Your attack logs preference is now: show MOST attack logs (like ALMOST ALL, except that it also hides attacks by players on NPCs)") + else if(prefs.atklog == ATKLOG_MOST) + prefs.atklog = ATKLOG_FEW + to_chat(usr, "Your attack logs preference is now: show FEW attack logs (only the most important stuff: attacks on SSDs, use of explosives, messing with the engine, gibbing, AI wiping, forcefeeding, acid sprays, and organ extraction)") + else if(prefs.atklog == ATKLOG_FEW) + prefs.atklog = ATKLOG_NONE + to_chat(usr, "Your attack logs preference is now: show NO attack logs") + else if(prefs.atklog == ATKLOG_NONE) + prefs.atklog = ATKLOG_ALL + to_chat(usr, "Your attack logs preference is now: show ALL attack logs") else - to_chat(usr, "You now won't get attack log messages") + prefs.atklog = ATKLOG_ALL + to_chat(usr, "Your attack logs preference is now: show ALL attack logs (your preference was set to an invalid value, it has been reset)") + + prefs.save_preferences(src) + /client/proc/toggleadminlogs() set name = "Toggle Admin Log Messages" diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index 5039146b1c3..fe487ae6431 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -80,7 +80,6 @@ Security Level - Delta
Create Weather
Weather - Ash Storm   - Weather - Advanced Darkness  
"} diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 1bd231ba5a9..abfc807f9df 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -39,35 +39,35 @@ switch(href_list["makeAntag"]) if("1") log_admin("[key_name(usr)] has spawned a traitor.") - if(!src.makeTraitors()) + if(!makeTraitors()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("2") log_admin("[key_name(usr)] has spawned a changeling.") - if(!src.makeChanglings()) + if(!makeChangelings()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("3") log_admin("[key_name(usr)] has spawned revolutionaries.") - if(!src.makeRevs()) + if(!makeRevs()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("4") log_admin("[key_name(usr)] has spawned a cultists.") - if(!src.makeCult()) + if(!makeCult()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("5") log_admin("[key_name(usr)] has spawned a wizard.") - if(!src.makeWizard()) + if(!makeWizard()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("6") log_admin("[key_name(usr)] has spawned vampires.") - if(!src.makeVampires()) + if(!makeVampires()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("7") log_admin("[key_name(usr)] has spawned vox raiders.") - if(!src.makeVoxRaiders()) + if(!makeVoxRaiders()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("8") log_admin("[key_name(usr)] has spawned an abductor team.") - if(!src.makeAbductorTeam()) + if(!makeAbductorTeam()) to_chat(usr, "Unfortunately there weren't enough candidates available.") else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"] || href_list["dbsearchip"] || href_list["dbsearchcid"] || href_list["dbsearchbantype"]) @@ -2727,48 +2727,6 @@ for(var/mob/M in player_list) if(M.stat != 2) M.show_message(text("The chilling wind suddenly stops..."), 1) -/* if("shockwave") - ok = 1 - to_chat(world, "ALERT: STATION STRESS CRITICAL") - sleep(60) - to_chat(world, "ALERT: STATION STRESS CRITICAL. TOLERABLE LEVELS EXCEEDED!") - sleep(80) - to_chat(world, "ALERT: STATION STRUCTURAL STRESS CRITICAL. SAFETY MECHANISMS FAILED!") - sleep(40) - for(var/mob/M in world) - shake_camera(M, 400, 1) - for(var/obj/structure/window/W in world) - spawn(0) - sleep(rand(10,400)) - W.ex_act(rand(2,1)) - for(var/obj/structure/grille/G in world) - spawn(0) - sleep(rand(20,400)) - G.ex_act(rand(2,1)) - for(var/obj/machinery/door/D in world) - spawn(0) - sleep(rand(20,400)) - D.ex_act(rand(2,1)) - for(var/turf/station/floor/Floor in world) - spawn(0) - sleep(rand(30,400)) - Floor.ex_act(rand(2,1)) - for(var/obj/structure/cable/Cable in world) - spawn(0) - sleep(rand(30,400)) - Cable.ex_act(rand(2,1)) - for(var/obj/structure/closet/Closet in world) - spawn(0) - sleep(rand(30,400)) - Closet.ex_act(rand(2,1)) - for(var/obj/machinery/Machinery in world) - spawn(0) - sleep(rand(30,400)) - Machinery.ex_act(rand(1,3)) - for(var/turf/station/wall/Wall in world) - spawn(0) - sleep(rand(30,400)) - Wall.ex_act(rand(2,1)) */ if("lightout") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","LO") @@ -2793,7 +2751,7 @@ var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No") if(sure == "No") return - weather_master.run_weather("the floor is lava") + SSweather.run_weather(/datum/weather/floor_is_lava) message_admins("[key_name_admin(usr)] made the floor lava") if("fakelava") feedback_inc("admin_secrets_fun_used", 1) @@ -2801,7 +2759,7 @@ var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No") if(sure == "No") return - weather_master.run_weather("fake lava") + SSweather.run_weather(/datum/weather/floor_is_lava/fake) message_admins("[key_name_admin(usr)] made aesthetic lava on the floor") if("weatherashstorm") feedback_inc("admin_secrets_fun_used", 1) @@ -2809,16 +2767,8 @@ var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No") if(sure == "No") return - weather_master.run_weather("ash storm") + SSweather.run_weather(/datum/weather/ash_storm) message_admins("[key_name_admin(usr)] spawned an ash storm on the mining asteroid") - if("weatherdarkness") - feedback_inc("admin_secrets_fun_used", 1) - feedback_add_details("admin_secrets_fun_used", "WD") - var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No") - if(sure == "No") - return - weather_master.run_weather("advanced darkness") - message_admins("[key_name_admin(usr)] made the station go through advanced darkness") if("retardify") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","RET") diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index dfca07426c5..c1e28a48f8d 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -46,6 +46,8 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", else if(isfile(var_value)) . = VV_FILE + else if(istype(var_value, /regex)) + . = VV_REGEX else . = VV_NULL @@ -66,6 +68,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", VV_DATUM_TYPE, VV_TYPE, VV_MATRIX, + VV_REGEX, VV_FILE, VV_NEW_ATOM, VV_NEW_DATUM, @@ -141,6 +144,14 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", .["class"] = null return + if(VV_REGEX) + var/reg = input("Enter regex", "Regex", "") as null|text + if(!reg) + return + .["value"] = regex(reg) + if(.["value"] == null) + .["class"] = null + if(VV_ATOM_REFERENCE) var/type = pick_closest_path(FALSE) diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index b3f0a1a15a8..5c8e1c77745 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -25,6 +25,22 @@ client/proc/one_click_antag() usr << browse(dat, "window=oneclickantag;size=400x400") return +/datum/admins/proc/CandCheck(var/role = null, var/mob/living/carbon/human/M, var/datum/game_mode/temp = null) + // You pass in ROLE define (optional), the applicant, and the gamemode, and it will return true / false depending on whether the applicant qualify for the candidacy in question + if(jobban_isbanned(M, "Syndicate")) + return FALSE + if(M.stat || !M.mind || M.mind.special_role) + return FALSE + if(temp) + if(M.mind.assigned_role in temp.restricted_jobs || M.client.prefs.species in temp.protected_species) + return FALSE + if(role) // Don't even bother evaluating if there's no role + if(player_old_enough_antag(M.client,role) && (role in M.client.prefs.be_special) && (!jobban_isbanned(M, role))) + return TRUE + else + return FALSE + else + return TRUE /datum/admins/proc/makeTraitors() var/datum/game_mode/traitor/temp = new @@ -35,35 +51,29 @@ client/proc/one_click_antag() var/list/mob/living/carbon/human/candidates = list() var/mob/living/carbon/human/H = null - log_admin("[key_name(owner)] tried making Traitors with One-Click-Antag") - message_admins("[key_name_admin(owner)] tried making Traitors with One-Click-Antag") + var/antnum = input(owner, "How many traitors you want to create? Enter 0 to cancel","Amount:", 0) as num + if(!antnum || antnum <= 0) + return + log_admin("[key_name(owner)] tried making [antnum] traitors with One-Click-Antag") + message_admins("[key_name_admin(owner)] tried making [antnum] traitors with One-Click-Antag") for(var/mob/living/carbon/human/applicant in player_list) - if(ROLE_TRAITOR in applicant.client.prefs.be_special) - if(player_old_enough_antag(applicant.client,ROLE_TRAITOR)) - if(!applicant.stat) - if(applicant.mind) - if(!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "traitor") && !jobban_isbanned(applicant, "Syndicate")) - if(!(applicant.mind.assigned_role in temp.restricted_jobs)) - if(!(applicant.client.prefs.species in temp.protected_species)) - candidates += applicant + if(CandCheck(ROLE_TRAITOR, applicant, temp)) + candidates += applicant if(candidates.len) - var/numTratiors = min(candidates.len, 3) + var/numTraitors = min(candidates.len, antnum) - for(var/i = 0, i300)//If more than 30 game seconds passed. + //Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos. + for(var/mob/G in respawnable_list) + if(!jobban_isbanned(G, "Syndicate")) + spawn(0) + switch(alert(G,"Do you wish to be considered for an elite syndicate strike team being sent in?","Please answer in 30 seconds!","Yes","No")) + if("Yes") + if((world.time-time_passed)>300)//If more than 30 game seconds passed. + return + candidates += G + if("No") return - candidates += G - if("No") - return - else - return - sleep(300) + else + return + sleep(300) - for(var/mob/dead/observer/G in candidates) - if(!G.key) - candidates.Remove(G) + for(var/mob/dead/observer/G in candidates) + if(!G.key) + candidates.Remove(G) - if(candidates.len) - var/numagents = 6 - //Spawns commandos and equips them. - for(var/obj/effect/landmark/L in /area/syndicate_mothership/elite_squad) - if(numagents<=0) - break - if(L.name == "Syndicate-Commando") - syndicate_leader_selected = numagents == 1?1:0 - - var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) - - - while((!theghost || !theghost.client) && candidates.len) - theghost = pick(candidates) - candidates.Remove(theghost) - - if(!theghost) - qdel(new_syndicate_commando) + if(candidates.len) + //Spawns commandos and equips them. + for(var/obj/effect/landmark/L in /area/syndicate_mothership/elite_squad) + if(antnum <= 0) break + if(L.name == "Syndicate-Commando") + syndicate_leader_selected = antnum == 1?1:0 - new_syndicate_commando.key = theghost.key - new_syndicate_commando.internal = new_syndicate_commando.s_store - new_syndicate_commando.update_action_buttons_icon() + var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) - //So they don't forget their code or mission. + while((!theghost || !theghost.client) && candidates.len) + theghost = pick(candidates) + candidates.Remove(theghost) + + if(!theghost) + qdel(new_syndicate_commando) + break + + new_syndicate_commando.key = theghost.key + new_syndicate_commando.internal = new_syndicate_commando.s_store + new_syndicate_commando.update_action_buttons_icon() + + //So they don't forget their code or mission. - to_chat(new_syndicate_commando, "You are an Elite Syndicate. [!syndicate_leader_selected ? "commando" : "LEADER"] in the service of the Syndicate. \nYour current mission is: [input]") + to_chat(new_syndicate_commando, "You are an Elite Syndicate. [!syndicate_leader_selected ? "commando" : "LEADER"] in the service of the Syndicate. \nYour current mission is: [input]") - numagents-- - if(numagents >= 6) - return 0 - - for(var/obj/effect/landmark/L in /area/shuttle/syndicate_elite) - if(L.name == "Syndicate-Commando-Bomb") - new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) + antnum-- + for(var/obj/effect/landmark/L in /area/shuttle/syndicate_elite) + if(L.name == "Syndicate-Commando-Bomb") + new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) return 1 @@ -429,10 +431,12 @@ client/proc/one_click_antag() var/leader_chosen = 0 //when the leader is chosen. The last person spawned. + var/antnum = input(owner, "How many raiders you want to create? Enter 0 to cancel.","Amount:", 0) as num + if(!antnum || antnum <= 0) + return log_admin("[key_name(owner)] tried making Vox Raiders with One-Click-Antag") message_admins("[key_name_admin(owner)] tried making Vox Raiders with One-Click-Antag") - - //Generates a list of candidates from active ghosts. +//Generates a list of candidates from active ghosts. for(var/mob/G in respawnable_list) if(istype(G) && G.client && (ROLE_RAIDER in G.client.prefs.be_special)) if(player_old_enough_antag(G.client,ROLE_RAIDER)) @@ -455,8 +459,7 @@ client/proc/one_click_antag() candidates.Remove(G) if(candidates.len) - var/max_raiders = 1 - var/raiders = max_raiders + var/raiders = min(antnum, candidates.len) //Spawns vox raiders and equips them. for(var/obj/effect/landmark/L in world) if(L.name == "voxstart") @@ -480,8 +483,6 @@ client/proc/one_click_antag() to_chat(new_vox, "Don't forget to turn on your nitrogen internals!") raiders-- - if(raiders > max_raiders) - return 0 else return 0 return 1 @@ -534,32 +535,26 @@ client/proc/one_click_antag() var/list/mob/living/carbon/human/candidates = list() var/mob/living/carbon/human/H = null + var/antnum = input(owner, "How many vampires you want to create? Enter 0 to cancel","Amount:", 0) as num + if(!antnum || antnum <= 0) + return + log_admin("[key_name(owner)] tried making Vampires with One-Click-Antag") message_admins("[key_name_admin(owner)] tried making Vampires with One-Click-Antag") for(var/mob/living/carbon/human/applicant in player_list) - if(ROLE_VAMPIRE in applicant.client.prefs.be_special) - if(player_old_enough_antag(applicant.client,ROLE_VAMPIRE)) - if(!applicant.stat) - if(applicant.mind) - if(!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "vampire") && !jobban_isbanned(applicant, "Syndicate")) - if(!(applicant.job in temp.restricted_jobs)) - if(!(applicant.client.prefs.species in temp.protected_species)) - candidates += applicant + if(CandCheck(ROLE_VAMPIRE, applicant, temp)) + candidates += applicant if(candidates.len) - var/numVampires = min(candidates.len, 3) + var/numVampires = min(candidates.len, antnum) for(var/i = 0, iNobody volunteered to join the DeathSquad.") return @@ -47,53 +47,62 @@ var/global/sent_strike_team = 0 // Spawns commandos and equips them. var/commando_number = commandos_possible //for selecting a leader var/is_leader = TRUE // set to FALSE after leader is spawned + for(var/obj/effect/landmark/L in landmarks_list) - if(commando_number<=0) break + + if(commando_number <= 0) + break + if(L.name == "Commando") - spawn(0) - var/use_ds_borg = FALSE - var/ghost_key // Ghost ckey that we intend to put into the commando. Can remain undefined if we don't have one. - if(commando_ckeys.len) - ghost_key = pick(commando_ckeys) - commando_ckeys -= ghost_key - if(!is_leader) - var/new_gender = alert(src, "Select Deathsquad Type.", "DS Character Generation", "Organic", "Cyborg") - if(new_gender == "Cyborg") - use_ds_borg = TRUE + if(!commando_ghosts.len) + break - if(use_ds_borg) - var/mob/living/silicon/robot/deathsquad/R = new() - R.forceMove(get_turf(L)) - var/rnum = rand(1,1000) - var/borgname = "Epsilon [rnum]" - R.name = borgname - R.custom_name = borgname - R.real_name = R.name - R.mind = new - R.mind.current = R - R.mind.original = R - R.mind.assigned_role = SPECIAL_ROLE_DEATHSQUAD - R.mind.special_role = SPECIAL_ROLE_DEATHSQUAD - if(!(R.mind in ticker.minds)) - ticker.minds += R.mind - ticker.mode.traitors += R.mind - if(ghost_key) - R.key = ghost_key - if(nuke_code) - R.mind.store_memory("Nuke Code: [nuke_code].") - R.mind.store_memory("Mission: [input].") - to_chat(R, "You are a Special Operations cyborg, in the service of Central Command. \nYour current mission is: [input]") - else - var/mob/living/carbon/human/new_commando = create_death_commando(L, is_leader) - if(ghost_key) - new_commando.key = ghost_key - new_commando.internal = new_commando.s_store - new_commando.update_action_buttons_icon() - if(nuke_code) - new_commando.mind.store_memory("Nuke Code: [nuke_code].") - new_commando.mind.store_memory("Mission: [input].") - to_chat(new_commando, "You are a Special Ops [is_leader ? "TEAM LEADER" : "commando"] in the service of Central Command. Check the table ahead for detailed instructions.\nYour current mission is: [input]") + var/use_ds_borg = FALSE + var/mob/ghost_mob = pick(commando_ghosts) + commando_ghosts -= ghost_mob + if(!ghost_mob || !ghost_mob.key || !ghost_mob.client) + continue + + if(!is_leader) + var/new_dstype = alert(ghost_mob.client, "Select Deathsquad Type.", "DS Character Generation", "Organic", "Cyborg") + if(new_dstype == "Cyborg") + use_ds_borg = TRUE + + if(!ghost_mob || !ghost_mob.key || !ghost_mob.client) // Have to re-check this due to the above alert() call + continue + + if(use_ds_borg) + var/mob/living/silicon/robot/deathsquad/R = new() + R.forceMove(get_turf(L)) + var/rnum = rand(1,1000) + var/borgname = "Epsilon [rnum]" + R.name = borgname + R.custom_name = borgname + R.real_name = R.name + R.mind = new + R.mind.current = R + R.mind.original = R + R.mind.assigned_role = SPECIAL_ROLE_DEATHSQUAD + R.mind.special_role = SPECIAL_ROLE_DEATHSQUAD + if(!(R.mind in ticker.minds)) + ticker.minds += R.mind + ticker.mode.traitors += R.mind + R.key = ghost_mob.key + if(nuke_code) + R.mind.store_memory("Nuke Code: [nuke_code].") + R.mind.store_memory("Mission: [input].") + to_chat(R, "You are a Special Operations cyborg, in the service of Central Command. \nYour current mission is: [input]") + else + var/mob/living/carbon/human/new_commando = create_death_commando(L, is_leader) + new_commando.mind.key = ghost_mob.key + new_commando.key = ghost_mob.key + new_commando.internal = new_commando.s_store + new_commando.update_action_buttons_icon() + if(nuke_code) + new_commando.mind.store_memory("Nuke Code: [nuke_code].") + new_commando.mind.store_memory("Mission: [input].") + to_chat(new_commando, "You are a Special Ops [is_leader ? "TEAM LEADER" : "commando"] in the service of Central Command. Check the table ahead for detailed instructions.\nYour current mission is: [input]") is_leader = FALSE commando_number-- @@ -133,6 +142,7 @@ var/global/sent_strike_team = 0 A.real_name = "[commando_rank] [commando_name]" A.copy_to(new_commando) + new_commando.dna.ready_dna(new_commando)//Creates DNA. //Creates mind stuff. diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm index ec31632208e..c5f46c98592 100644 --- a/code/modules/admin/verbs/striketeam_syndicate.dm +++ b/code/modules/admin/verbs/striketeam_syndicate.dm @@ -45,8 +45,8 @@ var/global/sent_syndicate_strike_team = 0 break // Find ghosts willing to be SST - var/list/commando_ckeys = pollCandidatesByKeyWithVeto(src, usr, syndicate_commandos_possible, "Join the Syndicate Strike Team?",, 21, 600, 1, role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE) - if(!commando_ckeys.len) + var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, syndicate_commandos_possible, "Join the Syndicate Strike Team?",, 21, 600, 1, role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE) + if(!commando_ghosts.len) to_chat(usr, "Nobody volunteered to join the SST.") return @@ -54,15 +54,29 @@ var/global/sent_syndicate_strike_team = 0 //Spawns commandos and equips them. for(var/obj/effect/landmark/L in landmarks_list) - if(syndicate_commando_number<=0) break + + if(syndicate_commando_number <= 0) + break + if(L.name == "Syndicate-Commando") + + if(!commando_ghosts.len) + break + + var/mob/ghost_mob = pick(commando_ghosts) + commando_ghosts -= ghost_mob + + if(!ghost_mob || !ghost_mob.key || !ghost_mob.client) + continue + var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, is_leader) - if(commando_ckeys.len) - new_syndicate_commando.key = pick(commando_ckeys) - commando_ckeys -= new_syndicate_commando.key - new_syndicate_commando.internal = new_syndicate_commando.s_store - new_syndicate_commando.update_action_buttons_icon() + if(!new_syndicate_commando) + continue + + new_syndicate_commando.key = ghost_mob.key + new_syndicate_commando.internal = new_syndicate_commando.s_store + new_syndicate_commando.update_action_buttons_icon() //So they don't forget their code or mission. if(nuke_code) diff --git a/code/datums/antagonists/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm similarity index 100% rename from code/datums/antagonists/antag_datum.dm rename to code/modules/antagonists/_common/antag_datum.dm diff --git a/code/datums/antagonists/antag_helpers.dm b/code/modules/antagonists/_common/antag_helpers.dm similarity index 100% rename from code/datums/antagonists/antag_helpers.dm rename to code/modules/antagonists/_common/antag_helpers.dm diff --git a/code/datums/antagonists/antag_hud.dm b/code/modules/antagonists/_common/antag_hud.dm similarity index 100% rename from code/datums/antagonists/antag_hud.dm rename to code/modules/antagonists/_common/antag_hud.dm diff --git a/code/datums/antagonists/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm similarity index 100% rename from code/datums/antagonists/antag_spawner.dm rename to code/modules/antagonists/_common/antag_spawner.dm diff --git a/code/datums/antagonists/antag_team.dm b/code/modules/antagonists/_common/antag_team.dm similarity index 100% rename from code/datums/antagonists/antag_team.dm rename to code/modules/antagonists/_common/antag_team.dm diff --git a/code/modules/antagonists/wishgranter/wishgranter.dm b/code/modules/antagonists/wishgranter/wishgranter.dm new file mode 100644 index 00000000000..54d12867ac1 --- /dev/null +++ b/code/modules/antagonists/wishgranter/wishgranter.dm @@ -0,0 +1,81 @@ +/datum/antagonist/wishgranter + name = "Wishgranter Avatar" + +/datum/antagonist/wishgranter/proc/forge_objectives() + var/datum/objective/hijack/hijack = new + hijack.owner = owner + objectives += hijack + owner.objectives |= objectives + +/datum/antagonist/wishgranter/on_gain() + owner.special_role = "Avatar of the Wish Granter" + forge_objectives() + . = ..() + give_powers() + +/datum/antagonist/wishgranter/greet() + to_chat(owner.current, "Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!") + owner.announce_objectives() + +/datum/antagonist/wishgranter/proc/give_powers() + var/mob/living/carbon/human/H = owner.current + if(!istype(H)) + return + H.ignore_gene_stability = TRUE + H.dna.SetSEState(HULKBLOCK, TRUE) + genemutcheck(H, HULKBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(XRAYBLOCK, TRUE) + genemutcheck(H, XRAYBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(FIREBLOCK, TRUE) + genemutcheck(H, FIREBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(COLDBLOCK, TRUE) + genemutcheck(H, COLDBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(TELEBLOCK, TRUE) + genemutcheck(H, TELEBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(INCREASERUNBLOCK, TRUE) + genemutcheck(H, INCREASERUNBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(BREATHLESSBLOCK, TRUE) + genemutcheck(H, BREATHLESSBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(REGENERATEBLOCK, TRUE) + genemutcheck(H, REGENERATEBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(SHOCKIMMUNITYBLOCK, TRUE) + genemutcheck(H, SHOCKIMMUNITYBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(SMALLSIZEBLOCK, TRUE) + genemutcheck(H, SMALLSIZEBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(SOBERBLOCK, TRUE) + genemutcheck(H, SOBERBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(PSYRESISTBLOCK, TRUE) + genemutcheck(H, PSYRESISTBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(SHADOWBLOCK, TRUE) + genemutcheck(H, SHADOWBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(CRYOBLOCK, TRUE) + genemutcheck(H, CRYOBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(EATBLOCK, TRUE) + genemutcheck(H, EATBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(JUMPBLOCK, TRUE) + genemutcheck(H, JUMPBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(SUPERFARTBLOCK, TRUE) + genemutcheck(H, SUPERFARTBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(IMMOLATEBLOCK, TRUE) + genemutcheck(H, IMMOLATEBLOCK, null, MUTCHK_FORCED) + + H.mutations.Add(LASER) + H.update_mutations() + H.update_body() \ No newline at end of file diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index e92330754f2..763152cc5cf 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -46,7 +46,7 @@ if(!status) status = 1 investigate_log("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB) - msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]") + msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_FEW) log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature - T0C]") to_chat(user, "A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.") else diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 23abcfb2897..db4f33ac121 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -90,6 +90,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/UI_style_alpha = 255 var/windowflashing = TRUE var/clientfps = 0 + var/atklog = ATKLOG_ALL //ghostly preferences var/ghost_anonsay = 0 @@ -203,6 +204,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") max_gear_slots = config.max_loadout_points + var/loaded_preferences_successfully = FALSE if(istype(C)) if(!IsGuestKey(C.key)) unlock_content = C.IsByondMember() @@ -211,16 +213,17 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(C.donator_level >= DONATOR_LEVEL_ONE) max_gear_slots += 5 - var/loaded_preferences_successfully = load_preferences(C) - if(loaded_preferences_successfully) - if(load_character(C)) - return + loaded_preferences_successfully = load_preferences(C) // Do not call this with no client/C, it generates a runtime / SQL error + if(loaded_preferences_successfully) + if(load_character(C)) + return //we couldn't load character data so just randomize the character appearance + name random_character() //let's create a random character then - rather than a fat, bald and naked man. real_name = random_name(gender) - if(!loaded_preferences_successfully) - save_preferences(C) - save_character(C) //let's save this new random character so it doesn't keep generating new ones. + if(istype(C)) + if(!loaded_preferences_successfully) + save_preferences(C) // Do not call this with no client/C, it generates a runtime / SQL error + save_character(C) // Do not call this with no client/C, it generates a runtime / SQL error /datum/preferences/proc/color_square(colour) return "___" diff --git a/code/modules/client/preference/preferences_mysql.dm b/code/modules/client/preference/preferences_mysql.dm index f2a9d739cfe..a175e39bc71 100644 --- a/code/modules/client/preference/preferences_mysql.dm +++ b/code/modules/client/preference/preferences_mysql.dm @@ -17,7 +17,8 @@ windowflashing, ghost_anonsay, exp, - clientfps + clientfps, + atklog FROM [format_table_name("player")] WHERE ckey='[C.ckey]'"} ) @@ -48,6 +49,7 @@ ghost_anonsay = text2num(query.item[15]) exp = query.item[16] clientfps = text2num(query.item[17]) + atklog = text2num(query.item[18]) //Sanitize ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) @@ -66,6 +68,7 @@ ghost_anonsay = sanitize_integer(ghost_anonsay, 0, 1, initial(ghost_anonsay)) exp = sanitize_text(exp, initial(exp)) clientfps = sanitize_integer(clientfps, 0, 1000, initial(clientfps)) + atklog = sanitize_integer(atklog, 0, 100, initial(atklog)) return 1 /datum/preferences/proc/save_preferences(client/C) @@ -85,6 +88,7 @@ be_role='[sanitizeSQL(list2params(be_special))]', default_slot='[default_slot]', toggles='[toggles]', + atklog='[atklog]', sound='[sound]', randomslot='[randomslot]', volume='[volume]', @@ -93,7 +97,8 @@ lastchangelog='[lastchangelog]', windowflashing='[windowflashing]', ghost_anonsay='[ghost_anonsay]', - clientfps='[clientfps]' + clientfps='[clientfps]', + atklog='[atklog]' WHERE ckey='[C.ckey]'"} ) diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm index 123b4e5fd5e..91884eeba2d 100644 --- a/code/modules/clothing/spacesuits/ert.dm +++ b/code/modules/clothing/spacesuits/ert.dm @@ -9,9 +9,10 @@ var/obj/machinery/camera/camera var/has_camera = TRUE strip_delay = 130 - species_fit = list("Grey") + species_fit = list("Grey", "Vox") sprite_sheets = list( - "Grey" = 'icons/mob/species/grey/helmet.dmi' + "Grey" = 'icons/mob/species/grey/helmet.dmi', + "Vox" = 'icons/mob/species/vox/helmet.dmi' ) /obj/item/clothing/head/helmet/space/hardsuit/ert/attack_self(mob/user) @@ -41,9 +42,10 @@ /obj/item/radio, /obj/item/analyzer, /obj/item/gun/energy/laser, /obj/item/gun/energy/pulse, \ /obj/item/gun/energy/gun/advtaser, /obj/item/melee/baton, /obj/item/gun/energy/gun) strip_delay = 130 - species_fit = list("Drask") + species_fit = list("Drask", "Vox") sprite_sheets = list( - "Drask" = 'icons/mob/species/drask/suit.dmi' + "Drask" = 'icons/mob/species/drask/suit.dmi', + "Vox" = 'icons/mob/species/vox/suit.dmi' ) //Commander diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index 74d07164101..7880dcc1dd3 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -9,6 +9,10 @@ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES burn_state = FIRE_PROOF + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/helmet.dmi' + ) /obj/item/clothing/suit/bio_suit name = "bio suit" diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 6aa79584fc7..e0b444afcd0 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -77,7 +77,7 @@ burn_state = FIRE_PROOF species_fit = list("Vox") sprite_sheets = list( - "Vox" = 'icons/mob/species/vox/head.dmi' + "Vox" = 'icons/mob/species/vox/helmet.dmi' ) /obj/item/clothing/suit/bomb_suit @@ -108,16 +108,12 @@ /obj/item/clothing/head/bomb_hood/security icon_state = "bombsuitsec" item_state = "bombsuitsec" - species_fit = null - sprite_sheets = null /obj/item/clothing/suit/bomb_suit/security icon_state = "bombsuitsec" item_state = "bombsuitsec" allowed = list(/obj/item/gun/energy,/obj/item/melee/baton,/obj/item/restraints/handcuffs) - species_fit = null - sprite_sheets = null /* * Radiation protection diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index 141d9ed0bf6..a229b72f745 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -1370,4 +1370,13 @@ /obj/item/clothing/suit/fluff/vetcoat/navy //Furasian: Fillmoore Grayson icon_state = "alchemistcoatnavy" - item_state = "alchemistcoatnavy" \ No newline at end of file + item_state = "alchemistcoatnavy" + +/obj/item/clothing/accessory/medal/fluff/panzermedal //PanzerSkull: GRN-DER + name = "Cross of Valor" + desc = "A medal from the bygone Asteroid Wars. Its Ruby shines with a strange intensity." + icon = 'icons/obj/custom_items.dmi' + icon_state = "panzermedal" + item_state = "panzermedal" + item_color = "panzermedal" + slot_flags = SLOT_TIE \ No newline at end of file diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index b514924abfa..cf2e3621498 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -11,7 +11,7 @@ /datum/event/disease_outbreak/start() if(!virus_type) - virus_type = pick(/datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis) + virus_type = pick(/datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis, /datum/disease/beesease, /datum/disease/anxiety, /datum/disease/fake_gbs, /datum/disease/fluspanish, /datum/disease/pierrot_throat, /datum/disease/lycan) for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) if(issmall(H)) //don't infect monkies; that's a waste diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index 0f2da54818c..4b822dd718e 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -1,70 +1,11 @@ -/datum/event/radiation_storm - announceWhen = 1 - var/safe_zones = list( - /area/maintenance, - /area/crew_quarters/sleep, - /area/security/brig, - /area/shuttle, - /area/vox_station, - /area/syndicate_station - ) - +/datum/event/radiation_storm/setup() + startWhen = 3 + endWhen = startWhen + 1 + announceWhen = 1 /datum/event/radiation_storm/announce() - // Don't do anything, we want to pack the announcement with the actual event - -/datum/event/radiation_storm/proc/is_safe_zone(var/area/A) - for(var/szt in safe_zones) - if(istype(A, szt)) - return 1 - return 0 + priority_announcement.Announce("High levels of radiation detected near the station. Maintenance is best shielded from radiation.", "Anomaly Alert", 'sound/ai/radiation.ogg') + //sound not longer matches the text, but an audible warning is probably good /datum/event/radiation_storm/start() - spawn() - event_announcement.Announce("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg') - - for(var/area/A in world) - if(!is_station_level(A.z) || is_safe_zone(A)) - continue - A.radiation_alert() - - make_maint_all_access() - - sleep(600) - - event_announcement.Announce("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert") - - for(var/i = 0, i < 10, i++) - for(var/mob/living/carbon/human/H in living_mob_list) - var/armor = H.getarmor(type = "rad") - if((RADIMMUNE in H.species.species_traits) || armor >= 100) // Leave radiation-immune species/fully rad armored players completely unaffected - continue - var/turf/T = get_turf(H) - if(!T) - continue - if(!is_station_level(T.z) || is_safe_zone(T.loc)) - continue - - if(istype(H,/mob/living/carbon/human)) - H.apply_effect((rand(15,35)),IRRADIATE,0) - if(prob(5)) - H.apply_effect((rand(40,70)),IRRADIATE,0) - if(prob(75)) - randmutb(H) // Applies bad mutation - domutcheck(H,null,1) - else - randmutg(H) // Applies good mutation - domutcheck(H,null,1) - - sleep(100) - - event_announcement.Announce("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert") - - for(var/area/A in world) - if(!is_station_level(A.z) || is_safe_zone(A)) - continue - A.reset_radiation_alert() - - sleep(600) // Want to give them time to get out of maintenance. - - revoke_maint_all_access() + SSweather.run_weather(/datum/weather/rad_storm) \ No newline at end of file diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index bc442486d5c..5dc010bfae9 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -99,6 +99,7 @@ U.overlays += I var/obj/item/reagent_containers/food/snacks/collected = new type + collected.name = name collected.loc = U collected.reagents.remove_any(collected.reagents.total_volume) collected.trash = null diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm index b4a787ea4c8..6f6d9132fdf 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm @@ -58,7 +58,7 @@ C.emote("scream") user.changeNext_move(CLICK_CD_MELEE) C.apply_damage(25, BURN, "head") //25 fire damage and disfigurement because your face was just deep fried! - head.disfigure("burn") + head.disfigure() add_attack_logs(user, G.affecting, "Deep-fried with [src]") qdel(G) //Removes the grip so the person MIGHT have a small chance to run the fuck away and to prevent rapid dunks. return 0 diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index 0c2af905a74..a67b88f97d4 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -260,7 +260,7 @@ new /obj/effect/decal/cleanable/blood/gibs(src) if(!UserOverride) - add_attack_logs(user, occupant, "Gibbed in [src]", !!occupant.ckey) + add_attack_logs(user, occupant, "Gibbed in [src]", !!occupant.ckey ? ATKLOG_FEW : ATKLOG_ALL) if(!iscarbon(user)) occupant.LAssailant = null diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm index 4e76f7dcc74..f42b7963104 100644 --- a/code/modules/martial_arts/martial.dm +++ b/code/modules/martial_arts/martial.dm @@ -60,7 +60,7 @@ D.apply_damage(damage, BRUTE, affecting, armor_block) - add_attack_logs(A, D, "Melee attacked with martial-art [src]", admin_notify = (damage > 0) ? TRUE : FALSE) + add_attack_logs(A, D, "Melee attacked with martial-art [src]", (damage > 0) ? null : ATKLOG_ALL) if((D.stat != DEAD) && damage >= A.species.punchstunthreshold) D.visible_message("[A] has weakened [D]!!", \ diff --git a/code/modules/mining/lavaland/loot/legion_loot.dm b/code/modules/mining/lavaland/loot/legion_loot.dm index 210710db4d9..f11d6162f55 100644 --- a/code/modules/mining/lavaland/loot/legion_loot.dm +++ b/code/modules/mining/lavaland/loot/legion_loot.dm @@ -5,7 +5,6 @@ item_state = "staffofstorms" icon = 'icons/obj/guns/magic.dmi' slot_flags = SLOT_BACK - item_state = "staffofstorms" w_class = WEIGHT_CLASS_BULKY force = 25 damtype = BURN @@ -19,34 +18,36 @@ return var/area/user_area = get_area(user) + var/turf/user_turf = get_turf(user) + if(!user_area || !user_turf) + to_chat(user, "Something is preventing you from using the staff here.") + return var/datum/weather/A - var/z_level_name = space_manager.levels_by_name[user.z] - for(var/V in weather_master.existing_weather) + for(var/V in SSweather.processing) var/datum/weather/W = V - if(W.target_z == z_level_name && W.area_type == user_area.type) + if((user_turf.z in W.impacted_z_levels) && W.area_type == user_area.type) A = W break - if(A) + if(A) if(A.stage != END_STAGE) if(A.stage == WIND_DOWN_STAGE) to_chat(user, "The storm is already ending! It would be a waste to use the staff now.") return user.visible_message("[user] holds [src] skywards as an orange beam travels into the sky!", \ "You hold [src] skyward, dispelling the storm!") - playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0) + playsound(user, 'sound/magic/staff_change.ogg', 200, 0) A.wind_down() return else - A = new storm_type + A = new storm_type(list(user_turf.z)) A.name = "staff storm" A.area_type = user_area.type - A.target_z = z_level_name A.telegraph_duration = 100 A.end_duration = 100 user.visible_message("[user] holds [src] skywards as red lightning crackles into the sky!", \ "You hold [src] skyward, calling down a terrible storm!") - playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0) + playsound(user, 'sound/magic/staff_change.ogg', 200, 0) A.telegraph() storm_cooldown = world.time + 200 diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index 0d9c50ba5cc..72bf30ceedf 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -35,7 +35,7 @@ In all, this is a lot like the monkey code. /N visible_message("[M.name] bites [src]!", \ "[M.name] bites [src]!") adjustBruteLoss(damage) - add_attack_logs(M, src, "Alien attack", FALSE) + add_attack_logs(M, src, "Alien attack", ATKLOG_ALL) updatehealth() else to_chat(M, "[name] is too injured for that.") diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 2abc612f758..8c02bac91d1 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -15,6 +15,7 @@ parent_organ = "head" slot = "brain" vital = 1 + hidden_pain = TRUE //the brain has no pain receptors, and brain damage is meant to be a stealthy damage type. var/mmi_icon = 'icons/obj/assemblies.dmi' var/mmi_icon_state = "mmi_full" diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index a0969b82b25..aa890cbd17f 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -201,7 +201,7 @@ swap_hand() /mob/living/carbon/proc/help_shake_act(mob/living/carbon/M) - add_attack_logs(M, src, "Shaked", admin_notify = FALSE) + add_attack_logs(M, src, "Shaked", ATKLOG_ALL) if(health >= config.health_threshold_crit) if(src == M && ishuman(src)) var/mob/living/carbon/human/H = src @@ -1015,7 +1015,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, return 1 /mob/living/carbon/proc/forceFedAttackLog(var/obj/item/reagent_containers/food/toEat, mob/user) - add_attack_logs(user, src, "Fed [toEat]. Reagents: [toEat.reagentlist(toEat)]") + add_attack_logs(user, src, "Fed [toEat]. Reagents: [toEat.reagentlist(toEat)]", ATKLOG_FEW) if(!iscarbon(user)) LAssailant = null else diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 84b4608b233..37749c0dd76 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -139,9 +139,11 @@ /mob/living/carbon/human/proc/makeSkeleton() var/obj/item/organ/external/head/H = get_organ("head") - if(SKELETON in src.mutations) return + if(SKELETON in src.mutations) + return if(istype(H)) + H.disfigured = TRUE if(H.f_style) H.f_style = initial(H.f_style) if(H.h_style) @@ -159,16 +161,17 @@ mutations.Add(SKELETON) mutations.Add(NOCLONE) - status_flags |= DISFIGURED update_body(0) update_mutantrace() return /mob/living/carbon/human/proc/ChangeToHusk() var/obj/item/organ/external/head/H = bodyparts_by_name["head"] - if(HUSK in mutations) return + if(HUSK in mutations) + return if(istype(H)) + H.disfigured = TRUE //makes them unknown without fucking up other stuff like admintools if(H.f_style) H.f_style = "Shaved" //we only change the icon_state of the hair datum, so it doesn't mess up their UI/UE if(H.h_style) @@ -177,7 +180,6 @@ update_hair(0) mutations.Add(HUSK) - status_flags |= DISFIGURED //makes them unknown without fucking up other stuff like admintools update_body(0) update_mutantrace() return diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index fcb0e3d8b25..cca71c1e8d6 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -513,7 +513,7 @@ //Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable /mob/living/carbon/human/proc/get_face_name() var/obj/item/organ/external/head = get_organ("head") - if( !head || head.disfigured || !real_name || (HUSK in mutations) ) //disfigured. use id-name if possible + if(!head || head.disfigured || cloneloss > 50 || !real_name || (HUSK in mutations)) //disfigured. use id-name if possible return "Unknown" return real_name @@ -651,12 +651,12 @@ unEquip(pocket_item) if(thief_mode) usr.put_in_hands(pocket_item) - add_attack_logs(usr, src, "Stripped of [pocket_item]", isLivingSSD(src)) + add_attack_logs(usr, src, "Stripped of [pocket_item]", isLivingSSD(src) ? null : ATKLOG_ALL) else if(place_item) usr.unEquip(place_item) equip_to_slot_if_possible(place_item, pocket_id, 0, 1) - add_attack_logs(usr, src, "Equipped with [pocket_item]", isLivingSSD(src)) + add_attack_logs(usr, src, "Equipped with [pocket_item]", isLivingSSD(src) ? null : ATKLOG_ALL) // Update strip window if(usr.machine == src && in_range(src, usr)) @@ -665,7 +665,7 @@ // Display a warning if the user mocks up if they don't have pickpocket gloves. if(!thief_mode) to_chat(src, "You feel your [pocket_side] pocket being fumbled with!") - add_attack_logs(usr, src, "Attempted strip of [pocket_item]", isLivingSSD(src)) + add_attack_logs(usr, src, "Attempted strip of [pocket_item]", isLivingSSD(src) ? null : ATKLOG_ALL) if(href_list["set_sensor"]) if(istype(w_uniform, /obj/item/clothing/under)) @@ -680,7 +680,7 @@ "You have dislodged everything from [src]'s headpocket!") var/obj/item/organ/internal/headpocket/C = get_int_organ(/obj/item/organ/internal/headpocket) C.empty_contents() - add_attack_logs(usr, src, "Stripped of headpocket items", isLivingSSD(src)) + add_attack_logs(usr, src, "Stripped of headpocket items", isLivingSSD(src) ? null : ATKLOG_ALL) if(href_list["strip_accessory"]) if(istype(w_uniform, /obj/item/clothing/under)) @@ -1203,7 +1203,7 @@ return 0 if(!L.is_bruised()) - src.custom_pain("You feel a stabbing pain in your chest!", 1) + custom_pain("You feel a stabbing pain in your chest!") L.damage = L.min_bruised_damage //returns 1 if made bloody, returns 0 otherwise @@ -1762,7 +1762,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X to_chat(H, "You feel a breath of fresh air enter your lungs. It feels good.") to_chat(src, "Repeat at least every 7 seconds.") - add_attack_logs(src, H, "CPRed", FALSE) + add_attack_logs(src, H, "CPRed", ATKLOG_ALL) return 1 else to_chat(src, "You need to stay still while performing CPR!") diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 3af9130fa7d..9a78eafadd8 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -20,7 +20,7 @@ //Moving around with fractured ribs won't do you any good if(E.is_broken() && E.internal_organs && E.internal_organs.len && prob(15)) var/obj/item/organ/internal/I = pick(E.internal_organs) - custom_pain("You feel broken bones moving in your [E.name]!", 1) + custom_pain("You feel broken bones moving in your [E.name]!") I.receive_damage(rand(3,5)) //handle_stance() diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 4de74d63e5a..139f2f7c9bb 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -357,7 +357,7 @@ var/datum/unarmed_attack/attack = user.species.unarmed user.do_attack_animation(target, attack.animation_type) - add_attack_logs(user, target, "Melee attacked with fists", admin_notify = target.ckey ? TRUE : FALSE) + add_attack_logs(user, target, "Melee attacked with fists", target.ckey ? null : ATKLOG_ALL) if(!iscarbon(user)) target.LAssailant = null @@ -392,7 +392,7 @@ if(attacker_style && attacker_style.disarm_act(user, target)) return 1 else - add_attack_logs(user, target, "Disarmed", admin_notify = FALSE) + add_attack_logs(user, target, "Disarmed", ATKLOG_ALL) user.do_attack_animation(target, ATTACK_EFFECT_DISARM) if(target.w_uniform) target.w_uniform.add_fingerprint(user) @@ -402,7 +402,7 @@ target.apply_effect(2, WEAKEN, target.run_armor_check(affecting, "melee")) playsound(target.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) target.visible_message("[user] has pushed [target]!") - add_attack_logs(user, target, "Pushed over", admin_notify = FALSE) + add_attack_logs(user, target, "Pushed over", ATKLOG_ALL) if(!iscarbon(user)) target.LAssailant = null else diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d008bf060c4..bff49e7c527 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -818,7 +818,7 @@ who.unEquip(what) if(silent) put_in_hands(what) - add_attack_logs(src, who, "Stripped of [what]", isLivingSSD(who)) + add_attack_logs(src, who, "Stripped of [what]") // The src mob is trying to place an item on someone // Override if a certain mob should be behave differently when placing items (can't, for example) @@ -837,8 +837,7 @@ if(what && Adjacent(who)) unEquip(what) who.equip_to_slot_if_possible(what, where, 0, 1) - add_attack_logs(src, who, "Equipped [what]", isLivingSSD(who)) - + add_attack_logs(src, who, "Equipped [what]") /mob/living/singularity_act() var/gain = 20 diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index e211cef629e..aaeb26fe2c6 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -129,7 +129,7 @@ add_attack_logs(M.occupant, src, "Mecha-meleed with [M]") else step_away(src,M) - add_attack_logs(M.occupant, src, "Mecha-pushed with [M]", FALSE) + add_attack_logs(M.occupant, src, "Mecha-pushed with [M]", ATKLOG_ALL) M.occupant_message("You push [src] out of the way.") visible_message("[M] pushes [src] out of the way.") return @@ -240,7 +240,7 @@ to_chat(user, "You already grabbed [src].") return - add_attack_logs(user, src, "Grabbed passively", admin_notify = FALSE) + add_attack_logs(user, src, "Grabbed passively", ATKLOG_ALL) var/obj/item/grab/G = new /obj/item/grab(user, src) if(buckled) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 986795ccd1e..5e79c315f42 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -276,7 +276,7 @@ return apply_damage(M.melee_damage_upper, BRUTE) visible_message("[M] has [M.attacktext] [src]!") - add_attack_logs(M, src, "Animal attacked", FALSE) + add_attack_logs(M, src, "Animal attacked", ATKLOG_ALL) if(prob(10)) new /obj/effect/decal/cleanable/blood/oil(loc) diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index 9e96a16fb0f..90c44f19286 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -282,73 +282,66 @@ log_game("[key_name(user)] has renamed a robot to [t]") //Medbot Assembly -/obj/item/firstaid_arm_assembly - name = "incomplete medibot assembly." - desc = "A first aid kit with a robot arm permanently grafted to it." - icon = 'icons/obj/aibots.dmi' - icon_state = "firstaid_arm" - var/build_step = 0 - var/created_name = "Medibot" //To preserve the name if it's a unique medbot I guess - var/skin = null //Same as medbot, set to tox or ointment for the respective kits. - w_class = WEIGHT_CLASS_NORMAL - var/treatment_brute = "salglu_solution" - var/treatment_oxy = "salbutamol" - var/treatment_fire = "salglu_solution" - var/treatment_tox = "charcoal" - var/treatment_virus = "spaceacillin" - req_one_access = list(access_medical, access_robotics) - - /obj/item/firstaid_arm_assembly/New() - ..() - spawn(5) - if(skin) - overlays += image('icons/obj/aibots.dmi', "kit_skin_[skin]") - -/obj/item/storage/firstaid/attackby(obj/item/robot_parts/S, mob/user, params) - - if((!istype(S, /obj/item/robot_parts/l_arm)) && (!istype(S, /obj/item/robot_parts/r_arm))) - ..() - return +/obj/item/storage/firstaid/attackby(obj/item/I, mob/user, params) + if(!istype(I, /obj/item/robot_parts/l_arm) && !istype(I, /obj/item/robot_parts/r_arm)) + return ..() //Making a medibot! - if(contents.len >= 1) + if(contents.len) to_chat(user, "You need to empty [src] out first!") return - var/obj/item/firstaid_arm_assembly/A = new /obj/item/firstaid_arm_assembly - if(istype(src,/obj/item/storage/firstaid/fire)) - A.skin = "ointment" - else if(istype(src,/obj/item/storage/firstaid/toxin)) - A.skin = "tox" - else if(istype(src,/obj/item/storage/firstaid/o2)) - A.skin = "o2" - else if(istype(src,/obj/item/storage/firstaid/brute)) - A.skin = "brute" - else if(istype(src,/obj/item/storage/firstaid/adv)) - A.skin = "adv" - else if(istype(src,/obj/item/storage/firstaid/tactical)) - A.skin = "bezerk" - else if(istype(src,/obj/item/storage/firstaid/aquatic_kit)) - A.skin = "fish" + var/obj/item/firstaid_arm_assembly/A = new /obj/item/firstaid_arm_assembly(loc, med_bot_skin) A.req_one_access = req_one_access + A.syndicate_aligned = syndicate_aligned A.treatment_oxy = treatment_oxy A.treatment_brute = treatment_brute A.treatment_fire = treatment_fire A.treatment_tox = treatment_tox A.treatment_virus = treatment_virus - qdel(S) + qdel(I) user.put_in_hands(A) to_chat(user, "You add the robot arm to the first aid kit.") user.unEquip(src, 1) qdel(src) +/obj/item/firstaid_arm_assembly + name = "incomplete medibot assembly." + desc = "A first aid kit with a robot arm permanently grafted to it." + icon = 'icons/obj/aibots.dmi' + icon_state = "firstaid_arm" + w_class = WEIGHT_CLASS_NORMAL + req_one_access = list(access_medical, access_robotics) + var/build_step = 0 + var/created_name = "Medibot" //To preserve the name if it's a unique medbot I guess + var/skin = null //Same as medbot, set to tox or ointment for the respective kits. + var/syndicate_aligned = FALSE + var/treatment_brute = "salglu_solution" + var/treatment_oxy = "salbutamol" + var/treatment_fire = "salglu_solution" + var/treatment_tox = "charcoal" + var/treatment_virus = "spaceacillin" -/obj/item/firstaid_arm_assembly/attackby(obj/item/W, mob/user, params) +/obj/item/firstaid_arm_assembly/New(loc, new_skin) ..() - if(istype(W, /obj/item/pen)) - var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN) + if(new_skin) + skin = new_skin + update_icon() + +/obj/item/firstaid_arm_assembly/update_icon() + overlays.Cut() + if(skin) + overlays += image('icons/obj/aibots.dmi', "kit_skin_[skin]") + if(build_step > 0) + overlays += image('icons/obj/aibots.dmi', "na_scanner") + + +/obj/item/firstaid_arm_assembly/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/pen)) + var/t = stripped_input(user, "Enter new robot name", name, created_name, MAX_NAME_LEN) if(!t) return if(!in_range(src, user) && loc != user) @@ -358,32 +351,34 @@ else switch(build_step) if(0) - if(istype(W, /obj/item/healthanalyzer)) - if(!user.unEquip(W)) + if(istype(I, /obj/item/healthanalyzer)) + if(!user.drop_item()) return - qdel(W) + qdel(I) build_step++ to_chat(user, "You add the health sensor to [src].") name = "First aid/robot arm/health analyzer assembly" - overlays += image('icons/obj/aibots.dmi', "na_scanner") + update_icon() if(1) - if(isprox(W)) - if(!user.unEquip(W)) + if(isprox(I)) + if(!user.drop_item()) return - qdel(W) + qdel(I) build_step++ to_chat(user, "You complete the Medibot. Beep boop!") var/turf/T = get_turf(src) - var/mob/living/simple_animal/bot/medbot/S = new /mob/living/simple_animal/bot/medbot(T) - S.skin = skin - S.name = created_name - S.bot_core.req_one_access = req_one_access - S.treatment_oxy = treatment_oxy - S.treatment_brute = treatment_brute - S.treatment_fire = treatment_fire - S.treatment_tox = treatment_tox - S.treatment_virus = treatment_virus + if(!syndicate_aligned) + var/mob/living/simple_animal/bot/medbot/S = new /mob/living/simple_animal/bot/medbot(T, skin) + S.name = created_name + S.bot_core.req_one_access = req_one_access + S.treatment_oxy = treatment_oxy + S.treatment_brute = treatment_brute + S.treatment_fire = treatment_fire + S.treatment_tox = treatment_tox + S.treatment_virus = treatment_virus + else + new /mob/living/simple_animal/bot/medbot/syndicate(T) //Syndicate medibots are a special case that have so many unique vars on them, it's not worth passing them through construction phases user.unEquip(src, 1) qdel(src) diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 1df98e99c07..6895dc21cbc 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -17,7 +17,7 @@ bot_filter = RADIO_SECBOT model = "ED-209" bot_purpose = "seek out criminals, handcuff them, and report their location to security" - bot_core = /obj/machinery/bot_core/secbot + bot_core_type = /obj/machinery/bot_core/secbot window_id = "autoed209" window_name = "Automatic Security Unit v2.6" path_image_color = "#FF0000" @@ -61,12 +61,14 @@ shot_delay = 6//Longer shot delay because JESUS CHRIST check_records = 0//Don't actively target people set to arrest arrest_type = 1//Don't even try to cuff - bot_core.req_access = list(access_maint_tunnels, access_theatre) - arrest_type = 1 - if((lasercolor == "b") && (name == "\improper ED-209 Security Robot"))//Picks a name if there isn't already a custome one - name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT") - if((lasercolor == "r") && (name == "\improper ED-209 Security Robot")) - name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT") + declare_arrests = 0 // Don't spam sec + bot_core.req_access = list(access_maint_tunnels, access_theatre, access_robotics) + + if(created_name == initial(name) || !created_name) + if(lasercolor == "b") + name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT") + else if (lasercolor == "r") + name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT") //SECHUD var/datum/atom_hud/secsensor = huds[DATA_HUD_SECURITY_ADVANCED] @@ -101,30 +103,30 @@ dat += hack(user) dat += showpai(user) dat += text({" -Security Unit v2.6 controls

-Status: []
-Behaviour controls are [locked ? "locked" : "unlocked"]
-Maintenance panel panel is [open ? "opened" : "closed"]
"}, + Security Unit v2.6 controls

+ Status: []
+ Behaviour controls are [locked ? "locked" : "unlocked"]
+ Maintenance panel panel is [open ? "opened" : "closed"]
"}, -"[on ? "On" : "Off"]" ) + "[on ? "On" : "Off"]" ) if(!locked || issilicon(user) || user.can_admin_interact()) + dat += "Auto Patrol [auto_patrol ? "On" : "Off"]
" + if(!lasercolor) dat += text({"
-Arrest Unidentifiable Persons: []
-Arrest for Unauthorized Weapons: []
-Arrest for Warrant: []
-
-Operating Mode: []
-Report Arrests[]
-Auto Patrol[]"}, + Arrest Unidentifiable Persons: []
+ Arrest for Unauthorized Weapons: []
+ Arrest for Warrant: []
+
+ Operating Mode: []
+ Report Arrests[]
"}, -"[idcheck ? "Yes" : "No"]", -"[weaponscheck ? "Yes" : "No"]", -"[check_records ? "Yes" : "No"]", -"[arrest_type ? "Detain" : "Arrest"]", -"[declare_arrests ? "Yes" : "No"]", -"[auto_patrol ? "On" : "Off"]" ) + "[idcheck ? "Yes" : "No"]", + "[weaponscheck ? "Yes" : "No"]", + "[check_records ? "Yes" : "No"]", + "[arrest_type ? "Detain" : "Arrest"]", + "[declare_arrests ? "Yes" : "No"]") return dat @@ -243,13 +245,18 @@ Auto Patrol[]"}, if(target) // make sure target exists if(Adjacent(target) && isturf(target.loc)) // if right next to perp stun_attack(target) + if(!lasercolor) + mode = BOT_PREP_ARREST + anchored = 1 + target_lastloc = target.loc + return + else + mode = BOT_HUNT + target = null + target_lastloc = null + return - mode = BOT_PREP_ARREST - anchored = 1 - target_lastloc = target.loc - return - - else // not next to perp + else if(!disabled) // not next to perp var/turf/olddist = get_dist(src, target) walk_to(src, target,1,4) if((get_dist(src, target)) >= (olddist)) @@ -410,7 +417,7 @@ Auto Patrol[]"}, shoot_sound = 'sound/weapons/laser.ogg' if(emagged == 2) if(lasercolor) - projectile = /obj/item/projectile/beam/lasertag + projectile = /obj/item/projectile/beam/disabler else projectile = /obj/item/projectile/beam else @@ -505,6 +512,7 @@ Auto Patrol[]"}, if(lasertag_check) icon_state = "[lasercolor]ed2090" disabled = 1 + walk_to(src, 0) target = null spawn(100) disabled = 0 @@ -573,4 +581,4 @@ Auto Patrol[]"}, if(!C.handcuffed) C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C) C.update_handcuffed() - back_to_idle() + back_to_idle() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index 9ad8837520d..b1133cb0e08 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -14,7 +14,7 @@ bot_filter = RADIO_FLOORBOT model = "Floorbot" bot_purpose = "seek out damaged or missing floor tiles, and repair or replace them as necessary" - bot_core = /obj/machinery/bot_core/floorbot + bot_core_type = /obj/machinery/bot_core/floorbot window_id = "autofloor" window_name = "Automatic Station Floor Repairer v1.1" path_image_color = "#FFA500" diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index 17afce5ffc0..a6ed4f0c08e 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -44,6 +44,7 @@ var/treatment_virus = "spaceacillin" var/treat_virus = 1 //If on, the bot will attempt to treat viral infections, curing them if possible. var/shut_up = 0 //self explanatory :) + var/syndicate_aligned = FALSE // Will it only treat operatives? /mob/living/simple_animal/bot/medbot/tox skin = "tox" @@ -68,8 +69,8 @@ desc = "International Medibot of mystery." skin = "bezerk" treatment_oxy = "perfluorodecalin" - treatment_brute = "styptic_powder" - treatment_fire = "silver_sulfadiazine" + treatment_brute = "bicaridine" + treatment_fire = "kelotane" treatment_tox = "charcoal" /mob/living/simple_animal/bot/medbot/syndicate @@ -77,9 +78,10 @@ desc = "You'd better have insurance!" skin = "bezerk" treatment_oxy = "perfluorodecalin" - treatment_brute = "styptic_powder" - treatment_fire = "silver_sulfadiazine" + treatment_brute = "bicaridine" + treatment_fire = "kelotane" treatment_tox = "charcoal" + syndicate_aligned = TRUE bot_core_type = /obj/machinery/bot_core/medbot/syndicate control_freq = BOT_FREQ + 1000 // make it not show up on lists radio_channel = "Syndicate" @@ -95,6 +97,9 @@ declare_crit = 0 /mob/living/simple_animal/bot/medbot/update_icon() + overlays.Cut() + if(skin) + overlays += "medskin_[skin]" if(!on) icon_state = "medibot0" return @@ -106,22 +111,21 @@ else icon_state = "medibot1" -/mob/living/simple_animal/bot/medbot/New() +/mob/living/simple_animal/bot/medbot/New(loc, new_skin) ..() - update_icon() - - spawn(4) - if(skin) - overlays += image('icons/obj/aibots.dmi', "medskin_[skin]") - - var/datum/job/doctor/J = new/datum/job/doctor - access_card.access += J.get_access() - prev_access = access_card.access + var/datum/job/doctor/J = new /datum/job/doctor + access_card.access += J.get_access() + prev_access = access_card.access + qdel(J) var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED] medsensor.add_hud_to(src) permanent_huds |= medsensor + if(new_skin) + skin = new_skin + update_icon() + /mob/living/simple_animal/bot/medbot/bot_reset() ..() patient = null @@ -276,8 +280,10 @@ if(assess_patient(H)) last_found = world.time if((last_newpatient_speak + 300) < world.time) //Don't spam these messages! - var/message = pick("Hey, [H.name]! Hold on, I'm coming.","Wait [H.name]! I want to help!","[H.name], you appear to be injured!") + var/list/messagevoice = list("Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/mcoming.ogg', "Wait [H.name]! I want to help!" = 'sound/voice/mhelp.ogg', "[H.name], you appear to be injured!" = 'sound/voice/minjured.ogg') + var/message = pick(messagevoice) speak(message) + playsound(loc, messagevoice[message], 50, 0) last_newpatient_speak = world.time return H else @@ -309,8 +315,10 @@ if(!patient) if(!shut_up && prob(1)) - var/message = pick("Radar, put a mask on!","There's always a catch, and it's the best there is.","I knew it, I should've been a plastic surgeon.","What kind of medbay is this? Everyone's dropping like dead flies.","Delicious!") + var/list/messagevoice = list("Radar, put a mask on!" = 'sound/voice/mradar.ogg', "There's always a catch, and I'm the best there is." = 'sound/voice/mcatch.ogg', "I knew it, I should've been a plastic surgeon." = 'sound/voice/msurgeon.ogg', "What kind of medbay is this? Everyone's dropping like flies." = 'sound/voice/mflies.ogg', "Delicious!" = 'sound/voice/mdelicious.ogg') + var/message = pick(messagevoice) speak(message) + playsound(loc, messagevoice[message], 50, 0) var/scan_range = (stationary_mode ? 1 : DEFAULT_SCAN_RANGE) //If in stationary mode, scan range is limited to adjacent patients. patient = scan(/mob/living/carbon/human, oldpatient, scan_range) oldpatient = patient @@ -376,7 +384,7 @@ if(emagged == 2) //Everyone needs our medicine. (Our medicine is toxins) return 1 - if((skin == "bezerk") && (!("syndicate" in C.faction))) + if(syndicate_aligned && (!("syndicate" in C.faction))) return 0 if(declare_crit && C.health <= 0) //Critical condition! Call for help! @@ -445,9 +453,11 @@ soft_reset() return - if(C.stat == 2) - var/death_message = pick("No! NO!","Live, damnit! LIVE!","I...I've never lost a patient before. Not today, I mean.") - speak(death_message) + if(C.stat == DEAD || (C.status_flags & FAKEDEATH)) + var/list/messagevoice = list("No! Stay with me!" = 'sound/voice/mno.ogg', "Live, damnit! LIVE!" = 'sound/voice/mlive.ogg', "I...I've never lost a patient before. Not today, I mean." = 'sound/voice/mlost.ogg') + var/message = pick(messagevoice) + speak(message) + playsound(loc, messagevoice[message], 50, 0) oldpatient = patient soft_reset() return @@ -497,8 +507,10 @@ break if(!reagent_id) //If they don't need any of that they're probably cured! - var/message = pick("All patched up!","An apple a day keeps me away.","Feel better soon!") + var/list/messagevoice = list("All patched up!" = 'sound/voice/mpatchedup.ogg', "An apple a day keeps me away." = 'sound/voice/mapple.ogg', "Feel better soon!" = 'sound/voice/mfeelbetter.ogg') + var/message = pick(messagevoice) speak(message) + playsound(loc, messagevoice[message], 50, 0) bot_reset() return else @@ -559,7 +571,8 @@ if("adv") new /obj/item/storage/firstaid/adv/empty(Tsec) if("bezerk") - new /obj/item/storage/firstaid/tactical/empty(Tsec) + var/obj/item/storage/firstaid/tactical/empty/T = new(Tsec) + T.syndicate_aligned = syndicate_aligned //This is a special case since Syndicate medibots and the mysterious medibot look the same; we also dont' want crew building Syndicate medibots if the mysterious medibot blows up. if("fish") new /obj/item/storage/firstaid/aquatic_kit(Tsec) else @@ -576,6 +589,9 @@ if(prob(50)) new /obj/item/robot_parts/l_arm(Tsec) + if(emagged && prob(25)) + playsound(loc, 'sound/voice/minsult.ogg', 50, 0) + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(3, 1, src) s.start() @@ -584,7 +600,7 @@ /mob/living/simple_animal/bot/medbot/proc/declare(crit_patient) if(declare_cooldown) return - if((skin == "bezerk")) + if(syndicate_aligned) return var/area/location = get_area(src) speak("Medical emergency! [crit_patient ? "[crit_patient]" : "A patient"] is in critical condition at [location]!", radio_channel) diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 63b248ffd41..fb62ad3a629 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -4,6 +4,7 @@ lastKnownIP = client.address computer_id = client.computer_id log_access_in(client) + create_attack_log("Logged in at [atom_loc_line(get_turf(src))]") if(config.log_access) for(var/mob/M in player_list) if(M == src) continue diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index a0f8594e870..cbcd51c44a7 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -3,6 +3,7 @@ unset_machine() player_list -= src log_access_out(src) + create_attack_log("Logged out at [atom_loc_line(get_turf(src))]") // `holder` is nil'd out by now, so we check the `admin_datums` array directly //Only report this stuff if we are currently playing. if(admin_datums[ckey] && ticker && ticker.current_state == GAME_STATE_PLAYING) diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 593d077a562..458138b9db0 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -263,7 +263,7 @@ state = GRAB_AGGRESSIVE icon_state = "grabbed1" hud.icon_state = "reinforce1" - add_attack_logs(assailant, affecting, "Aggressively grabbed", admin_notify = FALSE) + add_attack_logs(assailant, affecting, "Aggressively grabbed", ATKLOG_ALL) else if(state < GRAB_NECK) if(isslime(affecting)) to_chat(assailant, "You squeeze [affecting], but nothing interesting happens.") @@ -273,7 +273,7 @@ state = GRAB_NECK icon_state = "grabbed+1" assailant.setDir(get_dir(assailant, affecting)) - add_attack_logs(assailant, affecting, "Neck grabbed", admin_notify = FALSE) + add_attack_logs(assailant, affecting, "Neck grabbed", ATKLOG_ALL) if(!iscarbon(assailant)) affecting.LAssailant = null else diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm index ace8ab1b621..1cb1bc5f3b0 100644 --- a/code/modules/mob/status_procs.dm +++ b/code/modules/mob/status_procs.dm @@ -208,3 +208,7 @@ /mob/proc/AdjustWeakened() return + +/mob/proc/adjust_bodytemperature(amount, min_temp = 0, max_temp = INFINITY) + if(bodytemperature > min_temp && bodytemperature < max_temp) + bodytemperature = Clamp(bodytemperature + amount, min_temp, max_temp) \ No newline at end of file diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 70cd75bf85d..a6c86d3f2ef 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -121,7 +121,7 @@ if(radio_controller) radio_controller.remove_object(src, frequency) radio_connection = null - msg_admin_attack("Emitter deleted at ([x],[y],[z] - [ADMIN_JMP(src)])", 0, 1) + msg_admin_attack("Emitter deleted at ([x],[y],[z] - [ADMIN_JMP(src)])", ATKLOG_FEW) log_game("Emitter deleted at ([x],[y],[z])") investigate_log("deleted at ([x],[y],[z])","singulo") return ..() diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index 9a911400fd5..0520630dcac 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -10,6 +10,7 @@ move_self = 1 //Do we move on our own? grav_pull = 5 //How many tiles out do we pull? consume_range = 6 //How many tiles out do we eat + gender = FEMALE /obj/singularity/narsie/large name = "Nar-Sie" diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm index b8570de2c78..42fbb784f49 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -227,7 +227,7 @@ active = !active investigate_log("turned [active?"ON":"OFF"] by [usr ? usr.key : "outside forces"]","singulo") if(active) - msg_admin_attack("PA Control Computer turned ON by [key_name_admin(usr)]",0,1) + msg_admin_attack("PA Control Computer turned ON by [key_name_admin(usr)]", ATKLOG_FEW) log_game("PA Control Computer turned ON by [key_name(usr)] in ([x],[y],[z])") use_log += text("\[[time_stamp()]\] [key_name(usr)] has turned on the PA Control Computer.") if(active) diff --git a/code/modules/projectiles/guns/dartgun.dm b/code/modules/projectiles/guns/dartgun.dm index 5ae089d5522..c279abdc5c1 100644 --- a/code/modules/projectiles/guns/dartgun.dm +++ b/code/modules/projectiles/guns/dartgun.dm @@ -178,7 +178,8 @@ else M.LAssailant = user - add_attack_logs(user, M, "Shot with dartgun containing [R]", !!M.ckey) + add_attack_logs(user, M, "Shot with dartgun containing [R]") + if(D.reagents) D.reagents.trans_to(M, 15) to_chat(M, "You feel a slight prick.") diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index a378e291e7c..e38a42ff88f 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -114,13 +114,18 @@ "[L] is hit by \a [src][organ_hit_text]!") //X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter var/reagent_note + var/has_reagents = FALSE if(reagents && reagents.reagent_list) reagent_note = " REAGENTS:" for(var/datum/reagent/R in reagents.reagent_list) reagent_note += R.id + " (" reagent_note += num2text(R.volume) + ") " + has_reagents = TRUE if(!log_override && firer && original) - add_attack_logs(firer, L, "Shot with a [type] (potentially containing [reagent_note])") + if(has_reagents) + add_attack_logs(firer, L, "Shot with a [type] (containing [reagent_note])") + else + add_attack_logs(firer, L, "Shot with a [type]") return L.apply_effects(stun, weaken, paralyze, irradiate, slur, stutter, eyeblur, drowsy, blocked, stamina, jitter) /obj/item/projectile/proc/get_splatter_blockage(var/turf/step_over, var/atom/target, var/splatter_dir, var/target_loca) //Check whether the place we want to splatter blood is blocked (i.e. by windows). diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm index a979d350c2a..d1b44798b85 100644 --- a/code/modules/reagents/chemistry/reagents/medicine.dm +++ b/code/modules/reagents/chemistry/reagents/medicine.dm @@ -115,7 +115,11 @@ M.adjustToxLoss(-3) M.adjustBruteLoss(-12) M.adjustFireLoss(-12) - M.status_flags &= ~DISFIGURED + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/head/head = H.get_organ("head") + if(head) + head.disfigured = FALSE ..() /datum/reagent/medicine/rezadone @@ -131,7 +135,11 @@ M.adjustCloneLoss(-1) //What? We just set cloneloss to 0. Why? Simple; this is so external organs properly unmutate. M.adjustBruteLoss(-1) M.adjustFireLoss(-1) - M.status_flags &= ~DISFIGURED + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/head/head = H.get_organ("head") + if(head) + head.disfigured = FALSE ..() /datum/reagent/medicine/rezadone/overdose_process(mob/living/M, severity) diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm index cab45b6a587..7bff61218c6 100644 --- a/code/modules/reagents/chemistry/reagents/toxins.dm +++ b/code/modules/reagents/chemistry/reagents/toxins.dm @@ -611,11 +611,11 @@ return if(!H.unacidable) - var/obj/item/organ/external/affecting = H.get_organ("head") - affecting.receive_damage(0, 75) + var/obj/item/organ/external/head/affecting = H.get_organ("head") + if(affecting) + affecting.receive_damage(0, 75) H.UpdateDamageIcon() H.emote("scream") - H.status_flags |= DISFIGURED /datum/reagent/facid/reaction_obj(obj/O, volume) if((istype(O, /obj/item) || istype(O, /obj/structure/glowshroom))) diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 057a339649c..ad8b3438ee4 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -85,7 +85,7 @@ var/datum/reagent/injected = chemical_reagents_list[reagent_ids[mode]] var/contained = injected.name var/trans = R.trans_to(M, amount_per_transfer_from_this) - add_attack_logs(M, user, "Injected with [name] containing [contained], transfered [trans] units", !!M.ckey) + add_attack_logs(M, user, "Injected with [name] containing [contained], transfered [trans] units") M.LAssailant = user to_chat(user, "[trans] units injected. [R.total_volume] units remaining.") return diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm index 6b0dc98dd37..d20ef6f82ee 100644 --- a/code/modules/reagents/reagent_containers/glass_containers.dm +++ b/code/modules/reagents/reagent_containers/glass_containers.dm @@ -83,7 +83,7 @@ for(var/datum/reagent/R in reagents.reagent_list) injected += R.name var/contained = english_list(injected) - add_attack_logs(M, user, "Splashed with [name] containing [contained]", !!M.ckey) + add_attack_logs(M, user, "Splashed with [name] containing [contained]", !!M.ckey ? null : ATKLOG_ALL) if(!iscarbon(user)) M.LAssailant = null else diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 02d71db8719..02ab4408acb 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -49,14 +49,14 @@ user.newtonian_move(get_dir(A, user)) if(reagents.has_reagent("sacid")) - msg_admin_attack("[key_name_admin(user)] fired sulphuric acid from \a [src] at [COORD(src)].") - log_game("[key_name(user)] fired sulphuric acid from \a [src] at [COORD(src)].") + msg_admin_attack("[key_name_admin(user)] fired sulphuric acid from \a [src] at [COORD(user)].", ATKLOG_FEW) + log_game("[key_name(user)] fired sulphuric acid from \a [src] at [COORD(user)].") if(reagents.has_reagent("facid")) - msg_admin_attack("[key_name_admin(user)] fired fluorosulfuric acid from \a [src] at [COORD(src)].") - log_game("[key_name(user)] fired fluorosulfuric Acid from \a [src] at [COORD(src)].") + msg_admin_attack("[key_name_admin(user)] fired fluorosulfuric acid from \a [src] at [COORD(user)].", ATKLOG_FEW) + log_game("[key_name(user)] fired fluorosulfuric Acid from \a [src] at [COORD(user)].") if(reagents.has_reagent("lube")) - msg_admin_attack("[key_name_admin(user)] fired space lube from \a [src] at [COORD(src)].") - log_game("[key_name(user)] fired space lube from \a [src] at [COORD(src)].") + msg_admin_attack("[key_name_admin(user)] fired space lube from \a [src] at [COORD(user)].") + log_game("[key_name(user)] fired space lube from \a [src] at [COORD(user)].") return diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 322f392950d..bcbcad6bc98 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -131,7 +131,7 @@ var/obj/item/assembly_holder/H = I if(istype(H.a_left, /obj/item/assembly/igniter) || istype(H.a_right, /obj/item/assembly/igniter)) - msg_admin_attack("[key_name_admin(user)] rigged [src.name] with [I.name] for explosion (JMP)") + msg_admin_attack("[key_name_admin(user)] rigged [src.name] with [I.name] for explosion (JMP)", ATKLOG_FEW) log_game("[key_name(user)] rigged [src.name] with [I.name] for explosion at [COORD(loc)]") investigate_log("[key_name(user)] rigged [src.name] with [I.name] for explosion at [COORD(loc)]", INVESTIGATE_BOMB) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index aaf35238d80..00b3b06a3a5 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -133,7 +133,7 @@ for(var/mob/C in viewers(src)) C.show_message("[GM.name] has been placed in the [src] by [user].", 3) qdel(G) - add_attack_logs(usr, GM, "Disposal'ed", !!GM.ckey) + add_attack_logs(usr, GM, "Disposal'ed", !!GM.ckey ? null : ATKLOG_ALL) return if(!I) @@ -179,7 +179,7 @@ msg = "[user.name] stuffs [target.name] into the [src]!" to_chat(user, "You stuff [target.name] into the [src]!") - add_attack_logs(user, target, "Disposal'ed", !!target.ckey) + add_attack_logs(user, target, "Disposal'ed", !!target.ckey ? null : ATKLOG_ALL) else return target.forceMove(src) diff --git a/code/modules/research/designs/bluespace_designs.dm b/code/modules/research/designs/bluespace_designs.dm index 3c555c40849..7f5377741e4 100644 --- a/code/modules/research/designs/bluespace_designs.dm +++ b/code/modules/research/designs/bluespace_designs.dm @@ -57,7 +57,7 @@ id = "telepad_beacon" req_tech = list("programming" = 5, "bluespace" = 4, "engineering" = 4, "plasmatech" = 4) build_type = PROTOLATHE - materials = list (MAT_METAL = 2000, MAT_GLASS = 1750, MAT_SILVER = 500) + materials = list(MAT_METAL = 2000, MAT_GLASS = 1750, MAT_SILVER = 500) build_path = /obj/item/telepad_beacon category = list("Bluespace") @@ -67,6 +67,6 @@ id = "beacon" req_tech = list("bluespace" = 1) build_type = PROTOLATHE - materials = list (MAT_METAL = 150, MAT_GLASS = 100) + materials = list(MAT_METAL = 150, MAT_GLASS = 100) build_path = /obj/item/radio/beacon category = list("Bluespace") diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 9d973c1ed74..49a1a7d0eba 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -181,7 +181,7 @@ id = "scalpel_manager" req_tech = list("biotech" = 4, "materials" = 7, "magnets" = 5, "programming" = 4) build_type = PROTOLATHE - materials = list (MAT_METAL = 2000, MAT_GLASS = 1500, MAT_SILVER = 1000, MAT_GOLD = 1000, MAT_DIAMOND = 1000) + materials = list(MAT_METAL = 2000, MAT_GLASS = 1500, MAT_SILVER = 1000, MAT_GOLD = 1000, MAT_DIAMOND = 1000) build_path = /obj/item/scalpel/laser/manager category = list("Medical") @@ -271,13 +271,24 @@ build_path = /obj/item/organ/internal/cyberimp/mouth/breathing_tube category = list("Misc", "Medical") +/datum/design/cyberimp_surgical + name = "Surgical Arm Implant" + desc = "A set of surgical tools hidden behind a concealed panel on the user's arm." + id = "ci-surgey" + req_tech = list("materials" = 3, "engineering" = 3, "biotech" = 3, "programming" = 2, "magnets" = 3) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) + construction_time = 200 + build_path = /obj/item/organ/internal/cyberimp/arm/surgery + category = list("Misc", "Medical") + /datum/design/cyberimp_toolset name = "Toolset Arm Implant" desc = "A stripped-down version of engineering cyborg toolset, designed to be installed on subject's arm." id = "ci-toolset" req_tech = list("materials" = 3, "engineering" = 4, "biotech" = 4, "powerstorage" = 4) build_type = PROTOLATHE | MECHFAB - materials = list (MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) + materials = list(MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) construction_time = 200 build_path = /obj/item/organ/internal/cyberimp/arm/toolset category = list("Misc", "Medical") diff --git a/code/modules/scripting/Implementations/Telecomms.dm b/code/modules/scripting/Implementations/Telecomms.dm index 16640a8b4c8..a24a9522b38 100644 --- a/code/modules/scripting/Implementations/Telecomms.dm +++ b/code/modules/scripting/Implementations/Telecomms.dm @@ -24,14 +24,22 @@ interpreter.GC() +//temp +/datum/TCS_Compiler + var/datum/n_scriptOptions/nS_Options/options + var/datum/n_Scanner/nS_Scanner/scanner + var/list/tokens + var/datum/n_Parser/nS_Parser/parser + var/datum/node/BlockDefinition/GlobalBlock/program + /* -- Compile a raw block of text -- */ -/datum/TCS_Compiler/proc/Compile(code as message) - var/datum/n_scriptOptions/nS_Options/options = new() - var/datum/n_Scanner/nS_Scanner/scanner = new(code, options) - var/list/tokens = scanner.Scan() - var/datum/n_Parser/nS_Parser/parser = new(tokens, options) - var/datum/node/BlockDefinition/GlobalBlock/program = parser.Parse() +/datum/TCS_Compiler/proc/Compile(list/code) + options = new() + scanner = new(code, options) + tokens = scanner.Scan() + parser = new(tokens, options) + program = parser.Parse() var/list/returnerrors = list() diff --git a/code/modules/scripting/Interpreter/Interpreter.dm b/code/modules/scripting/Interpreter/Interpreter.dm index 79802ff2fa5..c24e9ba5e3a 100644 --- a/code/modules/scripting/Interpreter/Interpreter.dm +++ b/code/modules/scripting/Interpreter/Interpreter.dm @@ -184,6 +184,8 @@ Runs each statement in a block of code. else RaiseError(new/datum/runtimeError/UnknownInstruction()) + CHECK_TICK + if(status) break diff --git a/code/modules/scripting/Options.dm b/code/modules/scripting/Options.dm index b27acff91d3..be471756359 100644 --- a/code/modules/scripting/Options.dm +++ b/code/modules/scripting/Options.dm @@ -36,11 +36,12 @@ File: Options if(!CanStartID(id)) //don't need to grab first char in id, since text2ascii does it automatically return 0 - if(length(id) == 1) + var/list/charmap = string2charlist(id) + if(charmap.len == 1) return 1 - for(var/i=2 to length(id)) - if(!IsValidIDChar(copytext(id, i, i + 1))) + for(var/i = 2 to charmap.len) + if(!IsValidIDChar(charmap[i])) return 0 return 1 diff --git a/code/modules/scripting/Scanner/Scanner.dm b/code/modules/scripting/Scanner/Scanner.dm index 011621c8ea8..da6a2c04803 100644 --- a/code/modules/scripting/Scanner/Scanner.dm +++ b/code/modules/scripting/Scanner/Scanner.dm @@ -6,7 +6,7 @@ An object responsible for breaking up source code into tokens for use by the parser. */ /datum/n_Scanner - var/code + var/list/code /* Var: errors A list of fatal errors found by the scanner. If there are any items in this list, then it is not safe to parse the returned tokens. @@ -25,7 +25,7 @@ Proc: LoadCode Loads source code. */ -/datum/n_Scanner/proc/LoadCode(var/c) +/datum/n_Scanner/proc/LoadCode(var/list/c) code=c /* @@ -100,24 +100,23 @@ code - The source code to tokenize. options - An object used to configure the scanner. */ -/datum/n_Scanner/nS_Scanner/New(var/code, var/datum/n_scriptOptions/nS_Options/options) +/datum/n_Scanner/nS_Scanner/New(var/list/c, var/datum/n_scriptOptions/nS_Options/options) . = ..() ignore += ascii2text(13) //Carriage return delim += ignore + options.symbols + end_stmt + string_delim src.options = options - LoadCode(code) + LoadCode(c) /datum/n_Scanner/nS_Scanner/Scan() //Creates a list of tokens from source code var/list/tokens = new - for(, src.codepos <= length(code), src.codepos++) - - var/char = copytext(code, codepos, codepos + 1) - var/nextchar = copytext(code, codepos + 1, codepos + 2) + for(, src.codepos <= code.len, src.codepos++) + var/char = code[codepos] + var/nextchar = TCOMMS_SAFE_INDEX(code, codepos + 1) if(char == "\n") line++ linepos = codepos - if(ignore.Find(char)) + if(char in ignore) continue else if(char == "/" && (nextchar == "*" || nextchar == "/")) @@ -139,6 +138,7 @@ else if(options.symbols.Find(char)) tokens += ReadSymbol() + CHECK_TICK codepos = initial(codepos) line = initial(line) @@ -155,12 +155,12 @@ */ /datum/n_Scanner/nS_Scanner/proc/ReadString(start) var/buf - for(, codepos <= length(code), codepos++)//codepos to length(code)) - var/char = copytext(code, codepos, codepos + 1) + for(, codepos <= code.len, codepos++)//codepos to length(code)) + var/char = code[codepos] switch(char) if("\\") //Backslash (\) encountered in string codepos++ //Skip next character in string, since it was escaped by a backslash - char = copytext(code, codepos, codepos+1) + char = TCOMMS_SAFE_INDEX(code, codepos) switch(char) if("\\") //Double backslash buf += "\\" @@ -190,12 +190,14 @@ Reads characters separated by an item in into a token. */ /datum/n_Scanner/nS_Scanner/proc/ReadWord() - var/char = copytext(code, codepos, codepos + 1) + var/char = code[codepos] var/buf - while(!delim.Find(char) && codepos <= length(code)) + while(!delim.Find(char)) buf += char - char = copytext(code, ++codepos, codepos + 1) + if(++codepos > code.len) break + char = code[codepos] + codepos-- //allow main Scan() proc to read the delimiter if(options.keywords.Find(buf)) return new/datum/token/keyword(buf, line, COL) @@ -207,13 +209,13 @@ Reads a symbol into a token. */ /datum/n_Scanner/nS_Scanner/proc/ReadSymbol() - var/char=copytext(code, codepos, codepos + 1) + var/char = code[codepos] var/buf while(options.symbols.Find(buf + char)) buf += char - if(++codepos > length(code)) break - char = copytext(code, codepos, codepos + 1) + if(++codepos > code.len) break + char = code[codepos] codepos-- //allow main Scan() proc to read the next character return new /datum/token/symbol(buf, line, COL) @@ -223,7 +225,7 @@ Reads a number into a token. */ /datum/n_Scanner/nS_Scanner/proc/ReadNumber() - var/char = copytext(code, codepos, codepos + 1) + var/char = code[codepos] var/buf var/dec = 0 @@ -233,7 +235,7 @@ buf += char codepos++ - char = copytext(code, codepos, codepos + 1) + char = TCOMMS_SAFE_INDEX(code, codepos) var/datum/token/number/T = new(buf, line, COL) if(isnull(text2num(buf))) @@ -249,8 +251,8 @@ */ /datum/n_Scanner/nS_Scanner/proc/ReadComment() - var/char = copytext(code, codepos, codepos + 1) - var/nextchar = copytext(code, codepos + 1, codepos + 2) + var/char = code[codepos] + var/nextchar = TCOMMS_SAFE_INDEX(code, codepos + 1) var/charstring = char + nextchar var/comm = 1 // 1: single-line comment @@ -262,23 +264,23 @@ comm = 2 // starts a multi-line comment while(comm) - if(++codepos > length(code)) + if(++codepos > code.len) break if(expectedend) // ending statement expected... - char = copytext(code, codepos, codepos + 1) + char = code[codepos] if(char == "/") // ending statement found - beak the comment comm = 0 break if(comm == 2) // multi-line comments are broken by ending statements - char = copytext(code, codepos, codepos + 1) + char = code[codepos] if(char == "*") expectedend = 1 continue else - char = copytext(code, codepos, codepos + 1) + char = code[codepos] if(char == "\n") comm = 0 break diff --git a/code/modules/scripting/__defines.dm b/code/modules/scripting/__defines.dm new file mode 100644 index 00000000000..52f30e68fdc --- /dev/null +++ b/code/modules/scripting/__defines.dm @@ -0,0 +1 @@ +#define TCOMMS_SAFE_INDEX(list, index) list.len > index ? list[index] : null diff --git a/code/modules/space_management/level_traits.dm b/code/modules/space_management/level_traits.dm index ae5d6447aae..39b584df64d 100644 --- a/code/modules/space_management/level_traits.dm +++ b/code/modules/space_management/level_traits.dm @@ -1,62 +1,63 @@ /proc/is_level_reachable(z) - return check_level_trait(z, REACHABLE) + return check_level_trait(z, REACHABLE) /proc/is_station_level(z) - return check_level_trait(z, STATION_LEVEL) + return check_level_trait(z, STATION_LEVEL) /proc/is_station_contact(z) - return check_level_trait(z, STATION_CONTACT) + return check_level_trait(z, STATION_CONTACT) /proc/is_teleport_allowed(z) - return !check_level_trait(z, BLOCK_TELEPORT) + return !check_level_trait(z, BLOCK_TELEPORT) /proc/is_admin_level(z) - return check_level_trait(z, ADMIN_LEVEL) + return check_level_trait(z, ADMIN_LEVEL) /proc/is_away_level(z) - return check_level_trait(z, AWAY_LEVEL) + return check_level_trait(z, AWAY_LEVEL) /proc/is_mining_level(z) - return check_level_trait(z, ORE_LEVEL) + return check_level_trait(z, ORE_LEVEL) /proc/is_ai_allowed(z) - return check_level_trait(z, AI_OK) + return check_level_trait(z, AI_OK) /proc/level_blocks_magic(z) - return check_level_trait(z, IMPEDES_MAGIC) + return check_level_trait(z, IMPEDES_MAGIC) /proc/level_boosts_signal(z) - return check_level_trait(z, BOOSTS_SIGNAL) + return check_level_trait(z, BOOSTS_SIGNAL) // Used for the nuke disk, or for checking if players survived through xenos /proc/is_secure_level(z) - var/secure = check_level_trait(z, STATION_LEVEL) - if(!secure) - // This is to allow further admin levels later, other than centcomm - secure = (z == level_name_to_num(CENTCOMM)) - return secure + var/secure = check_level_trait(z, STATION_LEVEL) + if(!secure) + // This is to allow further admin levels later, other than centcomm + secure = (z == level_name_to_num(CENTCOMM)) + return secure var/list/default_map_traits = MAP_TRANSITION_CONFIG + /proc/check_level_trait(z, trait) - if(!z) - return 0 // If you're nowhere, you have no traits - var/list/trait_list - if(space_manager.initialized) - var/datum/space_level/S = space_manager.get_zlev(z) - trait_list = S.flags - else - trait_list = default_map_traits[z] - trait_list = trait_list["attributes"] - return (trait in trait_list) + if(!z) + return 0 // If you're nowhere, you have no traits + var/list/trait_list + if(space_manager.initialized) + var/datum/space_level/S = space_manager.get_zlev(z) + trait_list = S.flags + else + trait_list = default_map_traits[z] + trait_list = trait_list["attributes"] + return (trait in trait_list) /proc/levels_by_trait(trait) - var/list/result = list() - for(var/A in space_manager.z_list) - var/datum/space_level/S = space_manager.z_list[A] - if(trait in S.flags) - result |= S - return result + var/list/result = list() + for(var/A in space_manager.z_list) + var/datum/space_level/S = space_manager.z_list[A] + if(trait in S.flags) + result |= S.zpos + return result /proc/level_name_to_num(name) - var/datum/space_level/S = space_manager.get_zlev_by_name(name) - return S.zpos + var/datum/space_level/S = space_manager.get_zlev_by_name(name) + return S.zpos \ No newline at end of file diff --git a/code/modules/space_management/zlevel_manager.dm b/code/modules/space_management/zlevel_manager.dm index 087a70657ed..acb1cf5c0a0 100644 --- a/code/modules/space_management/zlevel_manager.dm +++ b/code/modules/space_management/zlevel_manager.dm @@ -12,6 +12,8 @@ var/global/datum/zlev_manager/space_manager = new var/datum/spacewalk_grid/linkage_map var/initialized = 0 + var/list/areas_in_z = list() + // Populate our space level list // and prepare space transitions /datum/zlev_manager/proc/initialize() @@ -166,4 +168,4 @@ var/global/datum/zlev_manager/space_manager = new var/datum/space_level/heap/heap = z_list["[C.zpos]"] if(!istype(heap)) throw EXCEPTION("Attempted to free chunk at invalid z-level ([C.x],[C.y],[C.zpos]) [C.width]x[C.height]") - heap.free(C) + heap.free(C) \ No newline at end of file diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm index dfe2c0feb8c..a053b568dc7 100644 --- a/code/modules/surgery/bones.dm +++ b/code/modules/surgery/bones.dm @@ -49,7 +49,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts applying medication to the damaged bones in [target]'s [affected.name] with \the [tool]." , \ "You start applying medication to the damaged bones in [target]'s [affected.name] with \the [tool].") - target.custom_pain("Something in your [affected.name] is causing you a lot of pain!",1) + target.custom_pain("Something in your [affected.name] is causing you a lot of pain!") ..() /datum/surgery_step/glue_bone/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -83,7 +83,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] is beginning to set the bone in [target]'s [affected.name] in place with \the [tool]." , \ "You are beginning to set the bone in [target]'s [affected.name] in place with \the [tool].") - target.custom_pain("The pain in your [affected.name] is going to make you pass out!",1) + target.custom_pain("The pain in your [affected.name] is going to make you pass out!") ..() /datum/surgery_step/set_bone/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -136,7 +136,7 @@ "Your hand slips, damaging [target]'s face with \the [tool]!") var/obj/item/organ/external/head/h = affected h.receive_damage(10) - h.disfigured = 1 + h.disfigure() return 0 /datum/surgery_step/finish_bone diff --git a/code/modules/surgery/cavity_implant.dm b/code/modules/surgery/cavity_implant.dm index 0e88927e1a2..2ab2aca37c7 100644 --- a/code/modules/surgery/cavity_implant.dm +++ b/code/modules/surgery/cavity_implant.dm @@ -78,7 +78,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts making some space inside [target]'s [get_cavity(affected)] cavity with \the [tool].", \ "You start making some space inside [target]'s [get_cavity(affected)] cavity with \the [tool]." ) - target.custom_pain("The pain in your chest is living hell!",1) + target.custom_pain("The pain in your chest is living hell!") ..() /datum/surgery_step/cavity/make_space/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -104,7 +104,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts mending [target]'s [get_cavity(affected)] cavity wall with \the [tool].", \ "You start mending [target]'s [get_cavity(affected)] cavity wall with \the [tool]." ) - target.custom_pain("The pain in your chest is living hell!",1) + target.custom_pain("The pain in your chest is living hell!") ..() /datum/surgery_step/cavity/close_space/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -155,7 +155,7 @@ else //no internal items..but we still need a message! user.visible_message("[user] checks for items in [target]'s [target_zone].", "You check for items in [target]'s [target_zone]...") - target.custom_pain("The pain in your [target_zone] is living hell!",1) + target.custom_pain("The pain in your [target_zone] is living hell!") ..() /datum/surgery_step/cavity/place_item/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -190,7 +190,7 @@ if((tool.w_class > get_max_wclass(affected)/2 && prob(50) && !(affected.status & ORGAN_ROBOT))) to_chat(user, " You tear some vessels trying to fit the object in the cavity.") affected.internal_bleeding = TRUE - affected.owner.custom_pain("You feel something rip in your [affected.name]!", 1) + affected.owner.custom_pain("You feel something rip in your [affected.name]!") user.drop_item() affected.hidden = tool tool.forceMove(affected) diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm index eddf116a45d..b9a33fcecab 100644 --- a/code/modules/surgery/encased.dm +++ b/code/modules/surgery/encased.dm @@ -38,7 +38,7 @@ user.visible_message("[user] begins to cut through [target]'s [affected.encased] with \the [tool].", \ "You begin to cut through [target]'s [affected.encased] with \the [tool].") - target.custom_pain("Something hurts horribly in your [affected.name]!",1) + target.custom_pain("Something hurts horribly in your [affected.name]!") ..() /datum/surgery_step/open_encased/saw/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -86,7 +86,7 @@ var/msg = "[user] starts to force open the [affected.encased] in [target]'s [affected.name] with \the [tool]." var/self_msg = "You start to force open the [affected.encased] in [target]'s [affected.name] with \the [tool]." user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your [affected.name]!",1) + target.custom_pain("Something hurts horribly in your [affected.name]!") ..() /datum/surgery_step/open_encased/retract/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -137,7 +137,7 @@ var/msg = "[user] starts bending [target]'s [affected.encased] back into place with \the [tool]." var/self_msg = "You start bending [target]'s [affected.encased] back into place with \the [tool]." user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your [affected.name]!",1) + target.custom_pain("Something hurts horribly in your [affected.name]!") ..() /datum/surgery_step/open_encased/close/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -187,7 +187,7 @@ var/msg = "[user] starts applying \the [tool] to [target]'s [affected.encased]." var/self_msg = "You start applying \the [tool] to [target]'s [affected.encased]." user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your [affected.name]!",1) + target.custom_pain("Something hurts horribly in your [affected.name]!") ..() /datum/surgery_step/open_encased/mend/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) diff --git a/code/modules/surgery/face.dm b/code/modules/surgery/face.dm deleted file mode 100644 index d96db814b78..00000000000 --- a/code/modules/surgery/face.dm +++ /dev/null @@ -1,147 +0,0 @@ -//Procedures in this file: Facial reconstruction surgery -////////////////////////////////////////////////////////////////// -// FACE SURGERY // -////////////////////////////////////////////////////////////////// -/datum/surgery/plastic_surgery - name = "Face Repair" - steps = list(/datum/surgery_step/generic/cut_face, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/face/mend_vocal, /datum/surgery_step/face/fix_face,/datum/surgery_step/face/cauterize) - possible_locs = list("head") - - - -/datum/surgery/plastic_surgery/can_start(mob/user, mob/living/carbon/target) - if(istype(target,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = target - var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) - if(!affected) - return 0 - if(affected.status & ORGAN_ROBOT) - return 0 - if(!affected.disfigured) - return 0 - return 1 - -/datum/surgery_step/face - priority = 2 - can_infect = 0 - -/datum/surgery_step/generic/cut_face - name = "make incision" - allowed_tools = list( - /obj/item/scalpel = 100, \ - /obj/item/kitchen/knife = 90, \ - /obj/item/shard = 60, \ - ) - - time = 16 - -/datum/surgery_step/generic/cut_face/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message("[user] starts to cut open [target]'s face and neck with \the [tool].", \ - "You start to cut open [target]'s face and neck with \the [tool].") - ..() - -/datum/surgery_step/generic/cut_face/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message(" [user] has cut open [target]'s face and neck with \the [tool]." , \ - " You have cut open [target]'s face and neck with \the [tool].",) - - return 1 - -/datum/surgery_step/generic/cut_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message(" [user]'s hand slips, slicing [target]'s throat wth \the [tool]!" , \ - " Your hand slips, slicing [target]'s throat wth \the [tool]!" ) - affected.receive_damage(60) - target.AdjustLoseBreath(4) - - return 0 - -/datum/surgery_step/face/mend_vocal - name = "mend vocal cords" - allowed_tools = list( - /obj/item/scalpel/laser/manager = 100, \ - /obj/item/hemostat = 100, \ - /obj/item/stack/cable_coil = 90, \ - /obj/item/assembly/mousetrap = 12 //I don't know. Don't ask me. But I'm leaving it because hilarity. - ) - - time = 24 - -/datum/surgery_step/face/mend_vocal/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message("[user] starts mending [target]'s vocal cords with \the [tool].", \ - "You start mending [target]'s vocal cords with \the [tool].") - ..() - -/datum/surgery_step/face/mend_vocal/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message(" [user] mends [target]'s vocal cords with \the [tool].", \ - " You mend [target]'s vocal cords with \the [tool].") - return 1 - -/datum/surgery_step/face/mend_vocal/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message(" [user]'s hand slips, clamping [target]'s trachea shut for a moment with \the [tool]!", \ - " Your hand slips, clamping [user]'s trachea shut for a moment with \the [tool]!") - target.AdjustLoseBreath(4) - return 0 - -/datum/surgery_step/face/fix_face - name = "reshape face" - allowed_tools = list( - /obj/item/scalpel/laser/manager = 100, \ - /obj/item/retractor = 100, \ - /obj/item/crowbar = 65, \ - /obj/item/kitchen/utensil/fork = 90) - - time = 64 - -/datum/surgery_step/face/fix_face/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message("[user] starts pulling skin on [target]'s face back in place with \the [tool].", \ - "You start pulling skin on [target]'s face back in place with \the [tool].") - ..() - -/datum/surgery_step/face/fix_face/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message(" [user] pulls skin on [target]'s face back in place with \the [tool].", \ - " You pull skin on [target]'s face back in place with \the [tool].") - return 1 - -/datum/surgery_step/face/fix_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message(" [user]'s hand slips, tearing skin on [target]'s face with \the [tool]!", \ - " Your hand slips, tearing skin on [target]'s face with \the [tool]!") - target.apply_damage(10, BRUTE, affected, sharp = 1) - return 0 - -/datum/surgery_step/face/cauterize - name = "close incision" - allowed_tools = list( - /obj/item/scalpel/laser = 100, \ - /obj/item/cautery = 100, \ - /obj/item/clothing/mask/cigarette = 90, \ - /obj/item/lighter = 60, \ - /obj/item/weldingtool = 30 - ) - - time = 24 - -/datum/surgery_step/face/cauterize/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message("[user] is beginning to cauterize the incision on [target]'s face and neck with \the [tool]." , \ - "You are beginning to cauterize the incision on [target]'s face and neck with \the [tool].") - ..() - -/datum/surgery_step/face/cauterize/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message(" [user] cauterizes the incision on [target]'s face and neck with \the [tool].", \ - " You cauterize the incision on [target]'s face and neck with \the [tool].") - affected.open = 0 - var/obj/item/organ/external/head/h = affected - h.disfigured = 0 - h.update_icon() - target.regenerate_icons() - - return 1 - -/datum/surgery_step/face/cauterize/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message(" [user]'s hand slips, leaving a small burn on [target]'s face with \the [tool]!", \ - " Your hand slips, leaving a small burn on [target]'s face with \the [tool]!") - target.apply_damage(4, BURN, affected) - - return 0 diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index 158656f8c01..1e1b3a10365 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -37,7 +37,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts the incision on [target]'s [affected.name] with \the [tool].", \ "You start the incision on [target]'s [affected.name] with \the [tool].") - target.custom_pain("You feel a horrible pain as if from a sharp knife in your [affected.name]!",1) + target.custom_pain("You feel a horrible pain as if from a sharp knife in your [affected.name]!") ..() /datum/surgery_step/generic/cut_open/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -71,7 +71,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts clamping bleeders in [target]'s [affected.name] with \the [tool].", \ "You start clamping bleeders in [target]'s [affected.name] with \the [tool].") - target.custom_pain("The pain in your [affected.name] is maddening!",1) + target.custom_pain("The pain in your [affected.name] is maddening!") ..() /datum/surgery_step/generic/clamp_bleeders/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -111,7 +111,7 @@ msg = "[user] starts to pry open the incision and rearrange the organs in [target]'s lower abdomen with \the [tool]." self_msg = "You start to pry open the incision and rearrange the organs in [target]'s lower abdomen with \the [tool]." user.visible_message(msg, self_msg) - target.custom_pain("It feels like the skin on your [affected.name] is on fire!",1) + target.custom_pain("It feels like the skin on your [affected.name] is on fire!") ..() /datum/surgery_step/generic/retract_skin/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -160,7 +160,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] is beginning to cauterize the incision on [target]'s [affected.name] with \the [tool]." , \ "You are beginning to cauterize the incision on [target]'s [affected.name] with \the [tool].") - target.custom_pain("Your [affected.name] is being burned!",1) + target.custom_pain("Your [affected.name] is being burned!") ..() /datum/surgery_step/generic/cauterize/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -219,7 +219,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] is beginning to amputate [target]'s [affected.name] with \the [tool]." , \ "You are beginning to cut through [target]'s [affected.amputation_point] with \the [tool].") - target.custom_pain("Your [affected.amputation_point] is being ripped apart!",1) + target.custom_pain("Your [affected.amputation_point] is being ripped apart!") ..() /datum/surgery_step/generic/amputate/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm index 7518cc701af..c36df974ea3 100644 --- a/code/modules/surgery/implant_removal.dm +++ b/code/modules/surgery/implant_removal.dm @@ -45,7 +45,7 @@ I = locate(/obj/item/implant) in target user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \ "You start poking around inside [target]'s [affected.name] with \the [tool]." ) - target.custom_pain("The pain in your [affected.name] is living hell!",1) + target.custom_pain("The pain in your [affected.name] is living hell!") ..() /datum/surgery_step/extract_implant/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index 9f2d24fd50a..bdc5f763442 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -242,7 +242,7 @@ /obj/item/organ/internal/cyberimp/arm/surgery name = "surgical toolset implant" desc = "A set of surgical tools hidden behind a concealed panel on the user's arm" - contents = newlist(/obj/item/retractor, /obj/item/hemostat, /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw, /obj/item/bonegel, /obj/item/FixOVein, /obj/item/bonesetter) + contents = newlist(/obj/item/retractor/augment, /obj/item/hemostat/augment, /obj/item/cautery/augment, /obj/item/surgicaldrill/augment, /obj/item/scalpel/augment, /obj/item/circular_saw/augment, /obj/item/bonegel/augment, /obj/item/FixOVein/augment, /obj/item/bonesetter/augment) origin_tech = "materials=3;engineering=3;biotech=3;programming=2;magnets=3" // lets make IPCs even *more* vulnerable to EMPs! diff --git a/code/modules/surgery/organs/organ.dm b/code/modules/surgery/organs/organ.dm index 8a29c148253..5837fab5925 100644 --- a/code/modules/surgery/organs/organ.dm +++ b/code/modules/surgery/organs/organ.dm @@ -30,6 +30,7 @@ var/sterile = FALSE //can the organ be infected by germs? var/tough = FALSE //can organ be easily damaged? var/emp_proof = FALSE //is the organ immune to EMPs? + var/hidden_pain = FALSE //will it skip pain messages? /obj/item/organ/Destroy() @@ -232,7 +233,7 @@ if(owner && parent_organ && amount > 0) var/obj/item/organ/external/parent = owner.get_organ(parent_organ) if(parent && !silent) - owner.custom_pain("Something inside your [parent.name] hurts a lot.", 1) + owner.custom_pain("Something inside your [parent.name] hurts a lot.") //check if we've hit max_damage if(damage >= max_damage) @@ -306,7 +307,7 @@ processing_objects |= src if(owner && vital && is_primary_organ()) // I'd do another check for species or whatever so that you couldn't "kill" an IPC by removing a human head from them, but it doesn't matter since they'll come right back from the dead - add_attack_logs(user, owner, "Removed vital organ ([src])", !!user) + add_attack_logs(user, owner, "Removed vital organ ([src])", !!user ? ATKLOG_FEW : ATKLOG_ALL) owner.death() owner = null return src diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index 7c06ec6ef3e..960ce7c0da1 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -272,8 +272,7 @@ This function completely restores a damaged organ to perfect condition. burn_dam = 0 open = 0 //Closing all wounds. internal_bleeding = FALSE - if(istype(src, /obj/item/organ/external/head) && disfigured) //If their head's disfigured, refigure it. - disfigured = 0 + disfigured = FALSE // handle internal organs for(var/obj/item/organ/internal/current_organ in internal_organs) @@ -408,7 +407,7 @@ Note that amputating the affected organ does in fact remove the infection from t var/local_damage = brute_dam + damage if(damage > 15 && local_damage > 30 && prob(damage) && !(status & ORGAN_ROBOT)) internal_bleeding = TRUE - owner.custom_pain("You feel something rip in your [name]!", 1) + owner.custom_pain("You feel something rip in your [name]!") // new damage icon system // returns just the brute/burn damage code @@ -736,19 +735,14 @@ Note that amputating the affected organ does in fact remove the infection from t qdel(spark_system) qdel(src) -/obj/item/organ/external/proc/disfigure(var/type = "brute") +/obj/item/organ/external/proc/disfigure() if(disfigured) return if(owner) - if(type == "brute") - owner.visible_message("You hear a sickening cracking sound coming from \the [owner]'s [name].", \ - "Your [name] becomes a mangled mess!", \ - "You hear a sickening crack.") - else - owner.visible_message("\The [owner]'s [name] melts away, turning into mangled mess!", \ - "Your [name] melts away!", \ - "You hear a sickening sizzle.") - disfigured = 1 + owner.visible_message("You hear a sickening sound coming from \the [owner]'s [name] as it turns into a mangled mess!", \ + "Your [name] becomes a mangled mess!", \ + "You hear a sickening sound.") + disfigured = TRUE /obj/item/organ/external/is_primary_organ(var/mob/living/carbon/human/O = null) if(isnull(O)) diff --git a/code/modules/surgery/organs/pain.dm b/code/modules/surgery/organs/pain.dm index d107c7439c6..e3386aef1b3 100644 --- a/code/modules/surgery/organs/pain.dm +++ b/code/modules/surgery/organs/pain.dm @@ -1,41 +1,28 @@ -mob/var/list/pain_stored = list() -mob/var/last_pain_message = "" -mob/var/next_pain_time = 0 +/mob/living/carbon/human + var/last_pain_message = "" + var/next_pain_time = 0 // partname is the name of a body part // amount is a num from 1 to 100 -mob/living/carbon/proc/pain(var/partname, var/amount, var/force, var/burning = 0) - if(stat >= 2) return +/mob/living/carbon/human/proc/pain(partname, amount) + if(stat >= UNCONSCIOUS) + return if(reagents.has_reagent("sal_acid")) return if(reagents.has_reagent("morphine")) return if(reagents.has_reagent("hydrocodone")) return - if(world.time < next_pain_time && !force) + if(world.time < next_pain_time) return - if(amount > 10 && istype(src,/mob/living/carbon/human)) - if(paralysis) - AdjustParalysis(-round(amount/10)) - if(amount > 50 && prob(amount / 5)) - src:drop_item() var/msg - if(burning) - switch(amount) - if(1 to 10) - msg = "Your [partname] burns." - if(11 to 90) - msg = "Your [partname] burns badly!" - if(91 to 10000) - msg = "OH GOD! Your [partname] is on fire!" - else - switch(amount) - if(1 to 10) - msg = "Your [partname] hurts." - if(11 to 90) - msg = "Your [partname] hurts badly." - if(91 to 10000) - msg = "OH GOD! Your [partname] is hurting terribly!" + switch(amount) + if(1 to 10) + msg = "Your [partname] hurts." + if(11 to 90) + msg = "Your [partname] hurts badly." + if(91 to INFINITY) + msg = "OH GOD! Your [partname] is hurting terribly!" if(msg && (msg != last_pain_message || prob(10))) last_pain_message = msg to_chat(src, msg) @@ -43,20 +30,18 @@ mob/living/carbon/proc/pain(var/partname, var/amount, var/force, var/burning = 0 // message is the custom message to be displayed -// flash_strength is 0 for weak pain flash, 1 for strong pain flash -mob/living/carbon/human/proc/custom_pain(var/message, var/flash_strength) - if(stat >= 1) return +mob/living/carbon/human/proc/custom_pain(message) + if(stat >= UNCONSCIOUS) + return if(NO_PAIN in species.species_traits) return - if(reagents.has_reagent("morphine")) return if(reagents.has_reagent("hydrocodone")) return - var/msg = "[message]" - if(flash_strength >= 1) - msg = "[message]" + + var/msg = "[message]" // Anti message spam checks if(msg && ((msg != last_pain_message) || (world.time >= next_pain_time))) @@ -67,70 +52,33 @@ mob/living/carbon/human/proc/custom_pain(var/message, var/flash_strength) mob/living/carbon/human/proc/handle_pain() // not when sleeping - if(NO_PAIN in species.species_traits) - //While synthetics don't feel pain, they will notice their gears gunking up with residue (toxins) - if(isSynthetic()) - var/toxDamageMessage = null - var/toxMessageProb = 1 - switch(getToxLoss()) - if(25 to 50) - toxMessageProb = 1 - toxDamageMessage = "Your servos seem to be working harder." - if(50 to 75) - toxMessageProb = 2 - toxDamageMessage = "Your joints seem to stick randomly." - if(75 to INFINITY) - toxMessageProb = 5 - toxDamageMessage = "Your motors seem to slip; it really grinds your gears!" - if(toxDamageMessage && prob(toxMessageProb)) - src.custom_pain(toxDamageMessage, getToxLoss() >= 15) + if(stat >= UNCONSCIOUS) + return + if(NO_PAIN in species.species_traits) return - - if(stat >= 2) return if(reagents.has_reagent("morphine")) return if(reagents.has_reagent("hydrocodone")) return + var/maxdam = 0 var/obj/item/organ/external/damaged_organ = null for(var/obj/item/organ/external/E in bodyparts) - if(E.status & ORGAN_DEAD|ORGAN_ROBOT) continue + if((E.status & ORGAN_DEAD|ORGAN_ROBOT) || E.hidden_pain) + continue var/dam = E.get_damage() // make the choice of the organ depend on damage, // but also sometimes use one of the less damaged ones - if(dam > maxdam && (maxdam == 0 || prob(70)) ) + if(dam > maxdam && (maxdam == 0 || prob(70))) damaged_organ = E maxdam = dam if(damaged_organ) - pain(damaged_organ.name, maxdam, 0) - + pain(damaged_organ.name, maxdam) // Damage to internal organs hurts a lot. for(var/obj/item/organ/internal/I in internal_organs) - if(istype(I, /obj/item/organ/internal/brain)) //the brain has no pain receptors, and brain damage is meant to be a stealthy damage type. + if(I.hidden_pain) continue - if(I.damage > 2) if(prob(2)) + if(I.damage > 2 && prob(2)) var/obj/item/organ/external/parent = get_organ(I.parent_organ) - src.custom_pain("You feel a sharp pain in your [parent.limb_name]", 1) - - var/toxDamageMessage = null - var/toxMessageProb = 1 - switch(getToxLoss()) - if(1 to 5) - toxMessageProb = 1 - toxDamageMessage = "Your body stings slightly." - if(6 to 10) - toxMessageProb = 2 - toxDamageMessage = "Your whole body hurts a little." - if(11 to 15) - toxMessageProb = 2 - toxDamageMessage = "Your whole body hurts." - if(15 to 25) - toxMessageProb = 3 - toxDamageMessage = "Your whole body hurts badly." - if(26 to INFINITY) - toxMessageProb = 5 - toxDamageMessage = "Your body aches all over, it's driving you mad." - - if(toxDamageMessage && prob(toxMessageProb)) - src.custom_pain(toxDamageMessage, getToxLoss() >= 15) + custom_pain("You feel a sharp pain in your [parent.limb_name]") \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/standard.dm b/code/modules/surgery/organs/subtypes/standard.dm index 3fd8effd56a..30c4e173cdc 100644 --- a/code/modules/surgery/organs/subtypes/standard.dm +++ b/code/modules/surgery/organs/subtypes/standard.dm @@ -211,11 +211,8 @@ /obj/item/organ/external/head/receive_damage(brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list(), ignore_resists = FALSE) ..(brute, burn, sharp, used_weapon, forbidden_limbs, ignore_resists) if(!disfigured) - if(brute_dam > 40) - if(prob(50)) - disfigure("brute") - if(burn_dam > 40) - disfigure("burn") + if(brute_dam + burn_dam > 50) + disfigure() /obj/item/organ/external/head/proc/handle_alt_icon() if(alt_head && alt_heads_list[alt_head]) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 1af925c3166..4c0094592e9 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -116,7 +116,7 @@ if(affected) user.visible_message("[user] starts transplanting [tool] into [target]'s [affected.name].", \ "You start transplanting [tool] into [target]'s [affected.name].") - H.custom_pain("Someone's rooting around in your [affected.name]!",1) + H.custom_pain("Someone's rooting around in your [affected.name]!") else user.visible_message("[user] starts transplanting [tool] into [target]'s [parse_zone(target_zone)].", \ "You start transplanting [tool] into [target]'s [parse_zone(target_zone)].") @@ -143,7 +143,7 @@ self_msg = "You begin injecting [tool] into [target]'s [I.name]." user.visible_message(msg, self_msg) if(H && affected) - H.custom_pain("Something burns horribly in your [affected.name]!",1) + H.custom_pain("Something burns horribly in your [affected.name]!") else if(implement_type in implements_finsh) //same as surgery step /datum/surgery_step/open_encased/close/ @@ -159,7 +159,7 @@ user.visible_message(msg, self_msg) if(H && affected) - H.custom_pain("Something hurts horribly in your [affected.name]!",1) + H.custom_pain("Something hurts horribly in your [affected.name]!") else if(implement_type in implements_extract) current_type = "extract" @@ -188,7 +188,7 @@ user.visible_message("[user] starts to separate [target]'s [I] with [tool].", \ "You start to separate [target]'s [I] with [tool] for removal." ) if(H && affected) - H.custom_pain("The pain in your [affected.name] is living hell!",1) + H.custom_pain("The pain in your [affected.name] is living hell!") else return -1 @@ -221,7 +221,7 @@ to_chat(user, "[I] does not appear to be damaged.") if(affected) - H.custom_pain("The pain in your [affected.name] is living hell!", 1) + H.custom_pain("The pain in your [affected.name] is living hell!") else if(istype(tool, /obj/item/reagent_containers/food/snacks/organ)) to_chat(user, "[tool] was bitten by someone! It's too damaged to use!") diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index 012f7ad3c5b..455a6a8de04 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -80,7 +80,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts patching the damaged vein in [target]'s [affected.name] with \the [tool]." , \ "You start patching the damaged vein in [target]'s [affected.name] with \the [tool].") - target.custom_pain("The pain in [affected.name] is unbearable!",1) + target.custom_pain("The pain in [affected.name] is unbearable!") ..() /datum/surgery_step/fix_vein/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -133,7 +133,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts cutting away necrotic tissue in [target]'s [affected.name] with \the [tool]." , \ "You start cutting away necrotic tissue in [target]'s [affected.name] with \the [tool].") - target.custom_pain("The pain in [affected.name] is unbearable!",1) + target.custom_pain("The pain in [affected.name] is unbearable!") ..() /datum/surgery_step/fix_dead_tissue/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -191,7 +191,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts applying medication to the affected tissue in [target]'s [affected.name] with \the [tool]." , \ "You start applying medication to the affected tissue in [target]'s [affected.name] with \the [tool].") - target.custom_pain("Something in your [affected.name] is causing you a lot of pain!",1) + target.custom_pain("Something in your [affected.name] is causing you a lot of pain!") ..() /datum/surgery_step/treat_necrosis/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -241,7 +241,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery/remove_thrall name = "Remove Shadow Tumor" - steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/open_encased/saw,/datum/surgery_step/open_encased/retract, /datum/surgery_step/internal/dethrall, /datum/surgery_step/glue_bone, /datum/surgery_step/set_bone,/datum/surgery_step/finish_bone,/datum/surgery_step/generic/cauterize) + steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/internal/dethrall, /datum/surgery_step/generic/cauterize) possible_locs = list("head", "chest", "groin") /datum/surgery/remove_thrall/synth diff --git a/code/modules/surgery/plastic_surgery.dm b/code/modules/surgery/plastic_surgery.dm new file mode 100644 index 00000000000..4d14d2e8a79 --- /dev/null +++ b/code/modules/surgery/plastic_surgery.dm @@ -0,0 +1,56 @@ +/datum/surgery/plastic_surgery + name = "Plastic Surgery" + steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/reshape_face, /datum/surgery_step/generic/cauterize) + possible_locs = list("head") + +/datum/surgery/plastic_surgery/can_start(mob/user, mob/living/carbon/target) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + var/obj/item/organ/external/head/head = H.get_organ(user.zone_sel.selecting) + if(!head) + return FALSE + if(head.status & ORGAN_ROBOT) + return FALSE + return TRUE + + +/datum/surgery_step/reshape_face + name = "reshape face" + allowed_tools = list(/obj/item/scalpel = 100, /obj/item/kitchen/knife = 50, /obj/item/wirecutters = 35) + time = 64 + +/datum/surgery_step/reshape_face/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] begins to alter [target]'s appearance.", "You begin to alter [target]'s appearance...") + +/datum/surgery_step/reshape_face/end_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/obj/item/organ/external/head/head = target.get_organ(target_zone) + var/species_names = target.get_species() + if(head.disfigured) + head.disfigured = FALSE + user.visible_message("[user] successfully restores [target]'s appearance!", "You successfully restore [target]'s appearance.") + else + var/list/names = list() + if(!isabductor(user)) + for(var/i in 1 to 10) + names += random_name(target.gender, species_names) + else + for(var/_i in 1 to 9) + names += "Subject [target.gender == MALE ? "i" : "o"]-[pick("a", "b", "c", "d", "e")]-[rand(10000, 99999)]" + names += random_name(target.gender, species_names) //give one normal name in case they want to do regular plastic surgery + var/chosen_name = input(user, "Choose a new name to assign.", "Plastic Surgery") as null|anything in names + if(!chosen_name) + return + var/oldname = target.real_name + target.real_name = chosen_name + var/newname = target.real_name //something about how the code handles names required that I use this instead of target.real_name + user.visible_message("[user] alters [oldname]'s appearance completely, [target.p_they()] [target.p_are()] now [newname]!", "You alter [oldname]'s appearance completely, [target.p_they()] [target.p_are()] now [newname].") + target.sec_hud_set_ID() + return TRUE + + +/datum/surgery_step/reshape_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/obj/item/organ/external/head/head = target.get_organ(target_zone) + user.visible_message(" [user]'s hand slips, tearing skin on [target]'s face with [tool]!", \ + " Your hand slips, tearing skin on [target]'s face with [tool]!") + target.apply_damage(10, BRUTE, head, sharp = TRUE) + return FALSE \ No newline at end of file diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 58b570eb5e3..ed82328c47d 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -248,10 +248,7 @@ user.visible_message(" [user] finishes patching damage to [target]'s [affected.name] with \the [tool].", \ " You finish patching damage to [target]'s [affected.name] with \the [tool].") affected.heal_damage(rand(30,50),0,1,1) - if(affected.disfigured) - affected.disfigured = 0 - affected.update_icon() - target.regenerate_icons() + affected.disfigured = FALSE if("burn") user.visible_message(" [user] finishes splicing cable into [target]'s [affected.name].", \ " You finishes splicing new cable into [target]'s [affected.name].") @@ -325,7 +322,7 @@ user.visible_message("[user] begins reattaching [target]'s [tool].", \ "You start reattaching [target]'s [tool].") - target.custom_pain("Someone's rooting around in your [affected.name]!",1) + target.custom_pain("Someone's rooting around in your [affected.name]!") else if(istype(tool,/obj/item/mmi)) current_type = "install" @@ -386,7 +383,7 @@ user.visible_message("[user] starts to decouple [target]'s [I] with \the [tool].", \ "You start to decouple [target]'s [I] with \the [tool]." ) - target.custom_pain("The pain in your [affected.name] is living hell!",1) + target.custom_pain("The pain in your [affected.name] is living hell!") else return -1 @@ -407,7 +404,7 @@ to_chat(user, "There are no damaged components in [affected].") return -1 - target.custom_pain("The pain in your [affected.name] is living hell!",1) + target.custom_pain("The pain in your [affected.name] is living hell!") else if(implement_type in implements_finish) current_type = "finish" @@ -522,7 +519,7 @@ user.visible_message("[user] starts to decouple [target]'s [affected.name] with \the [tool].", \ "You start to decouple [target]'s [affected.name] with \the [tool]." ) - target.custom_pain("Your [affected.amputation_point] is being ripped apart!",1) + target.custom_pain("Your [affected.amputation_point] is being ripped apart!") ..() /datum/surgery_step/robotics/external/amputate/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index a0d5cf335a9..53691dd0264 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -8,6 +8,10 @@ w_class = WEIGHT_CLASS_SMALL origin_tech = "materials=1;biotech=1" +/obj/item/retractor/augment + desc = "Micro-mechanical manipulator for retracting stuff." + w_class = WEIGHT_CLASS_TINY + toolspeed = 0.5 /obj/item/hemostat name = "hemostat" @@ -20,6 +24,9 @@ origin_tech = "materials=1;biotech=1" attack_verb = list("attacked", "pinched") +/obj/item/hemostat/augment + desc = "Tiny servos power a pair of pincers to stop bleeding." + toolspeed = 0.5 /obj/item/cautery name = "cautery" @@ -32,6 +39,9 @@ origin_tech = "materials=1;biotech=1" attack_verb = list("burnt") +/obj/item/cautery/augment + desc = "A heated element that cauterizes wounds." + toolspeed = 0.5 /obj/item/surgicaldrill name = "surgical drill" @@ -52,6 +62,12 @@ "[user] is pressing [src] to [user.p_their()] chest and activating it! It looks like [user.p_theyre()] trying to commit suicide.")) return (BRUTELOSS) +/obj/item/surgicaldrill/augment + desc = "Effectively a small power drill contained within your arm, edges dulled to prevent tissue damage. May or may not pierce the heavens." + hitsound = 'sound/weapons/circsawhit.ogg' + force = 10 + w_class = WEIGHT_CLASS_SMALL + toolspeed = 0.5 /obj/item/scalpel name = "scalpel" @@ -78,6 +94,10 @@ return (BRUTELOSS) +/obj/item/scalpel/augment + desc = "Ultra-sharp blade attached directly to your bone for extra-accuracy." + toolspeed = 0.5 + /* * Researchable Scalpels */ @@ -129,6 +149,12 @@ origin_tech = "biotech=1;combat=1" attack_verb = list("attacked", "slashed", "sawed", "cut") +/obj/item/circular_saw/augment + desc = "A small but very fast spinning saw. Edges dulled to prevent accidental cutting inside of the surgeon." + force = 10 + w_class = WEIGHT_CLASS_SMALL + toolspeed = 0.5 + //misc, formerly from code/defines/weapons.dm /obj/item/bonegel name = "bone gel" @@ -139,6 +165,9 @@ throwforce = 1.0 origin_tech = "materials=1;biotech=1" +/obj/item/bonegel/augment + toolspeed = 0.5 + /obj/item/FixOVein name = "FixOVein" icon = 'icons/obj/surgery.dmi' @@ -148,6 +177,9 @@ origin_tech = "materials=1;biotech=1" w_class = WEIGHT_CLASS_SMALL +/obj/item/FixOVein/augment + toolspeed = 0.5 + /obj/item/bonesetter name = "bone setter" icon = 'icons/obj/surgery.dmi' @@ -160,6 +192,9 @@ attack_verb = list("attacked", "hit", "bludgeoned") origin_tech = "materials=1;biotech=1" +/obj/item/bonesetter/augment + toolspeed = 0.5 + /obj/item/surgical_drapes name = "surgical drapes" desc = "Nanotrasen brand surgical drapes provide optimal safety and infection control." diff --git a/config/example/dbconfig.txt b/config/example/dbconfig.txt index a962b4b685c..563768b69bc 100644 --- a/config/example/dbconfig.txt +++ b/config/example/dbconfig.txt @@ -9,7 +9,7 @@ ## This value must be set to the version of the paradise schema in use. ## If this value does not match, the SQL database will not be loaded and an error will be generated. ## Roundstart will be delayed. -DB_VERSION 2 +DB_VERSION 4 ## Server the MySQL database can be found at. # Examples: localhost, 200.135.5.43, www.mysqldb.com, etc. @@ -26,11 +26,11 @@ FEEDBACK_DATABASE feedback ## Note, this does not change the table names in the database, you will have to do that yourself. ## IE: ## FEEDBACK_TABLEPREFIX erro_ -## FEEDBACK_TABLEPREFIX +## FEEDBACK_TABLEPREFIX ## FEEDBACK_TABLEPREFIX SS13_ ## ## Leave as is if you are using the standard schema file. -FEEDBACK_TABLEPREFIX +FEEDBACK_TABLEPREFIX ## Username/Login used to access the database. FEEDBACK_LOGIN username diff --git a/config/example/jobs_highpop.txt b/config/example/jobs_highpop.txt new file mode 100644 index 00000000000..962803ab886 --- /dev/null +++ b/config/example/jobs_highpop.txt @@ -0,0 +1,37 @@ +Captain=1 +Head of Personnel=1 +Head of Security=1 +Chief Engineer=1 +Research Director=1 +Chief Medical Officer=1 + +Station Engineer=5 +Roboticist=1 + +Medical Doctor=5 +Geneticist=2 +Virologist=1 + +Scientist=3 +Chemist=2 + +Bartender=1 +Botanist=2 +Chef=1 +Janitor=1 +Quartermaster=1 +Shaft Miner=3 + +Warden=1 +Detective=1 +Security Officer=7 + +Assistant=-1 +Atmospheric Technician=4 +Cargo Technician=3 +Chaplain=1 +Lawyer=2 +Librarian=1 + +AI=1 +Cyborg=1 \ No newline at end of file diff --git a/html/changelog.html b/html/changelog.html index 22c77125162..c661f36509d 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,77 @@ -->
+

13 June 2018

+

Aurorablade updated:

+
    +
  • Fluff for Panzerskull
  • +
+

Fox McCloud updated:

+
    +
  • Medibots now actually talk, like beepsky
  • +
  • Adds Plastic surgery; fix someone's face or give them a new identity!
  • +
  • Having more than 50 cloneloss will render you "Unknown"
  • +
  • head disfigurement requires you to have more than 50 combined brute and burn damage, rather than tracking it separately
  • +
  • Fixes Cryoxadone and Rezadone not fixing disfigurement, Fixes fluorosulfuric acid not causing disfigurement at proper thresholds
  • +
  • Fixes syndicate medibot not being constructable from tactical medkits
  • +
  • Syndicate medibot and the mysterious medibot are better at treating brute and burn damage
  • +
  • Radiation event reworked; graphics updated--effects may be a bit more deadly
  • +
  • Buffed DIY chainsaws damage slightly
  • +
  • You now flip about when you spin with a double e-sword
  • +
  • Adds surgical augment to R&D
  • +
  • Tools on surgical augment are slightly faster at surgery
  • +
  • Wishgranter grants "Avatar of the Wishgranter" instead of making you a superhero
  • +
  • Toxin damage is stealthier and will no longer cause stinging spam message
  • +
+

Kyep updated:

+
    +
  • Additional job slots are now available at 80+ server population.
  • +
+

MINIMAN10000 updated:

+
    +
  • Airlock electronics lock
  • +
  • Airlock electronics close button
  • +
+

Piccione updated:

+
    +
  • Added Magboots to the Paramedic's EVA gear closet
  • +
+

Tayyyyyyy updated:

+
    +
  • Shadowling dethrall has been shortened to scalpel, hemostat, retractor, shine light, cautery
  • +
+ +

11 June 2018

+

FalseIncarnate updated:

+
    +
  • Food on utensils now properly inherits the name of the source dish.
  • +
  • Joined Souls rune can now properly can summon restrained targets with 3+ invokers.
  • +
+ +

09 June 2018

+

Fox McCloud updated:

+
    +
  • Fixes holobarrier icons being missing
  • +
+ +

08 June 2018

+

Alffd updated:

+
    +
  • Adds an automated emergency var on air alarms for mappers
  • +
+

Anasari updated:

+
    +
  • Fixes admin log for spray displaying (0,0,0) all the time.
  • +
+

Desolate updated:

+
    +
  • ED-209 code corrected to work properly. Floorbot code corrected to work properly.
  • +
+

and Dumbdumb updated:

+
    +
  • Unathi and Vox Sec Hardsuit update
  • +
+

05 June 2018

Kyep updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index b57f3e4bc83..6cec07f4761 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -6464,3 +6464,53 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. Kyep: - bugfix: The Terror Spider away mission now has spiders colonizing the west side of the map. Only the gateway room is safe. +2018-06-08: + Alffd: + - rscadd: Adds an automated emergency var on air alarms for mappers + Anasari: + - bugfix: Fixes admin log for spray displaying (0,0,0) all the time. + Desolate: + - bugfix: ED-209 code corrected to work properly. Floorbot code corrected to work + properly. + and Dumbdumb: + - rscadd: Unathi and Vox Sec Hardsuit update +2018-06-09: + Fox McCloud: + - bugfix: Fixes holobarrier icons being missing +2018-06-11: + FalseIncarnate: + - bugfix: Food on utensils now properly inherits the name of the source dish. + - bugfix: Joined Souls rune can now properly can summon restrained targets with + 3+ invokers. +2018-06-13: + Aurorablade: + - rscadd: Fluff for Panzerskull + Fox McCloud: + - rscadd: Medibots now actually talk, like beepsky + - rscadd: Adds Plastic surgery; fix someone's face or give them a new identity! + - tweak: Having more than 50 cloneloss will render you "Unknown" + - tweak: head disfigurement requires you to have more than 50 combined brute and + burn damage, rather than tracking it separately + - bugfix: Fixes Cryoxadone and Rezadone not fixing disfigurement, Fixes fluorosulfuric + acid not causing disfigurement at proper thresholds + - bugfix: Fixes syndicate medibot not being constructable from tactical medkits + - tweak: Syndicate medibot and the mysterious medibot are better at treating brute + and burn damage + - tweak: Radiation event reworked; graphics updated--effects may be a bit more deadly + - tweak: Buffed DIY chainsaws damage slightly + - tweak: You now flip about when you spin with a double e-sword + - rscadd: Adds surgical augment to R&D + - tweak: Tools on surgical augment are slightly faster at surgery + - rscadd: Wishgranter grants "Avatar of the Wishgranter" instead of making you a + superhero + - tweak: Toxin damage is stealthier and will no longer cause stinging spam message + Kyep: + - rscadd: Additional job slots are now available at 80+ server population. + MINIMAN10000: + - rscdel: Airlock electronics lock + - bugfix: Airlock electronics close button + Piccione: + - rscadd: Added Magboots to the Paramedic's EVA gear closet + Tayyyyyyy: + - tweak: Shadowling dethrall has been shortened to scalpel, hemostat, retractor, + shine light, cautery diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 24515e61641..060d8b77a27 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/effects/weather_effects.dmi b/icons/effects/weather_effects.dmi index 215cf53556f..da1523706e2 100644 Binary files a/icons/effects/weather_effects.dmi and b/icons/effects/weather_effects.dmi differ diff --git a/icons/mob/species/unathi/helmet.dmi b/icons/mob/species/unathi/helmet.dmi index f969705ec83..14b099f3f45 100644 Binary files a/icons/mob/species/unathi/helmet.dmi and b/icons/mob/species/unathi/helmet.dmi differ diff --git a/icons/mob/species/unathi/suit.dmi b/icons/mob/species/unathi/suit.dmi index ebbfa5f9c73..1d0bcf81f27 100644 Binary files a/icons/mob/species/unathi/suit.dmi and b/icons/mob/species/unathi/suit.dmi differ diff --git a/icons/mob/species/vox/collar.dmi b/icons/mob/species/vox/collar.dmi index c0b8c6ba936..6c442c62f77 100644 Binary files a/icons/mob/species/vox/collar.dmi and b/icons/mob/species/vox/collar.dmi differ diff --git a/icons/mob/species/vox/helmet.dmi b/icons/mob/species/vox/helmet.dmi index c9227ce2119..a7186d611b6 100644 Binary files a/icons/mob/species/vox/helmet.dmi and b/icons/mob/species/vox/helmet.dmi differ diff --git a/icons/mob/species/vox/suit.dmi b/icons/mob/species/vox/suit.dmi index ca8289a3ccb..3af770d719a 100644 Binary files a/icons/mob/species/vox/suit.dmi and b/icons/mob/species/vox/suit.dmi differ diff --git a/icons/mob/ties.dmi b/icons/mob/ties.dmi index b3f92a3b57f..db92d8c21a6 100644 Binary files a/icons/mob/ties.dmi and b/icons/mob/ties.dmi differ diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index a63ff4f5daa..d1aa0e9805a 100644 Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ diff --git a/icons/obj/clothing/species/unathi/hats.dmi b/icons/obj/clothing/species/unathi/hats.dmi index be2fb4f62aa..1ee46571f66 100644 Binary files a/icons/obj/clothing/species/unathi/hats.dmi and b/icons/obj/clothing/species/unathi/hats.dmi differ diff --git a/icons/obj/clothing/species/unathi/suits.dmi b/icons/obj/clothing/species/unathi/suits.dmi index 34c3ea75105..30b590cc7ed 100644 Binary files a/icons/obj/clothing/species/unathi/suits.dmi and b/icons/obj/clothing/species/unathi/suits.dmi differ diff --git a/icons/obj/custom_items.dmi b/icons/obj/custom_items.dmi index 940f2ba25da..8296c4ceb7d 100644 Binary files a/icons/obj/custom_items.dmi and b/icons/obj/custom_items.dmi differ diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi index 22dc1384904..288785052cd 100644 Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ diff --git a/icons/obj/status_display.dmi b/icons/obj/status_display.dmi index b131da89349..81ccc415de1 100644 Binary files a/icons/obj/status_display.dmi and b/icons/obj/status_display.dmi differ diff --git a/paradise.dme b/paradise.dme index be0e062f082..e161ae03eb0 100644 --- a/paradise.dme +++ b/paradise.dme @@ -198,7 +198,6 @@ #include "code\controllers\Processes\obj.dm" #include "code\controllers\Processes\shuttles.dm" #include "code\controllers\Processes\ticker.dm" -#include "code\controllers\Processes\weather.dm" #include "code\controllers\ProcessScheduler\core\process.dm" #include "code\controllers\ProcessScheduler\core\processScheduler.dm" #include "code\controllers\subsystem\air.dm" @@ -213,6 +212,7 @@ #include "code\controllers\subsystem\sun.dm" #include "code\controllers\subsystem\throwing.dm" #include "code\controllers\subsystem\timer.dm" +#include "code\controllers\subsystem\weather.dm" #include "code\controllers\subsystem\processing\processing.dm" #include "code\datums\action.dm" #include "code\datums\ai_law_sets.dm" @@ -241,11 +241,6 @@ #include "code\datums\uplink_item.dm" #include "code\datums\vision_override.dm" #include "code\datums\vr.dm" -#include "code\datums\antagonists\antag_datum.dm" -#include "code\datums\antagonists\antag_helpers.dm" -#include "code\datums\antagonists\antag_hud.dm" -#include "code\datums\antagonists\antag_spawner.dm" -#include "code\datums\antagonists\antag_team.dm" #include "code\datums\cache\air_alarm.dm" #include "code\datums\cache\apc.dm" #include "code\datums\cache\cache.dm" @@ -318,6 +313,7 @@ #include "code\datums\helper_datums\topic_input.dm" #include "code\datums\looping_sounds\looping_sound.dm" #include "code\datums\looping_sounds\machinery_sounds.dm" +#include "code\datums\looping_sounds\weather.dm" #include "code\datums\outfits\outfit.dm" #include "code\datums\outfits\outfit_admin.dm" #include "code\datums\ruins\space.dm" @@ -357,7 +353,10 @@ #include "code\datums\status_effects\status_effect.dm" #include "code\datums\vr\level.dm" #include "code\datums\weather\weather.dm" -#include "code\datums\weather\weather_types.dm" +#include "code\datums\weather\weather_types\ash_storm.dm" +#include "code\datums\weather\weather_types\floor_is_lava.dm" +#include "code\datums\weather\weather_types\radiation_storm.dm" +#include "code\datums\weather\weather_types\snow_storm.dm" #include "code\datums\wires\airlock.dm" #include "code\datums\wires\alarm.dm" #include "code\datums\wires\apc.dm" @@ -530,6 +529,7 @@ #include "code\game\jobs\job_controller.dm" #include "code\game\jobs\job_exp.dm" #include "code\game\jobs\job_objective.dm" +#include "code\game\jobs\job_scaling.dm" #include "code\game\jobs\jobs.dm" #include "code\game\jobs\whitelist.dm" #include "code\game\jobs\job\central.dm" @@ -1138,6 +1138,12 @@ #include "code\modules\alarm\fire_alarm.dm" #include "code\modules\alarm\motion_alarm.dm" #include "code\modules\alarm\power_alarm.dm" +#include "code\modules\antagonists\_common\antag_datum.dm" +#include "code\modules\antagonists\_common\antag_helpers.dm" +#include "code\modules\antagonists\_common\antag_hud.dm" +#include "code\modules\antagonists\_common\antag_spawner.dm" +#include "code\modules\antagonists\_common\antag_team.dm" +#include "code\modules\antagonists\wishgranter\wishgranter.dm" #include "code\modules\arcade\arcade_base.dm" #include "code\modules\arcade\arcade_prize.dm" #include "code\modules\arcade\claw_game.dm" @@ -2109,6 +2115,7 @@ #include "code\modules\research\xenobiology\xenobio_camera.dm" #include "code\modules\research\xenobiology\xenobiology.dm" #include "code\modules\ruins\ruin_areas.dm" +#include "code\modules\scripting\__defines.dm" #include "code\modules\scripting\Errors.dm" #include "code\modules\scripting\Options.dm" #include "code\modules\scripting\AST\AST Nodes.dm" @@ -2159,7 +2166,6 @@ #include "code\modules\surgery\cavity_implant.dm" #include "code\modules\surgery\dental_implant.dm" #include "code\modules\surgery\encased.dm" -#include "code\modules\surgery\face.dm" #include "code\modules\surgery\generic.dm" #include "code\modules\surgery\helpers.dm" #include "code\modules\surgery\implant_removal.dm" @@ -2167,6 +2173,7 @@ #include "code\modules\surgery\limb_reattach.dm" #include "code\modules\surgery\organs_internal.dm" #include "code\modules\surgery\other.dm" +#include "code\modules\surgery\plastic_surgery.dm" #include "code\modules\surgery\remove_embedded_object.dm" #include "code\modules\surgery\rig_removal.dm" #include "code\modules\surgery\robotics.dm" diff --git a/sound/lavaland/ash_storm_end.ogg b/sound/lavaland/ash_storm_end.ogg deleted file mode 100644 index f9b01453dda..00000000000 Binary files a/sound/lavaland/ash_storm_end.ogg and /dev/null differ diff --git a/sound/lavaland/ash_storm_start.ogg b/sound/lavaland/ash_storm_start.ogg deleted file mode 100644 index 4b9bebffd08..00000000000 Binary files a/sound/lavaland/ash_storm_start.ogg and /dev/null differ diff --git a/sound/lavaland/ash_storm_windup.ogg b/sound/lavaland/ash_storm_windup.ogg deleted file mode 100644 index a9f0fa3270e..00000000000 Binary files a/sound/lavaland/ash_storm_windup.ogg and /dev/null differ diff --git a/sound/voice/mapple.ogg b/sound/voice/mapple.ogg new file mode 100644 index 00000000000..21e26742ca1 Binary files /dev/null and b/sound/voice/mapple.ogg differ diff --git a/sound/voice/mcatch.ogg b/sound/voice/mcatch.ogg new file mode 100644 index 00000000000..07b8aaab75c Binary files /dev/null and b/sound/voice/mcatch.ogg differ diff --git a/sound/voice/mcoming.ogg b/sound/voice/mcoming.ogg new file mode 100644 index 00000000000..d3eb9e467f4 Binary files /dev/null and b/sound/voice/mcoming.ogg differ diff --git a/sound/voice/mdelicious.ogg b/sound/voice/mdelicious.ogg new file mode 100644 index 00000000000..5158538580e Binary files /dev/null and b/sound/voice/mdelicious.ogg differ diff --git a/sound/voice/mfeelbetter.ogg b/sound/voice/mfeelbetter.ogg new file mode 100644 index 00000000000..fdbe57fd2e9 Binary files /dev/null and b/sound/voice/mfeelbetter.ogg differ diff --git a/sound/voice/mflies.ogg b/sound/voice/mflies.ogg new file mode 100644 index 00000000000..831281ebbee Binary files /dev/null and b/sound/voice/mflies.ogg differ diff --git a/sound/voice/mhelp.ogg b/sound/voice/mhelp.ogg new file mode 100644 index 00000000000..516d5db068d Binary files /dev/null and b/sound/voice/mhelp.ogg differ diff --git a/sound/voice/minjured.ogg b/sound/voice/minjured.ogg new file mode 100644 index 00000000000..0e968b3980c Binary files /dev/null and b/sound/voice/minjured.ogg differ diff --git a/sound/voice/minsult.ogg b/sound/voice/minsult.ogg new file mode 100644 index 00000000000..017292977a1 Binary files /dev/null and b/sound/voice/minsult.ogg differ diff --git a/sound/voice/mlive.ogg b/sound/voice/mlive.ogg new file mode 100644 index 00000000000..ceb0dec9a34 Binary files /dev/null and b/sound/voice/mlive.ogg differ diff --git a/sound/voice/mlost.ogg b/sound/voice/mlost.ogg new file mode 100644 index 00000000000..7b332ac346a Binary files /dev/null and b/sound/voice/mlost.ogg differ diff --git a/sound/voice/mno.ogg b/sound/voice/mno.ogg new file mode 100644 index 00000000000..030e43a0109 Binary files /dev/null and b/sound/voice/mno.ogg differ diff --git a/sound/voice/mpatchedup.ogg b/sound/voice/mpatchedup.ogg new file mode 100644 index 00000000000..1314f6ee471 Binary files /dev/null and b/sound/voice/mpatchedup.ogg differ diff --git a/sound/voice/mradar.ogg b/sound/voice/mradar.ogg new file mode 100644 index 00000000000..ad347a6d891 Binary files /dev/null and b/sound/voice/mradar.ogg differ diff --git a/sound/voice/msurgeon.ogg b/sound/voice/msurgeon.ogg new file mode 100644 index 00000000000..a300ee57ef6 Binary files /dev/null and b/sound/voice/msurgeon.ogg differ diff --git a/sound/weather/ashstorm/inside/active_end.ogg b/sound/weather/ashstorm/inside/active_end.ogg new file mode 100644 index 00000000000..959bf5773eb Binary files /dev/null and b/sound/weather/ashstorm/inside/active_end.ogg differ diff --git a/sound/weather/ashstorm/inside/active_mid1.ogg b/sound/weather/ashstorm/inside/active_mid1.ogg new file mode 100644 index 00000000000..95244cd2b7c Binary files /dev/null and b/sound/weather/ashstorm/inside/active_mid1.ogg differ diff --git a/sound/weather/ashstorm/inside/active_mid2.ogg b/sound/weather/ashstorm/inside/active_mid2.ogg new file mode 100644 index 00000000000..a45584b9f31 Binary files /dev/null and b/sound/weather/ashstorm/inside/active_mid2.ogg differ diff --git a/sound/weather/ashstorm/inside/active_mid3.ogg b/sound/weather/ashstorm/inside/active_mid3.ogg new file mode 100644 index 00000000000..be2e672fa0e Binary files /dev/null and b/sound/weather/ashstorm/inside/active_mid3.ogg differ diff --git a/sound/weather/ashstorm/inside/active_start.ogg b/sound/weather/ashstorm/inside/active_start.ogg new file mode 100644 index 00000000000..3efab12ef26 Binary files /dev/null and b/sound/weather/ashstorm/inside/active_start.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_end.ogg b/sound/weather/ashstorm/inside/weak_end.ogg new file mode 100644 index 00000000000..416b75a9b84 Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_end.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_mid1.ogg b/sound/weather/ashstorm/inside/weak_mid1.ogg new file mode 100644 index 00000000000..d3211c6b5fc Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_mid1.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_mid2.ogg b/sound/weather/ashstorm/inside/weak_mid2.ogg new file mode 100644 index 00000000000..b6491a7afb8 Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_mid2.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_mid3.ogg b/sound/weather/ashstorm/inside/weak_mid3.ogg new file mode 100644 index 00000000000..95238c72d40 Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_mid3.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_start.ogg b/sound/weather/ashstorm/inside/weak_start.ogg new file mode 100644 index 00000000000..59abf1937dc Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_start.ogg differ diff --git a/sound/weather/ashstorm/outside/active_end.ogg b/sound/weather/ashstorm/outside/active_end.ogg new file mode 100644 index 00000000000..95149d846cc Binary files /dev/null and b/sound/weather/ashstorm/outside/active_end.ogg differ diff --git a/sound/weather/ashstorm/outside/active_mid1.ogg b/sound/weather/ashstorm/outside/active_mid1.ogg new file mode 100644 index 00000000000..189528ab569 Binary files /dev/null and b/sound/weather/ashstorm/outside/active_mid1.ogg differ diff --git a/sound/weather/ashstorm/outside/active_mid2.ogg b/sound/weather/ashstorm/outside/active_mid2.ogg new file mode 100644 index 00000000000..92317f2e0a7 Binary files /dev/null and b/sound/weather/ashstorm/outside/active_mid2.ogg differ diff --git a/sound/weather/ashstorm/outside/active_mid3.ogg b/sound/weather/ashstorm/outside/active_mid3.ogg new file mode 100644 index 00000000000..34846bfd42c Binary files /dev/null and b/sound/weather/ashstorm/outside/active_mid3.ogg differ diff --git a/sound/weather/ashstorm/outside/active_start.ogg b/sound/weather/ashstorm/outside/active_start.ogg new file mode 100644 index 00000000000..8b3acf1a153 Binary files /dev/null and b/sound/weather/ashstorm/outside/active_start.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_end.ogg b/sound/weather/ashstorm/outside/weak_end.ogg new file mode 100644 index 00000000000..55db2fc3565 Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_end.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_mid1.ogg b/sound/weather/ashstorm/outside/weak_mid1.ogg new file mode 100644 index 00000000000..56faa9ad26c Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_mid1.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_mid2.ogg b/sound/weather/ashstorm/outside/weak_mid2.ogg new file mode 100644 index 00000000000..0c836ad220a Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_mid2.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_mid3.ogg b/sound/weather/ashstorm/outside/weak_mid3.ogg new file mode 100644 index 00000000000..f2cbfb0f4b9 Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_mid3.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_start.ogg b/sound/weather/ashstorm/outside/weak_start.ogg new file mode 100644 index 00000000000..1ac59c36f05 Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_start.ogg differ