diff --git a/code/__DEFINES/dcs/signals/atom/mob/living/signals_xeno.dm b/code/__DEFINES/dcs/signals/atom/mob/living/signals_xeno.dm index ab233e9cf82c..e76768a82b46 100644 --- a/code/__DEFINES/dcs/signals/atom/mob/living/signals_xeno.dm +++ b/code/__DEFINES/dcs/signals/atom/mob/living/signals_xeno.dm @@ -50,6 +50,10 @@ /// From /datum/action/xeno_action/proc/use_ability_wrapper(): (mob/owner) #define COMSIG_XENO_ACTION_USED "xeno_action_used" +/// From /datum/action/xeno_action/proc/use_ability_wrapper(): (mob/owner) +#define COMSIG_XENO_PRE_ACTION_USED "xeno_pre_action_used" +/// From /datum/action/xeno_action/proc/use_ability_wrapper(): (mob/owner) +#define COMSIG_XENO_FAILED_ACTION_USED "xeno_failed_action_used" /// From /mob/living/carbon/xenomorph/proc/check_blood_splash() #define COMSIG_XENO_DEAL_ACID_DAMAGE "xeno_deal_acid_damage" /// From /mob/living/carbon/xenomorph/proc/recalculate_speed() diff --git a/code/__DEFINES/dcs/signals/atom/signals_item.dm b/code/__DEFINES/dcs/signals/atom/signals_item.dm index 5ba79960657b..88f99bbff578 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_item.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_item.dm @@ -83,3 +83,5 @@ #define COMSIG_CAMERA_SET_AREA "camera_manager_set_area" #define COMSIG_CAMERA_CLEAR "camera_manager_clear_target" #define COMSIG_CAMERA_REFRESH "camera_manager_refresh" + +#define COMSIG_PRED_BRACER_DECLOAKED "pred_bracer_decloaked" diff --git a/code/__DEFINES/dcs/signals/atom/signals_movable.dm b/code/__DEFINES/dcs/signals/atom/signals_movable.dm index ba889d0b5212..ad4be2b1dc9f 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_movable.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_movable.dm @@ -11,6 +11,9 @@ #define COMPONENT_CANCEL_MOVE (1<<0) /// From /turf/open/gm/river/Entered(): (turf/open/gm/river/river, covered) #define COMSIG_MOVABLE_ENTERED_RIVER "movable_entered_river" +/// From /atom/movable/proc/doMove: I think it only works with forceMove so watch out +#define COMSIG_MOVABLE_FORCEMOVE_PRE_CROSSED "movable_forcemove_pre_crossed" + #define COMPONENT_IGNORE_CROSS (1<<0) ///from /mob/living/carbon/xenomorph/start_pulling(): (mob/living/carbon/xenomorph/X) #define COMSIG_MOVABLE_XENO_START_PULLING "movable_xeno_start_pulling" diff --git a/code/__DEFINES/dcs/signals/signals_datum.dm b/code/__DEFINES/dcs/signals/signals_datum.dm index b798d510763e..c35038fcf3e9 100644 --- a/code/__DEFINES/dcs/signals/signals_datum.dm +++ b/code/__DEFINES/dcs/signals/signals_datum.dm @@ -34,6 +34,8 @@ #define COMSIG_ACTION_HIDDEN "action_hidden" /// From base of /datum/action/proc/unhide_from(): (mob/owner) #define COMSIG_ACTION_UNHIDDEN "action_unhidden" +/// From base of /datum/action/proc/action_activate() : () +#define COMSIG_ACTION_ACTIVATED "action_activated" ///from /datum/component/bonus_damage_stack #define COMSIG_BONUS_DAMAGE "bonus_damage" diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 77f2393e6542..d8f820ab382b 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -113,7 +113,7 @@ #define CANROOT (1<<6) #define GODMODE (1<<12) #define FAKEDEATH (1<<13) //Replaces stuff like changeling.changeling_fakedeath -#define DISFIGURED (1<<14) //I'll probably move this elsewhere if I ever get wround to writing a bitflag mob-damage system +//#define DISFIGURED (1<<14) //unused #define XENO_HOST (1<<15) //Tracks whether we're gonna be a baby alien's mummy. #define IMMOBILE_ACTION (1<<16) // If you are performing an action that prevents you from being pushed by your own people. #define PERMANENTLY_DEAD (1<<17) diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 47aa0e732c76..88496c79d630 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -123,6 +123,7 @@ #define SS_INIT_NIGHTMARE 21.5 #define SS_INIT_TIMETRACK 21.1 #define SS_INIT_HUMANS 21 +#define SS_INIT_WHO 20 #define SS_INIT_POWER 19 #define SS_INIT_INFLUXMCSTATS 12 #define SS_INIT_INFLUXSTATS 11 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 964e77402655..e6b9c4c4b9ee 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -161,6 +161,8 @@ #define TRAIT_MERGED_WITH_WEEDS "merged_with_weeds" /// Apply this to identify a mob as temporarily muted #define TRAIT_TEMPORARILY_MUTED "temporarily_muted" +/// Mob wont get hit by stray projectiles +#define TRAIT_NO_STRAY "trait_no_stray" // SPECIES TRAITS /// Knowledge of Yautja technology diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index e46c92df543a..aa73d6008e02 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -128,17 +128,23 @@ * You should only pass integers in. */ /proc/pick_weight(list/list_to_pick) + if(length(list_to_pick) == 0) + return null + var/total = 0 - var/item - for(item in list_to_pick) + for(var/item in list_to_pick) if(!list_to_pick[item]) list_to_pick[item] = 0 total += list_to_pick[item] - total = rand(0, total) - for(item in list_to_pick) - total -= list_to_pick[item] - if(total <= 0 && list_to_pick[item]) + total = rand(1, total) + for(var/item in list_to_pick) + var/item_weight = list_to_pick[item] + if(item_weight == 0) + continue + + total -= item_weight + if(total <= 0) return item return null diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 5bf36f785746..094f8205c80e 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -235,7 +235,7 @@ * * hive - The hive we're filling a slot for to check if the player is banished * * sorted - Whether to sort by larva_queue_time (default TRUE) or leave unsorted */ -/proc/get_alien_candidates(datum/hive_status/hive = null, sorted = TRUE) +/proc/get_alien_candidates(datum/hive_status/hive = null, sorted = TRUE, abomination = FALSE) var/list/candidates = list() for(var/mob/dead/observer/cur_obs as anything in GLOB.observer_list) @@ -275,6 +275,11 @@ if(banished) continue + if(abomination) + if(!(/datum/tutorial/xenomorph/abomination::tutorial_id in cur_obs.client.prefs.completed_tutorials)) + to_chat(cur_obs, SPAN_BOLDNOTICE("You were passed over for playing as an Abomination because you have not completed its tutorial.")) + continue + candidates += cur_obs // Optionally sort by larva_queue_time diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index d5212611a04b..32ea0f5ec32e 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -87,22 +87,6 @@ result = first ^ second return result -//Pretends to pick an element based on its weight but really just seems to pick a random element. -/proc/pickweight(list/L) - var/total = 0 - var/item - for (item in L) - if (!L[item]) - L[item] = 1 - total += L[item] - - total = rand(1, total) - for (item in L) - total -=L [item] - if (total <= 0) - return item - return null - /// Pick a random element from the list and remove it from the list. /proc/pick_n_take(list/L) RETURN_TYPE(L[_].type) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index facc2b951ad3..d3fc9994414a 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -356,7 +356,6 @@ DEFINE_BITFIELD(status_flags, list( "PASSEMOTES" = PASSEMOTES, "GODMODE" = GODMODE, "FAKEDEATH" = FAKEDEATH, - "DISFIGURED" = DISFIGURED, "XENO_HOST" = XENO_HOST, "IMMOBILE_ACTION" = IMMOBILE_ACTION, "PERMANENTLY_DEAD" = PERMANENTLY_DEAD, diff --git a/code/_globalvars/global_lists.dm b/code/_globalvars/global_lists.dm index c054b9a4bf1f..c6957eefd22c 100644 --- a/code/_globalvars/global_lists.dm +++ b/code/_globalvars/global_lists.dm @@ -119,6 +119,34 @@ GLOBAL_LIST(chemical_reactions_filtered_list) //List of all /datum/chemical_reac GLOBAL_LIST(chemical_reactions_list) //List of all /datum/chemical_reaction datums indexed by reaction id. Used to search for the result instead of the components. GLOBAL_LIST(chemical_reagents_list) //List of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff GLOBAL_LIST(chemical_properties_list) //List of all /datum/chem_property datums indexed by property name +//list of all properties that conflict with each other. +GLOBAL_LIST_INIT_TYPED(conflicting_properties, /list, list( PROPERTY_NUTRITIOUS = PROPERTY_HEMORRAGING, PROPERTY_NUTRITIOUS = PROPERTY_HEMOLYTIC, PROPERTY_TOXIC = PROPERTY_ANTITOXIC,\ + PROPERTY_CORROSIVE = PROPERTY_ANTICORROSIVE, PROPERTY_BIOCIDIC = PROPERTY_NEOGENETIC, PROPERTY_HYPERTHERMIC = PROPERTY_HYPOTHERMIC,\ + PROPERTY_NUTRITIOUS = PROPERTY_KETOGENIC, PROPERTY_PAINING = PROPERTY_PAINKILLING, PROPERTY_HALLUCINOGENIC = PROPERTY_ANTIHALLUCINOGENIC,\ + PROPERTY_HEPATOTOXIC = PROPERTY_HEPATOPEUTIC, PROPERTY_NEPHROTOXIC = PROPERTY_NEPHROPEUTIC, PROPERTY_PNEUMOTOXIC = PROPERTY_PNEUMOPEUTIC,\ + PROPERTY_OCULOTOXIC = PROPERTY_OCULOPEUTIC, PROPERTY_CARDIOTOXIC = PROPERTY_CARDIOPEUTIC, PROPERTY_NEUROTOXIC = PROPERTY_NEUROPEUTIC,\ + PROPERTY_FLUXING = PROPERTY_REPAIRING, PROPERTY_RELAXING = PROPERTY_MUSCLESTIMULATING, PROPERTY_HEMOGENIC = PROPERTY_HEMOLYTIC,\ + PROPERTY_HEMOGENIC = PROPERTY_HEMORRAGING, PROPERTY_NUTRITIOUS = PROPERTY_EMETIC,\ + PROPERTY_HYPERGENETIC = PROPERTY_NEOGENETIC, PROPERTY_HYPERGENETIC = PROPERTY_HEPATOPEUTIC, PROPERTY_HYPERGENETIC = PROPERTY_NEPHROPEUTIC,\ + PROPERTY_HYPERGENETIC = PROPERTY_PNEUMOPEUTIC, PROPERTY_HYPERGENETIC = PROPERTY_OCULOPEUTIC, PROPERTY_HYPERGENETIC = PROPERTY_CARDIOPEUTIC,\ + PROPERTY_HYPERGENETIC = PROPERTY_NEUROPEUTIC, PROPERTY_ADDICTIVE = PROPERTY_ANTIADDICTIVE, PROPERTY_NEUROSHIELDING = PROPERTY_NEUROTOXIC,\ + PROPERTY_HYPOMETABOLIC = PROPERTY_HYPERMETABOLIC, PROPERTY_HYPERTHROTTLING = PROPERTY_NEUROINHIBITING, + PROPERTY_FOCUSING = PROPERTY_NERVESTIMULATING, PROPERTY_THERMOSTABILIZING = PROPERTY_HYPERTHERMIC, PROPERTY_THERMOSTABILIZING = PROPERTY_HYPOTHERMIC, + PROPERTY_AIDING = PROPERTY_NEUROINHIBITING, PROPERTY_OXYGENATING = PROPERTY_HYPOXEMIC, PROPERTY_ANTICARCINOGENIC = PROPERTY_CARCINOGENIC, \ + PROPERTY_CIPHERING = PROPERTY_CIPHERING_PREDATOR, PROPERTY_TRANSFORMATIVE = PROPERTY_ANTITOXIC, PROPERTY_MUSCLESTIMULATING = PROPERTY_NERVESTIMULATING)) +//list of all properties that combine into something else, now featured in global list +GLOBAL_LIST_INIT_TYPED(combining_properties, /list, list( PROPERTY_DEFIBRILLATING = list(PROPERTY_MUSCLESTIMULATING, PROPERTY_CARDIOPEUTIC),\ + PROPERTY_THANATOMETABOL = list(PROPERTY_HYPOXEMIC, PROPERTY_CRYOMETABOLIZING, PROPERTY_NEUROCRYOGENIC),\ + PROPERTY_HYPERDENSIFICATING = list(PROPERTY_MUSCLESTIMULATING, PROPERTY_BONEMENDING, PROPERTY_CARCINOGENIC),\ + PROPERTY_HYPERTHROTTLING = list(PROPERTY_PSYCHOSTIMULATING, PROPERTY_HALLUCINOGENIC),\ + PROPERTY_NEUROSHIELDING = list(PROPERTY_ALCOHOLIC, PROPERTY_BALDING),\ + PROPERTY_ANTIADDICTIVE = list(PROPERTY_PSYCHOSTIMULATING, PROPERTY_ANTIHALLUCINOGENIC),\ + PROPERTY_ADDICTIVE = list(PROPERTY_PSYCHOSTIMULATING, PROPERTY_NEUROTOXIC),\ + PROPERTY_CIPHERING_PREDATOR = list(PROPERTY_CIPHERING, PROPERTY_CROSSMETABOLIZING),\ + PROPERTY_FIRE_PENETRATING = list(PROPERTY_OXYGENATING, PROPERTY_VISCOUS),\ + PROPERTY_BONEMENDING = list(PROPERTY_HYPERDENSIFICATING, PROPERTY_NUTRITIOUS),\ + PROPERTY_BONEMENDING = list(PROPERTY_HYPERDENSIFICATING, PROPERTY_NUTRITIOUS),\ + PROPERTY_ENCEPHALOPHRASIVE = list(PROPERTY_NERVESTIMULATING, PROPERTY_PSYCHOSTIMULATING))) //List of all id's from classed /datum/reagent datums indexed by class or tier. Used by chemistry generator and chem spawners. GLOBAL_LIST_INIT_TYPED(chemical_gen_classes_list, /list, list("C" = list(),"C1" = list(),"C2" = list(),"C3" = list(),"C4" = list(),"C5" = list(),"C6" = list(),"T1" = list(),"T2" = list(),"T3" = list(),"T4" = list(),"tau", list())) //properties generated in chemicals, helps to make sure the same property doesn't show up 10 times diff --git a/code/_macros.dm b/code/_macros.dm index abfa83df7d36..9b92dc8730c3 100644 --- a/code/_macros.dm +++ b/code/_macros.dm @@ -95,6 +95,9 @@ #define GENERATE_DEBUG_ID "[rand(0, 9)][rand(0, 9)][rand(0, 9)][rand(0, 9)][pick(alphabet_lowercase)][pick(alphabet_lowercase)][pick(alphabet_lowercase)][pick(alphabet_lowercase)]" #define RECT new /datum/shape/rectangle +#define SQUARE new /datum/shape/rectangle/square +#define ELLIPSE new /datum/shape/ellipse +#define CIRCLE new /datum/shape/ellipse/circle #define QTREE new /datum/quadtree #define SEARCH_QTREE(qtree, shape_range, flags) qtree.query_range(shape_range, null, flags) diff --git a/code/_onclick/xeno.dm b/code/_onclick/xeno.dm index 3bb69fe05419..15dc1c39f495 100644 --- a/code/_onclick/xeno.dm +++ b/code/_onclick/xeno.dm @@ -3,7 +3,7 @@ */ /mob/living/carbon/xenomorph/UnarmedAttack(atom/target, proximity, click_parameters, tile_attack = FALSE, ignores_resin = FALSE) - if(body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_ABILITY_BURROWED)) //No attacks while laying down + if(body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_ABILITY_BURROWED) || cannot_slash) //No attacks while laying down return FALSE var/mob/alt diff --git a/code/controllers/subsystem/sound.dm b/code/controllers/subsystem/sound.dm index 024df7cc45ad..3cc3f0ef8090 100644 --- a/code/controllers/subsystem/sound.dm +++ b/code/controllers/subsystem/sound.dm @@ -19,8 +19,7 @@ SUBSYSTEM_DEF(sound) if(!run_hearers) // Initialize for handling next template run_hearers = run_queue[run_template] // get base hearers if(run_template.range) // ranging - var/datum/shape/rectangle/zone = RECT(run_template.x, run_template.y, run_template.range * 2, run_template.range * 2) - run_hearers |= SSquadtree.players_in_range(zone, run_template.z) + run_hearers |= SSquadtree.players_in_range(SQUARE(run_template.x, run_template.y, run_template.range * 2), run_template.z) if(MC_TICK_CHECK) return while(length(run_hearers)) // Output sound to hearers diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 85e2a57cc6d6..25f522753543 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -414,6 +414,7 @@ SUBSYSTEM_DEF(vote) qdel(src) /datum/action/innate/vote/action_activate() + . = ..() owner.vote() /datum/action/innate/vote/proc/remove_from_client() diff --git a/code/controllers/subsystem/who.dm b/code/controllers/subsystem/who.dm new file mode 100644 index 000000000000..43ecbb435587 --- /dev/null +++ b/code/controllers/subsystem/who.dm @@ -0,0 +1,312 @@ +SUBSYSTEM_DEF(who) + name = "Who" + flags = SS_BACKGROUND + runlevels = RUNLEVELS_DEFAULT|RUNLEVEL_LOBBY + init_order = SS_INIT_WHO + wait = 5 SECONDS + + var/datum/player_list/who = new + var/datum/player_list/staff/staff_who = new + +/datum/controller/subsystem/who/Initialize() + who.update_data() + staff_who.update_data() + return SS_INIT_SUCCESS + +/datum/controller/subsystem/who/fire(resumed = TRUE) + who.update_data() + staff_who.update_data() + +//datum +/datum/player_list + var/tgui_name = "Who" + var/tgui_interface_name = "Who" + var/list/mobs_ckey = list() + var/list/list_data = list() + +/datum/player_list/proc/update_data() + var/list/new_list_data = list() + var/list/new_mobs_ckey = list() + var/list/additional_data = list( + "lobby" = 0, + "admin_observers" = 0, + "observers" = 0, + "yautja" = 0, + "infected_preds" = 0, + "humans" = 0, + "infected_humans" = 0, + "uscm" = 0, + "uscm_marines" = 0, + ) + new_list_data["additional_info"] = list() + var/list/counted_factions = list() + for(var/client/client as anything in sortTim(GLOB.clients, GLOBAL_PROC_REF(cmp_ckey_asc))) + CHECK_TICK + new_list_data["all_clients"]++ + var/list/client_payload = list() + client_payload["ckey"] = "[client.key]" + client_payload["text"] = "[client.key]" + client_payload["ckey_color"] = "white" + var/mob/client_mob = client.mob + new_mobs_ckey[client.key] = client_mob + if(client_mob) + if(istype(client_mob, /mob/new_player)) + client_payload["text"] += " - in Lobby" + additional_data["lobby"]++ + + else if(isobserver(client_mob)) + client_payload["text"] += " - Playing as [client_mob.real_name]" + if(CLIENT_IS_STAFF(client)) + additional_data["admin_observers"]++ + else + additional_data["observers"]++ + + var/mob/dead/observer/observer = client_mob + if(observer.started_as_observer) + client_payload["color"] += "#ce89cd" + client_payload["text"] += " - Spectating" + else + client_payload["color"] += "#A000D0" + client_payload["text"] += " - DEAD" + + else + client_payload["text"] += " - Playing as [client_mob.real_name]" + + switch(client_mob.stat) + if(UNCONSCIOUS) + client_payload["color"] += "#B0B0B0" + client_payload["text"] += " - Unconscious" + if(DEAD) + client_payload["color"] += "#A000D0" + client_payload["text"] += " - DEAD" + + if(client_mob.stat != DEAD) + if(isxeno(client_mob)) + client_payload["color"] += "#ec3535" + client_payload["text"] += " - Xenomorph" + + else if(ishuman(client_mob)) + if(client_mob.faction == FACTION_ZOMBIE) + counted_factions[FACTION_ZOMBIE]++ + client_payload["color"] += "#2DACB1" + client_payload["text"] += " - Zombie" + else if(client_mob.faction == FACTION_YAUTJA) + client_payload["color"] += "#7ABA19" + client_payload["text"] += " - Yautja" + additional_data["yautja"]++ + if(client_mob.status_flags & XENO_HOST) + additional_data["infected_preds"]++ + else + additional_data["humans"]++ + if(client_mob.status_flags & XENO_HOST) + additional_data["infected_humans"]++ + if(client_mob.faction == FACTION_MARINE) + additional_data["uscm"]++ + if(client_mob.job in (GLOB.ROLES_MARINES)) + additional_data["uscm_marines"]++ + else + counted_factions[client_mob.faction]++ + + new_list_data["total_players"] += list(client_payload) + + new_list_data["additional_info"] += list(list( + "content" = "In Lobby: [additional_data["lobby"]]", + "color" = "#777", + "text" = "Player in lobby", + )) + + new_list_data["additional_info"] += list(list( + "content" = "Spectating Players: [additional_data["observers"]]", + "color" = "#777", + "text" = "Spectating players", + )) + + new_list_data["additional_info"] += list(list( + "content" = "Spectating Admins: [additional_data["admin_observers"]]", + "color" = "#777", + "text" = "Spectating administrators", + )) + + new_list_data["additional_info"] += list(list( + "content" = "Humans: [additional_data["humans"]]", + "color" = "#2C7EFF", + "text" = "Players playing as Human", + )) + + new_list_data["additional_info"] += list(list( + "content" = "Infected Humans: [additional_data["infected_humans"]]", + "color" = "#ec3535", + "text" = "Players playing as Infected Human", + )) + + new_list_data["additional_info"] += list(list( + "content" = "[MAIN_SHIP_NAME] Personnel: [additional_data["uscm"]]", + "color" = "#5442bd", + "text" = "Players playing as [MAIN_SHIP_NAME] Personnel", + )) + + new_list_data["additional_info"] += list(list( + "content" = "Marines: [additional_data["uscm_marines"]]", + "color" = "#5442bd", + "text" = "Players playing as Marines", + )) + + new_list_data["additional_info"] += list(list( + "content" = "Yautjas: [additional_data["yautja"]]", + "color" = "#7ABA19", + "text" = "Players playing as Yautja", + )) + + new_list_data["additional_info"] += list(list( + "content" = "Infected Predators: [additional_data["infected_preds"]]", + "color" = "#7ABA19", + "text" = "Players playing as Infected Yautja", + )) + + for(var/i in 1 to length(counted_factions)) + if(counted_factions[counted_factions[i]]) + new_list_data["factions"] += list(list( + "content" = "[counted_factions[i]]: [counted_factions[counted_factions[i]]]", + "color" = "#2C7EFF", + "text" = "Other", + )) + if(counted_factions[FACTION_NEUTRAL]) + new_list_data["factions"] += list(list( + "content" = "[FACTION_NEUTRAL] Humans: [counted_factions[FACTION_NEUTRAL]]", + "color" = "#688944", + "text" = "Neutrals", + )) + + for(var/faction_to_get in ALL_XENO_HIVES) + var/datum/hive_status/hive = GLOB.hive_datum[faction_to_get] + if(hive && length(hive.totalXenos)) + new_list_data["xenomorphs"] += list(list( + "content" = "[hive.name]: [length(hive.totalXenos)]", + "color" = hive.color ? hive.color : "#8200FF", + "text" = "Queen: [hive.living_xeno_queen ? "Alive" : "Dead"]", + )) + + list_data = new_list_data + mobs_ckey = new_mobs_ckey + +/datum/player_list/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, tgui_name, tgui_interface_name) + ui.open() + ui.set_autoupdate(TRUE) + +/datum/player_list/ui_data(mob/user) + . = list_data + +/datum/player_list/ui_static_data(mob/user) + . = list() + + .["admin"] = CLIENT_IS_STAFF(user.client) + +/datum/player_list/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + + switch(action) + if("get_player_panel") + if(mobs_ckey[params["ckey"]]) + GLOB.admin_datums[usr.client.ckey].show_player_panel(mobs_ckey[params["ckey"]]) + +/datum/player_list/ui_status(mob/user, datum/ui_state/state) + return UI_INTERACTIVE + + +/datum/player_list/staff + tgui_name = "StaffWho" + tgui_interface_name = "Staff Who" + + var/list/category_colors = list( + "Management" = "purple", + "Maintainers" = "blue", + "Administrators" = "red", + "Moderators" = "orange", + "Mentors" = "green" + ) + +/datum/player_list/staff/update_data() + var/list/new_list_data = list() + mobs_ckey = list() + + var/list/listings + var/list/mappings + if(CONFIG_GET(flag/show_manager)) + LAZYSET(mappings, "Management", R_PERMISSIONS) + if(CONFIG_GET(flag/show_devs)) + LAZYSET(mappings, "Maintainers", R_PROFILER) + LAZYSET(mappings, "Administrators", R_ADMIN) + if(CONFIG_GET(flag/show_mods)) + LAZYSET(mappings, "Moderators", R_MOD && R_BAN) + if(CONFIG_GET(flag/show_mentors)) + LAZYSET(mappings, "Mentors", R_MENTOR) + + for(var/category in mappings) + LAZYSET(listings, category, list()) + + for(var/client/client as anything in GLOB.admins) + if(client.admin_holder?.fakekey && !CLIENT_IS_STAFF(client)) + continue + + for(var/category in mappings) + if(CLIENT_HAS_RIGHTS(client, mappings[category])) + LAZYADD(listings[category], client) + break + + for(var/category in listings) + var/list/admins = list() + for(var/client/entry as anything in listings[category]) + var/list/admin = list() + var/rank = entry.admin_holder.rank + if(entry.admin_holder.extra_titles?.len) + for(var/srank in entry.admin_holder.extra_titles) + rank += " & [srank]" + + admin["content"] = "[entry.key] ([rank])" + admin["text"] = "" + + if(entry.admin_holder?.fakekey) + admin["text"] += " (HIDDEN)" + + if(istype(entry.mob, /mob/dead/observer)) + admin["color"] = "#808080" + admin["text"] += " Spectating" + + else if(istype(entry.mob, /mob/new_player)) + admin["color"] = "#688944" + admin["text"] += " in Lobby" + else + admin["color"] = "#688944" + admin["text"] += " Playing" + + if(entry.is_afk()) + admin["color"] = "#A040D0" + admin["text"] += " (AFK)" + + admins += list(admin) + + new_list_data["administrators"] += list(list( + "category" = category, + "category_color" = category_colors[category], + "category_administrators" = length(listings[category]), + "admins" = admins, + )) + + list_data = new_list_data + +/mob/verb/who() + set category = "OOC" + set name = "Who" + + SSwho.who.tgui_interact(src) + +/mob/verb/staffwho() + set category = "Admin" + set name = "StaffWho" + + SSwho.staff_who.tgui_interact(src) diff --git a/code/datums/action.dm b/code/datums/action.dm index d1768655a2da..e6c87eca6a0d 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -43,7 +43,9 @@ return /datum/action/proc/action_activate() - return + SHOULD_CALL_PARENT(TRUE) + + SEND_SIGNAL(src, COMSIG_ACTION_ACTIVATED) /// handler for when a keybind signal is received by the action, calls the action_activate proc asynchronous /datum/action/proc/keybind_activation() @@ -158,6 +160,10 @@ hidden = FALSE L.update_action_buttons() +/proc/get_action(mob/action_mob, action_path) + for(var/datum/action/action in action_mob.actions) + if(istype(action, action_path)) + return action /datum/action/item_action name = "Use item" @@ -181,11 +187,6 @@ holder_item = null return ..() -/datum/action/item_action/action_activate() - if(target) - var/obj/item/I = target - I.ui_action_click(owner, holder_item) - /datum/action/item_action/can_use_action() if(ishuman(owner) && !owner.is_mob_incapacitated()) var/mob/living/carbon/human/human = owner @@ -206,6 +207,17 @@ name = "Toggle [target]" button.name = name +/datum/action/item_action/toggle/action_activate() + . = ..() + if(target) + var/obj/item/I = target + I.ui_action_click(owner, holder_item) + +/datum/action/item_action/toggle/use/New(target) + . = ..() + name = "Use [target]" + button.name = name + //This is the proc used to update all the action buttons. /mob/proc/update_action_buttons(reload_screen) if(!client) diff --git a/code/datums/ammo/bullet/lever_action.dm b/code/datums/ammo/bullet/lever_action.dm index 2770231b6811..e1475146b21f 100644 --- a/code/datums/ammo/bullet/lever_action.dm +++ b/code/datums/ammo/bullet/lever_action.dm @@ -52,7 +52,7 @@ /datum/ammo/bullet/lever_action/xm88 name = ".458 SOCOM round" - damage = 80 + damage = 104 penetration = ARMOR_PENETRATION_TIER_2 accuracy = HIT_ACCURACY_TIER_1 shell_speed = AMMO_SPEED_TIER_6 diff --git a/code/datums/ammo/misc.dm b/code/datums/ammo/misc.dm index 9a9ed2fb505b..28610f283df2 100644 --- a/code/datums/ammo/misc.dm +++ b/code/datums/ammo/misc.dm @@ -49,10 +49,21 @@ drop_flame(get_turf(P), P.weapon_cause_data) /datum/ammo/flamethrower/tank_flamer - flamer_reagent_id = "napalmx" - + flamer_reagent_id = "highdamagenapalm" max_range = 8 +/datum/ammo/flamethrower/tank_flamer/drop_flame(turf/turf, datum/cause_data/cause_data) + if(!istype(turf)) + return + + var/datum/reagent/napalm/high_damage/reagent = new() + new /obj/flamer_fire(turf, cause_data, reagent, 1) + + var/datum/effect_system/smoke_spread/landingsmoke = new /datum/effect_system/smoke_spread + landingsmoke.set_up(1, 0, turf, null, 4, cause_data) + landingsmoke.start() + landingsmoke = null + /datum/ammo/flamethrower/sentry_flamer flags_ammo_behavior = AMMO_IGNORE_ARMOR|AMMO_IGNORE_COVER|AMMO_FLAME flamer_reagent_id = "napalmx" diff --git a/code/datums/autocells/explosion.dm b/code/datums/autocells/explosion.dm index ecc6f9925800..ec310e80367c 100644 --- a/code/datums/autocells/explosion.dm +++ b/code/datums/autocells/explosion.dm @@ -264,7 +264,9 @@ as having entered the turf. falloff = max(falloff, power/100) - msg_admin_attack("Explosion with Power: [power], Falloff: [falloff], Shape: [falloff_shape] in [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]).", epicenter.x, epicenter.y, epicenter.z) + var/obj/causing_obj = explosion_cause_data?.resolve_cause() + var/mob/causing_mob = explosion_cause_data?.resolve_mob() + msg_admin_attack("Explosion with Power: [power], Falloff: [falloff], Shape: [falloff_shape],[causing_obj ? " from [causing_obj]" : ""][causing_mob ? " by [key_name(causing_mob)]" : ""] in [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]).", epicenter.x, epicenter.y, epicenter.z) playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(power^2,1)) diff --git a/code/datums/components/bad_leg.dm b/code/datums/components/bad_leg.dm index 4a8678c4da76..8793271803dc 100644 --- a/code/datums/components/bad_leg.dm +++ b/code/datums/components/bad_leg.dm @@ -149,6 +149,7 @@ CRASH("No bound wound to link action") /datum/action/human_action/rest_legs/action_activate() + . = ..() var/mob/living/carbon/human/homan = owner if(in_use) to_chat(homan, SPAN_WARNING("You're already doing that!")) diff --git a/code/datums/components/bonus_damage_stack.dm b/code/datums/components/bonus_damage_stack.dm index 78da5e036ce4..7a9bf5aa9560 100644 --- a/code/datums/components/bonus_damage_stack.dm +++ b/code/datums/components/bonus_damage_stack.dm @@ -60,7 +60,7 @@ var/color = COLOR_BONUS_DAMAGE var/intensity = bonus_damage_stacks / (initial(bonus_damage_cap) * 2) // if intensity is too high of a value, the hex code will become invalid - color += num2text(BONUS_DAMAGE_MAX_ALPHA * clamp(intensity, 0, 0.5), 1, 16) + color += num2text(BONUS_DAMAGE_MAX_ALPHA * clamp(intensity, 0, 0.5), 2, 16) if(parent) var/atom/A = parent A.add_filter("bonus_damage_stacks", 2, list("type" = "outline", "color" = color, "size" = 1 + clamp(intensity, 0, 1))) diff --git a/code/datums/quadtree.dm b/code/datums/quadtree.dm index 5e5b27d57330..9056dfd6bd59 100644 --- a/code/datums/quadtree.dm +++ b/code/datums/quadtree.dm @@ -49,43 +49,124 @@ ..() return QDEL_HINT_IWILLGC -/datum/shape //Leaving rectangles as a subtype if anyone decides to add circles later +/// A simple geometric shape for testing collisions and intersections. This one is a single point. +/datum/shape + /// Horizontal position of the shape's center point. var/center_x = 0 + /// Vertical position of the shape's center point. var/center_y = 0 + /// Distance from the shape's leftmost to rightmost extent. + var/bounds_x = 0 + /// Distance from the shape's topmost to bottommost extent. + var/bounds_y = 0 -/datum/shape/proc/intersects() - return -/datum/shape/proc/contains() - return +/datum/shape/New(center_x, center_y) + set_shape(center_x, center_y) +/// Assign shape variables. +/datum/shape/proc/set_shape(center_x, center_y) + src.center_x = center_x + src.center_y = center_y + +/// Returns TRUE if the coordinates x, y are in or on the shape, otherwise FALSE. +/datum/shape/proc/contains_xy(x, y) + return center_x == x && center_y == y + +/// Returns TRUE if the coord datum is in or on the shape, otherwise FALSE. +/datum/shape/proc/contains_coords(datum/coords/coords) + return contains_xy(coords.x_pos, coords.y_pos) + +/// Returns TRUE if the atom is in or on the shape, otherwise FALSE. +/datum/shape/proc/contains_atom(atom/atom) + return contains_xy(atom.x, atom.y) + +/// Returns TRUE if this shape's bounding box intersects the provided shape's bounding box, otherwise FALSE. Generally faster than a full intersection test. +/datum/shape/proc/intersects_aabb(datum/shape/aabb) + return (abs(src.center_x - aabb.center_x) <= (src.bounds_x + aabb.bounds_x) * 0.5) && (abs(src.center_y - aabb.center_y) <= (src.bounds_y + aabb.bounds_y) * 0.5) + +/// Returns TRUE if this shape intersects the provided rectangle shape, otherwise FALSE. +/datum/shape/proc/intersects_rect(datum/shape/rectangle/rect) + return rect.contains_xy(src.center_x, src.center_y) + +/// A simple geometric shape for testing collisions and intersections. This one is an axis-aligned rectangle. /datum/shape/rectangle + /// Distance from the shape's leftmost to rightmost extent. + var/width = 0 + /// Distance from the shape's topmost to bottommost extent. + var/height = 0 + +/datum/shape/rectangle/New(center_x, center_y, width, height) + set_shape(center_x, center_y, width, height) + +/datum/shape/rectangle/set_shape(center_x, center_y, width, height) + ..() + src.bounds_x = width + src.bounds_y = height + src.width = width + src.height = height + +/datum/shape/rectangle/contains_xy(x, y) + return (abs(center_x - x) <= width * 0.5) && (abs(center_y - y) <= height * 0.5) + +/datum/shape/rectangle/intersects_rect(datum/shape/rectangle/rect) + return intersects_aabb(rect) + +/// A simple geometric shape for testing collisions and intersections. This one is an axis-aligned square. +/datum/shape/rectangle/square + /// Distance between the shape's opposing extents. + var/length = 0 + +/datum/shape/rectangle/square/New(center_x, center_y, length) + set_shape(center_x, center_y, length) + +/datum/shape/rectangle/square/set_shape(center_x, center_y, length) + ..(center_x, center_y, length, length) + src.length = length + +/// A simple geometric shape for testing collisions and intersections. This one is an axis-aligned ellipse. +/datum/shape/ellipse + /// Distance from the shape's leftmost to rightmost extent. var/width = 0 + /// Distance from the shape's topmost to bottommost extent. var/height = 0 + VAR_PROTECTED/_axis_x_sq = 0 + VAR_PROTECTED/_axis_y_sq = 0 + +/datum/shape/ellipse/New(center_x, center_y, width, height) + set_shape(center_x, center_y, width, height) -/datum/shape/rectangle/New(x, y, w, h) +/datum/shape/ellipse/set_shape(center_x, center_y, width, height) ..() - center_x = x - center_y = y - width = w - height = h - -/datum/shape/rectangle/intersects(datum/shape/rectangle/range) - return !(range.center_x + range.width/2 < center_x - width / 2|| \ - range.center_x - range.width/2 > center_x + width / 2|| \ - range.center_y + range.height/2 < center_y - height / 2|| \ - range.center_y - range.height/2 > center_y + height / 2) - -/datum/shape/rectangle/contains(datum/coords/coords) - return (coords.x_pos >= center_x - width / 2 \ - && coords.x_pos <= center_x + width / 2 \ - && coords.y_pos >= center_y - height /2 \ - && coords.y_pos <= center_y + height / 2) - -/datum/shape/rectangle/proc/contains_atom(atom/A) - return (A.x >= center_x - width / 2 \ - && A.x <= center_x + width / 2 \ - && A.y >= center_y - height /2 \ - && A.y <= center_y + height / 2) + src.bounds_x = width + src.bounds_y = height + src.width = width + src.height = height + src._axis_x_sq = (width * 0.5)**2 + src._axis_y_sq = (height * 0.5)**2 + +/datum/shape/ellipse/contains_xy(x, y) + return ((center_x - x)**2 / _axis_x_sq + (center_y - y)**2 / _axis_y_sq <= 1) + +/datum/shape/ellipse/intersects_rect(datum/shape/rectangle/rect) + if(..()) + return TRUE + + var/nearest_x = clamp(src.center_x, rect.center_x - rect.width * 0.5, rect.center_x + rect.width * 0.5) + var/nearest_y = clamp(src.center_y, rect.center_y - rect.height * 0.5, rect.center_y + rect.height * 0.5) + + return src.contains_xy(nearest_x, nearest_y) + +/// A simple geometric shape for testing collisions and intersections. This one is a circle. +/datum/shape/ellipse/circle + /// Distance from the shape's center to edge. + var/radius = 0 + +/datum/shape/ellipse/circle/New(center_x, center_y, radius) + set_shape(center_x, center_y, radius) + +/datum/shape/ellipse/circle/set_shape(center_x, center_y, radius) + ..(center_x, center_y, radius * 2, radius * 2) + src.radius = radius /datum/quadtree/proc/subdivide() //Warning: this might give you eye cancer @@ -96,7 +177,7 @@ is_divided = TRUE /datum/quadtree/proc/insert_player(datum/coords/qtplayer/p_coords) - if(!boundary.contains(p_coords)) + if(!boundary.contains_coords(p_coords)) return FALSE if(!player_coords) @@ -118,11 +199,11 @@ player_coords.Add(p_coords) return TRUE -/datum/quadtree/proc/query_range(datum/shape/rectangle/range, list/found_players, flags = 0) +/datum/quadtree/proc/query_range(datum/shape/range, list/found_players, flags = 0) if(!found_players) found_players = list() . = found_players - if(!range?.intersects(boundary)) + if(!range?.intersects_rect(boundary)) return if(is_divided) nw_branch.query_range(range, found_players, flags) @@ -136,7 +217,7 @@ continue if((flags & QTREE_EXCLUDE_OBSERVER) && P.is_observer) continue - if(range.contains(P)) + if(range.contains_coords(P)) if(flags & QTREE_SCAN_MOBS) found_players.Add(P.player.mob) else diff --git a/code/datums/statistics/entities/round_stats.dm b/code/datums/statistics/entities/round_stats.dm index 10ec04c6da0e..79493ca87ef0 100644 --- a/code/datums/statistics/entities/round_stats.dm +++ b/code/datums/statistics/entities/round_stats.dm @@ -393,6 +393,7 @@ return TRUE /datum/action/show_round_statistics/action_activate() + . = ..() if(!can_use_action()) return diff --git a/code/datums/supply_packs/explosives.dm b/code/datums/supply_packs/explosives.dm index 032ef047c78a..78f0f3e9251a 100644 --- a/code/datums/supply_packs/explosives.dm +++ b/code/datums/supply_packs/explosives.dm @@ -89,6 +89,18 @@ containername = "\improper explosive M40 HEDP grenades crate (WARNING)" group = "Explosives" +/datum/supply_packs/explosives_sebb + name = "G2 electroshock grenades crate (x6)" + contains = list( + /obj/item/storage/box/packet/sebb, + /obj/item/storage/box/packet/sebb, + ) + cost = 30 + containertype = /obj/structure/closet/crate/explosives + containername = "\improper G2 electroshock grenades crate (WARNING)" + group = "Explosives" + + /datum/supply_packs/explosives_hedp name = "M40 HEDP blast grenade box crate (x25)" contains = list( diff --git a/code/datums/tutorial/_tutorial.dm b/code/datums/tutorial/_tutorial.dm index ddeddddd0407..b7403da3c0a9 100644 --- a/code/datums/tutorial/_tutorial.dm +++ b/code/datums/tutorial/_tutorial.dm @@ -4,7 +4,7 @@ GLOBAL_LIST_EMPTY_TYPED(ongoing_tutorials, /datum/tutorial) /datum/tutorial /// What the tutorial is called, is player facing var/name = "Base" - /// Internal ID of the tutorial, kept for save files + /// Internal ID of the tutorial, kept for save files. Format is "tutorialtype_specifictutorial_number". So, the first basic xeno tutorial would be "xeno_basic_1", and the 2nd marine medical tutorial would be "marine_medical_2" var/tutorial_id = "base" /// A short 1-2 sentence description of the tutorial itself var/desc = "" @@ -144,6 +144,8 @@ GLOBAL_LIST_EMPTY_TYPED(ongoing_tutorials, /datum/tutorial) /// Ends the tutorial after a certain amount of time. /datum/tutorial/proc/tutorial_end_in(time = 5 SECONDS, completed = TRUE) + if(completed) + mark_completed() // This is done because if you're calling this proc with completed == TRUE, then the tutorial's a done deal. We shouldn't penalize the player if they exit a few seconds before it actually completes. tutorial_ending = TRUE addtimer(CALLBACK(src, PROC_REF(end_tutorial), completed), time) @@ -221,6 +223,7 @@ GLOBAL_LIST_EMPTY_TYPED(ongoing_tutorials, /datum/tutorial) tutorial = WEAKREF(selected_tutorial) /datum/action/tutorial_end/action_activate() + . = ..() if(!tutorial) return diff --git a/code/datums/tutorial/xenomorph/abomination.dm b/code/datums/tutorial/xenomorph/abomination.dm new file mode 100644 index 000000000000..83ac86b8f09e --- /dev/null +++ b/code/datums/tutorial/xenomorph/abomination.dm @@ -0,0 +1,256 @@ +/datum/tutorial/xenomorph/abomination + name = "Xenomorph - Predalien" + desc = "A tutorial to teach you how to play the \"Predalien\", also known as Abomination, xenomorph caste. Completing this is required to be able to play an Abomination." + icon_state = "predalien" + tutorial_id = "xeno_abom_1" + tutorial_template = /datum/map_template/tutorial/s7x7 + starting_xenomorph_type = /mob/living/carbon/xenomorph/predalien/tutorial + /// How many marines in the kill_marines stage have been killed + var/ending_marines_killed = 0 + +// START OF SCRITPING + +/datum/tutorial/xenomorph/abomination/start_tutorial(mob/starting_mob) + . = ..() + if(!.) + return + + init_mob() + xeno.lock_evolve = TRUE + + message_to_player("Welcome to the tutorial for the Abomination xenomorph. As an Abomination, you are a frontline powerhouse whose damage scales with your kill count.") + message_to_player("Your kill count scales when you kill humans with your slash attack, up to 10 kills. Ability kills do not count towards this.") + + addtimer(CALLBACK(src, PROC_REF(how_to_be_abom)), 12 SECONDS) + +/datum/tutorial/xenomorph/abomination/proc/how_to_be_abom() + message_to_player("Be aware that you are kill-on-sight to all Predators forever, and will very likely need to defend yourself against multiple.") + message_to_player("Be sure to stick close to other xenomorphs or over-extend. While you may be stronger than many, you don't have enough health or armor to go out on your own.") + addtimer(CALLBACK(src, PROC_REF(feral_rush_tutorial)), 10.5 SECONDS) + +/datum/tutorial/xenomorph/abomination/proc/feral_rush_tutorial() + var/datum/action/rush = give_action(xeno, /datum/action/xeno_action/onclick/feralrush) + message_to_player("Your first unique ability is Feral Rush, an ability that temporarily increases your speed and your armor. Use Feral Rush to continue.") + update_objective("Use your Feral Rush ability.") + add_highlight(rush.button) + RegisterSignal(rush, COMSIG_XENO_ACTION_USED, PROC_REF(on_rush_used)) + +/datum/tutorial/xenomorph/abomination/proc/on_rush_used(datum/action/source, mob/owner) + SIGNAL_HANDLER + + UnregisterSignal(source, COMSIG_XENO_ACTION_USED) + remove_highlight(source.button) + addtimer(CALLBACK(src, PROC_REF(predalien_roar_tutorial_1)), 5 SECONDS) + +/datum/tutorial/xenomorph/abomination/proc/predalien_roar_tutorial_1() + hide_action(xeno, /datum/action/xeno_action/onclick/feralrush) + xeno.cannot_slash = TRUE + message_to_player("Your next ability is Roar, a versatile ability that disables any motion detectors or cloaks in a medium radius around you.") + message_to_player("Additionally, it gives a slash and speed bonus to any friendly xenomorphs in range.") + addtimer(CALLBACK(src, PROC_REF(predalien_roar_tutorial_2)), 8 SECONDS) + +/datum/tutorial/xenomorph/abomination/proc/predalien_roar_tutorial_2() + var/datum/action/roar = give_action(xeno, /datum/action/xeno_action/onclick/predalien_roar) + message_to_player("One of Roar's most useful abilities is uncloaking nearby Predators. Use Roar to uncloak the newly spawned Predator.") + update_objective("Use your Roar ability to uncloak the nearby predator.") + add_highlight(roar.button) + var/mob/living/carbon/human/pred = new(loc_from_corner(3, 3)) + add_to_tracking_atoms(pred) + pred.create_hud() + arm_equipment(pred, /datum/equipment_preset/yautja/blooded) + var/obj/item/clothing/gloves/yautja/hunter/bracers = locate() in pred + if(!bracers) + message_to_player("Something has gone wrong. Please make a bug report.") + CRASH("predator spawned without bracers in tutorial") + + bracers.cloaker_internal(pred, TRUE, TRUE, TRUE) + RegisterSignal(bracers, COMSIG_PRED_BRACER_DECLOAKED, PROC_REF(smash_tutorial_1)) + +/datum/tutorial/xenomorph/abomination/proc/smash_tutorial_1(datum/source) + SIGNAL_HANDLER + + var/datum/action/roar = get_action(xeno, /datum/action/xeno_action/onclick/predalien_roar) + remove_highlight(roar.button) + update_objective("") + + UnregisterSignal(source, COMSIG_PRED_BRACER_DECLOAKED) + addtimer(CALLBACK(src, PROC_REF(smash_tutorial_2)), 2.5 SECONDS) + +/datum/tutorial/xenomorph/abomination/proc/smash_tutorial_2() + hide_action(xeno, /datum/action/xeno_action/onclick/predalien_roar) + message_to_player("Good. Roar will be one of your primary tools for defending against Predators. Your next ability is Feral Smash.") + xeno.cannot_slash = FALSE + + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human, pred) + remove_from_tracking_atoms(pred) + qdel(pred) + + addtimer(CALLBACK(src, PROC_REF(smash_tutorial_3)), 5 SECONDS) + +/datum/tutorial/xenomorph/abomination/proc/smash_tutorial_3() + var/datum/action/smash = give_action(xeno, /datum/action/xeno_action/activable/feral_smash) + RegisterSignal(smash, COMSIG_XENO_PRE_ACTION_USED, PROC_REF(frenzy_tutorial_1)) + add_highlight(smash.button) + + message_to_player("Feral Smash is a strong lunge with a range of five tiles. It deals decent damage that scales with your kill count.") + message_to_player("Use Feral Smash on the marine to continue.") + update_objective("Use your Feral Smash ability on the marine.") + + xeno.forceMove(loc_from_corner(0, 2)) + xeno.anchored = TRUE + ADD_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_TUTORIAL) + + var/mob/living/carbon/human/marine = new(loc_from_corner(4, 2)) + add_to_tracking_atoms(marine) + arm_equipment(marine, /datum/equipment_preset/uscm/private_equipped) + +/datum/tutorial/xenomorph/abomination/proc/frenzy_tutorial_1(datum/action/source, mob/owner) + SIGNAL_HANDLER + + xeno.anchored = FALSE + REMOVE_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_TUTORIAL) + RegisterSignal(source, COMSIG_XENO_ACTION_USED, PROC_REF(frenzy_tutorial_2)) + RegisterSignal(source, COMSIG_XENO_FAILED_ACTION_USED, PROC_REF(frenzy_tutorial_1_fail)) + +/datum/tutorial/xenomorph/abomination/proc/frenzy_tutorial_1_fail(datum/action/source, mob/owner) + SIGNAL_HANDLER + + xeno.anchored = TRUE + ADD_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_TUTORIAL) + UnregisterSignal(source, list(COMSIG_XENO_FAILED_ACTION_USED, COMSIG_XENO_ACTION_USED)) + +/datum/tutorial/xenomorph/abomination/proc/frenzy_tutorial_2(datum/action/source, mob/owner) + SIGNAL_HANDLER + + if(get_turf(xeno) == loc_from_corner(0, 2)) // xeno didn't lunge at the mob + xeno.anchored = TRUE + UnregisterSignal(source, COMSIG_XENO_ACTION_USED) + ADD_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_TUTORIAL) + return + + update_objective("") + var/datum/action/smash = get_action(xeno, /datum/action/xeno_action/activable/feral_smash) + remove_highlight(smash.button) + UnregisterSignal(source, list(COMSIG_XENO_ACTION_USED, COMSIG_XENO_PRE_ACTION_USED)) + addtimer(CALLBACK(src, PROC_REF(frenzy_tutorial_3)), 2 SECONDS) + +/datum/tutorial/xenomorph/abomination/proc/frenzy_tutorial_3() + remove_action(xeno, /datum/action/xeno_action/activable/feral_smash) + message_to_player("Good. Your final ability is Feral Frenzy, a strong ability that can alternate between hitting a single target or all within a large radius. However, it locks you in place while it winds up.") + + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human, marine) + remove_from_tracking_atoms(marine) + qdel(marine) + + addtimer(CALLBACK(src, PROC_REF(frenzy_tutorial_4)), 6 SECONDS) + +/datum/tutorial/xenomorph/abomination/proc/frenzy_tutorial_4() + var/mob/living/carbon/human/marine = new(loc_from_corner(4, 2)) + add_to_tracking_atoms(marine) + RegisterSignal(marine, COMSIG_MOB_DEATH, PROC_REF(on_marine_early_death)) + arm_equipment(marine, /datum/equipment_preset/uscm/private_equipped) + + var/datum/action/frenzy = give_action(xeno, /datum/action/xeno_action/activable/feralfrenzy) + add_highlight(frenzy.button) + message_to_player("By default, Feral Frenzy is on single-target mode. Use Feral Frenzy on the newly spawned marine.") + update_objective("Use Feral Frenzy on the marine.") + + RegisterSignal(frenzy, COMSIG_XENO_ACTION_USED, PROC_REF(frenzy_tutorial_5)) + +/datum/tutorial/xenomorph/abomination/proc/frenzy_tutorial_5(datum/action/xeno_action/source, mob/owner) + SIGNAL_HANDLER + + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human, marine) + if(get_dist(marine, xeno) > 1) + return + + UnregisterSignal(source, COMSIG_XENO_ACTION_USED) + var/datum/action/frenzy = get_action(xeno, /datum/action/xeno_action/activable/feralfrenzy) + remove_highlight(frenzy.button) + var/datum/action/frenzy_toggle = give_action(xeno, /datum/action/xeno_action/onclick/toggle_gut_targeting) + add_highlight(frenzy_toggle.button) + message_to_player("Good, now toggle Feral Frenzy's AOE mode with the newly available Toggle Gutting Type ability.") + update_objective("Use the Toggle Gutting Type ability to change your frenzy mode.") + + RegisterSignal(frenzy_toggle, COMSIG_XENO_ACTION_USED, PROC_REF(frenzy_tutorial_6)) + +/datum/tutorial/xenomorph/abomination/proc/frenzy_tutorial_6(datum/action/xeno_action/source, mob/owner) + SIGNAL_HANDLER + + UnregisterSignal(source, COMSIG_XENO_ACTION_USED) + remove_highlight(source.button) + source.plasma_cost = INFINITY // slightly scuffed way of disabling the switch button + source.update_button_icon() + + message_to_player("Feral Frenzy has now been changed into AOE mode. Use Feral Frenzy again anywhere within 2 tiles of the marine.") + update_objective("Use Feral Frenzy within 2 tiles of the marine.") + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human, marine) + marine.rejuvenate() + var/datum/action/xeno_action/activable/feralfrenzy/frenzy = get_action(xeno, /datum/action/xeno_action/activable/feralfrenzy) + frenzy.targeting = AOETARGETGUT + frenzy.reduce_cooldown(frenzy.xeno_cooldown) + add_highlight(frenzy.button) + + RegisterSignal(frenzy, COMSIG_XENO_ACTION_USED, PROC_REF(frenzy_tutorial_7)) + +/datum/tutorial/xenomorph/abomination/proc/frenzy_tutorial_7(datum/action/source) + SIGNAL_HANDLER + + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human, marine) + var/datum/action/xeno_action/activable/feralfrenzy/frenzy = get_action(xeno, /datum/action/xeno_action/activable/feralfrenzy) + if(get_dist(xeno, marine) > frenzy.range) + // Not close enough to actually hit the marine + return + + UnregisterSignal(frenzy, COMSIG_XENO_ACTION_USED) + UnregisterSignal(marine, COMSIG_MOB_DEATH) + remove_highlight(frenzy.button) + message_to_player("Good. As you may have noticed, the AOE version of Feral Frenzy takes longer to wind up, in addition to doing less overall damage.") + addtimer(CALLBACK(src, PROC_REF(kill_marines)), 6 SECONDS) + +/datum/tutorial/xenomorph/abomination/proc/kill_marines() + message_to_player("To finish the tutorial, kill the three newly-spawned marines using any of your attacks or abilities.") + + // Spawn/rejuv the dummies + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human, marine) // we can reuse this one though + marine.rejuvenate() + marine.forceMove(loc_from_corner(4, 2)) + RegisterSignal(marine, COMSIG_MOB_DEATH, PROC_REF(kill_marines_2)) + + var/mob/living/carbon/human/marine_2 = new(loc_from_corner(2, 2)) + arm_equipment(marine_2, /datum/equipment_preset/uscm/private_equipped) + RegisterSignal(marine_2, COMSIG_MOB_DEATH, PROC_REF(kill_marines_2)) + + var/mob/living/carbon/human/marine_3 = new(loc_from_corner(0, 2)) + arm_equipment(marine_3, /datum/equipment_preset/uscm/private_equipped) + RegisterSignal(marine_3, COMSIG_MOB_DEATH, PROC_REF(kill_marines_2)) + + // Arrange the actions about how they'd be in an actual game + remove_action(xeno, /datum/action/xeno_action/activable/feralfrenzy) + remove_action(xeno, /datum/action/xeno_action/onclick/toggle_gut_targeting) + + give_action(xeno, /datum/action/xeno_action/activable/tail_stab) + give_action(xeno, /datum/action/xeno_action/onclick/feralrush) + give_action(xeno, /datum/action/xeno_action/onclick/predalien_roar) + give_action(xeno, /datum/action/xeno_action/activable/feral_smash) + give_action(xeno, /datum/action/xeno_action/activable/feralfrenzy) + give_action(xeno, /datum/action/xeno_action/onclick/toggle_gut_targeting) + +/datum/tutorial/xenomorph/abomination/proc/kill_marines_2(datum/source) + SIGNAL_HANDLER + + if(ending_marines_killed < 2) + ending_marines_killed++ + return + + message_to_player("Good work. The tutorial will end shortly.") + tutorial_end_in(7 SECONDS, TRUE) + +// END OF SCRIPTING + +/// In case a marine dies early to prevent softlocks +/datum/tutorial/xenomorph/abomination/proc/on_marine_early_death(datum/source) + SIGNAL_HANDLER + + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human, marine) + marine.rejuvenate() diff --git a/code/datums/xeno_shields/shield_types/vanguard_shield.dm b/code/datums/xeno_shields/shield_types/vanguard_shield.dm index 21d9fb12cfd7..cd9e4534e778 100644 --- a/code/datums/xeno_shields/shield_types/vanguard_shield.dm +++ b/code/datums/xeno_shields/shield_types/vanguard_shield.dm @@ -42,7 +42,7 @@ return linked_xeno.overlay_shields() - var/datum/action/xeno_action/activable/cleave/cAction = get_xeno_action_by_type(linked_xeno, /datum/action/xeno_action/activable/cleave) + var/datum/action/xeno_action/activable/cleave/cAction = get_action(linked_xeno, /datum/action/xeno_action/activable/cleave) if (istype(cAction)) addtimer(CALLBACK(cAction, TYPE_PROC_REF(/datum/action/xeno_action/activable/cleave, remove_buff)), 7, TIMER_UNIQUE) diff --git a/code/game/camera_manager/camera_manager.dm b/code/game/camera_manager/camera_manager.dm index 9f111b0f8ec6..90e80ec7037e 100644 --- a/code/game/camera_manager/camera_manager.dm +++ b/code/game/camera_manager/camera_manager.dm @@ -6,7 +6,7 @@ /datum/component/camera_manager var/map_name var/obj/structure/machinery/camera/current - var/datum/shape/rectangle/current_area + var/datum/shape/current_area var/atom/movable/screen/map_view/cam_screen var/atom/movable/screen/background/cam_background var/list/range_turfs = list() @@ -86,7 +86,7 @@ RegisterSignal(parent, COMSIG_CAMERA_UNREGISTER_UI, PROC_REF(unregister)) RegisterSignal(parent, COMSIG_CAMERA_SET_NVG, PROC_REF(enable_nvg)) RegisterSignal(parent, COMSIG_CAMERA_CLEAR_NVG, PROC_REF(disable_nvg)) - RegisterSignal(parent, COMSIG_CAMERA_SET_AREA, PROC_REF(set_camera_rect)) + RegisterSignal(parent, COMSIG_CAMERA_SET_AREA, PROC_REF(set_camera_area)) RegisterSignal(parent, COMSIG_CAMERA_SET_TARGET, PROC_REF(set_camera)) RegisterSignal(parent, COMSIG_CAMERA_CLEAR, PROC_REF(clear_camera)) RegisterSignal(parent, COMSIG_CAMERA_REFRESH, PROC_REF(refresh_camera)) @@ -133,18 +133,18 @@ RegisterSignal(current, COMSIG_PARENT_QDELETING, PROC_REF(show_camera_static)) update_target_camera() -/datum/component/camera_manager/proc/set_camera_rect(source, x, y, z, w, h) +/datum/component/camera_manager/proc/set_camera_area(source, datum/shape/new_area, z) SIGNAL_HANDLER render_mode = RENDER_MODE_AREA if(current) UnregisterSignal(current, COMSIG_PARENT_QDELETING) current = null - current_area = RECT(x, y, w, h) - target_x = x - target_y = y + current_area = new_area + target_x = current_area.center_x + target_y = current_area.center_y target_z = z - target_width = w - target_height = h + target_width = current_area.bounds_x + target_height = current_area.bounds_y update_area_camera() /datum/component/camera_manager/proc/enable_nvg(source, power, matrixcol) @@ -221,8 +221,8 @@ // Cameras that get here are moving, and are likely attached to some moving atom such as cyborgs. last_camera_turf = new_location - var/x_size = current_area.width - var/y_size = current_area.height + var/x_size = current_area.bounds_x + var/y_size = current_area.bounds_y var/turf/target = locate(current_area.center_x, current_area.center_y, target_z) var/list/visible_things = isXRay ? range("[x_size]x[y_size]", target) : view("[x_size]x[y_size]", target) diff --git a/code/game/machinery/autolathe_datums.dm b/code/game/machinery/autolathe_datums.dm index 78a8e46b64aa..9c8ee271845d 100644 --- a/code/game/machinery/autolathe_datums.dm +++ b/code/game/machinery/autolathe_datums.dm @@ -136,11 +136,6 @@ path = /obj/item/circuitboard/apc category = AUTOLATHE_CATEGORY_ENGINEERING -/datum/autolathe/recipe/rcd_ammo - name = "matter cartridge" - path = /obj/item/ammo_rcd - category = AUTOLATHE_CATEGORY_ENGINEERING - /datum/autolathe/recipe/table_parts name = "table parts" path = /obj/item/frame/table diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index ff8f3959d64e..4f6f4df4ef08 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -123,7 +123,7 @@ src.temp = "[src.enemy_name] has fallen! Rejoice!" if(!length(contents)) - var/prizeselect = pickweight(prizes) + var/prizeselect = pick_weight(prizes) new prizeselect(src.loc) if(istype(prizeselect, /obj/item/toy/gun)) //Ammo comes with the gun @@ -176,5 +176,5 @@ if(2) num_of_prizes = rand(0,2) for(num_of_prizes; num_of_prizes > 0; num_of_prizes--) - empprize = pickweight(prizes) + empprize = pick_weight(prizes) new empprize(src.loc) diff --git a/code/game/machinery/computer/dropship_weapons.dm b/code/game/machinery/computer/dropship_weapons.dm index e07b415ed233..7f8f4f2b3850 100644 --- a/code/game/machinery/computer/dropship_weapons.dm +++ b/code/game/machinery/computer/dropship_weapons.dm @@ -313,9 +313,8 @@ var/obj/structure/machinery/defenses/sentry/defense = sentry.deployed_turret if(defense.has_camera) defense.set_range() - var/datum/shape/rectangle/current_bb = defense.range_bounds camera_area_equipment = sentry - SEND_SIGNAL(src, COMSIG_CAMERA_SET_AREA, current_bb.center_x, current_bb.center_y, defense.loc.z, current_bb.width, current_bb.height) + SEND_SIGNAL(src, COMSIG_CAMERA_SET_AREA, defense.range_bounds, defense.loc.z) return TRUE if("clear-camera") diff --git a/code/game/machinery/medical_pod/autodoc.dm b/code/game/machinery/medical_pod/autodoc.dm index ef335c6841e6..b5fd43b35651 100644 --- a/code/game/machinery/medical_pod/autodoc.dm +++ b/code/game/machinery/medical_pod/autodoc.dm @@ -238,11 +238,6 @@ surgery_list += create_autodoc_surgery(L,ORGAN_SURGERY,"damage",0,I) organdamagesurgery++ - if(istype(L,/obj/limb/head)) - var/obj/limb/head/H = L - if(H.disfigured) - surgery_list += create_autodoc_surgery(L,LIMB_SURGERY,"facial") - if(L.status & LIMB_BROKEN) surgery_list += create_autodoc_surgery(L,LIMB_SURGERY,"broken") if(L.status & LIMB_DESTROYED) @@ -521,20 +516,6 @@ if(!surgery) break close_incision(H,S.limb_ref) - if("facial") - if(prob(30)) visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning Facial Reconstruction Surgery."); - if(S.unneeded) - sleep(UNNEEDED_DELAY) - visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary."); - surgery_todo_list -= S - continue - if(istype(S.limb_ref, /obj/limb/head)) - var/obj/limb/head/F = S.limb_ref - sleep(SCALPEL_MAX_DURATION + HEMOSTAT_MAX_DURATION + RETRACTOR_MAX_DURATION + CAUTERY_MAX_DURATION) - F.remove_all_bleeding(TRUE) - F.disfigured = 0 - F.owner.name = F.owner.get_visible_name() - if("open") if(prob(30)) visible_message("[icon2html(src, viewers(src))] \The [src]croaks: Closing surgical incision."); close_encased(H,S.limb_ref) @@ -753,9 +734,6 @@ if("shrapnel") surgeryqueue["shrapnel"] = 1 dat += "Shrapnel Removal Surgery" - if("facial") - surgeryqueue["facial"] = 1 - dat += "Facial Reconstruction Surgery" if("open") surgeryqueue["open"] = 1 dat += "Close Open Incisions" @@ -902,18 +880,6 @@ N.fields["autodoc_manual"] += create_autodoc_surgery(null,LIMB_SURGERY,"shrapnel",1) updateUsrDialog() - if(href_list["facial"]) - for(var/obj/limb/L in connected.occupant.limbs) - if(L) - if(istype(L,/obj/limb/head)) - var/obj/limb/head/J = L - if(J.disfigured) - N.fields["autodoc_manual"] += create_autodoc_surgery(L,LIMB_SURGERY,"facial") - else - N.fields["autodoc_manual"] += create_autodoc_surgery(L,LIMB_SURGERY,"facial",1) - updateUsrDialog() - break - if(href_list["open"]) for(var/obj/limb/L in connected.occupant.limbs) if(L) diff --git a/code/game/machinery/vending/vendor_types/crew/combat_correspondent.dm b/code/game/machinery/vending/vendor_types/crew/combat_correspondent.dm index b0894ca2a5a2..81bee126dbc8 100644 --- a/code/game/machinery/vending/vendor_types/crew/combat_correspondent.dm +++ b/code/game/machinery/vending/vendor_types/crew/combat_correspondent.dm @@ -3,9 +3,11 @@ GLOBAL_LIST_INIT(cm_vending_clothing_combat_correspondent, list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), list("Essential Reporter's Set", 0, /obj/effect/essentials_set/cc, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_MANDATORY), + list("Leather Satchel", 0, /obj/item/storage/backpack/satchel, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + + list("CIVILIAN EQUIPMENT (TAKE ALL)", 0, null, null, null), list("Portable Press Fax Machine", 0, /obj/item/device/fax_backpack, CIVILIAN_CAN_BUY_BACKPACK, VENDOR_ITEM_RECOMMENDED), list("Press Broadcasting Camera", 0, /obj/item/device/camera/broadcasting, CIVILIAN_CAN_BUY_UTILITY, VENDOR_ITEM_RECOMMENDED), - list("Leather Satchel", 0, /obj/item/storage/backpack/satchel, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), list("UNIFORM (CHOOSE 1)", 0, null, null, null), list("Black Uniform", 0, /obj/item/clothing/under/marine/reporter/black, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/crew/commanding_officer.dm b/code/game/machinery/vending/vendor_types/crew/commanding_officer.dm index d7d49a8ae044..dd2fc9c4a5b7 100644 --- a/code/game/machinery/vending/vendor_types/crew/commanding_officer.dm +++ b/code/game/machinery/vending/vendor_types/crew/commanding_officer.dm @@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_commanding_officer, list( list("HEDP Grenade Pack", 15, /obj/item/storage/box/packet/high_explosive, null, VENDOR_ITEM_REGULAR), list("HEFA Grenade Pack", 15, /obj/item/storage/box/packet/hefa, null, VENDOR_ITEM_REGULAR), list("WP Grenade Pack", 15, /obj/item/storage/box/packet/phosphorus, null, VENDOR_ITEM_REGULAR), + list("G2 Electroshock Grenade Packet (x3 grenades)", 15, /obj/item/storage/box/packet/sebb, null, VENDOR_ITEM_REGULAR), list("RAIL ATTACHMENTS", 0, null, null, null), list("Red-Dot Sight", 15, /obj/item/attachable/reddot, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/crew/staff_officer_armory.dm b/code/game/machinery/vending/vendor_types/crew/staff_officer_armory.dm index 1e21f2f7256d..46de6ed028d0 100644 --- a/code/game/machinery/vending/vendor_types/crew/staff_officer_armory.dm +++ b/code/game/machinery/vending/vendor_types/crew/staff_officer_armory.dm @@ -18,7 +18,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_staff_officer_armory, list( list("Marine Combat Gloves", 0, /obj/item/clothing/gloves/marine, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY), list("Aviator Shades", 0, /obj/item/clothing/glasses/sunglasses/aviator, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_REGULAR), - list("Bayonet", 0, /obj/item/attachable/bayonet, null, VENDOR_ITEM_REGULAR), + list("Bayonet", 0, /obj/item/attachable/bayonet, MARINE_CAN_BUY_ATTACHMENT, VENDOR_ITEM_REGULAR), list("SPECIALISATION KIT (CHOOSE 1)", 0, null, null, null), list("Essential Engineer Set", 0, /obj/effect/essentials_set/engi, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_RECOMMENDED), diff --git a/code/game/machinery/vending/vendor_types/crew/synthetic.dm b/code/game/machinery/vending/vendor_types/crew/synthetic.dm index 7fbe39480999..9ce15535e2da 100644 --- a/code/game/machinery/vending/vendor_types/crew/synthetic.dm +++ b/code/game/machinery/vending/vendor_types/crew/synthetic.dm @@ -188,7 +188,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth, list( GLOBAL_LIST_INIT(cm_vending_clothing_synth_snowflake, list( list("USCM UNIFORMS", 0, null, null, null), list("Medical Scrubs, Blue", 12, /obj/item/clothing/under/rank/medical/blue, null, VENDOR_ITEM_REGULAR), - list("Medical Scrubs, Light Blue", 0, /obj/item/clothing/under/rank/medical/lightblue, null, VENDOR_ITEM_REGULAR), + list("Medical Scrubs, Light Blue", 12, /obj/item/clothing/under/rank/medical/lightblue, null, VENDOR_ITEM_REGULAR), list("Medical Scrubs, Green", 12, /obj/item/clothing/under/rank/medical/green, null, VENDOR_ITEM_REGULAR), list("Medical Scrubs, Purple", 12, /obj/item/clothing/under/rank/medical/purple, null, VENDOR_ITEM_REGULAR), list("Medical Scrubs, Olive", 12, /obj/item/clothing/under/rank/medical/olive, null, VENDOR_ITEM_REGULAR), @@ -349,6 +349,13 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth_snowflake, list( list("Purple Armband", 6, /obj/item/clothing/accessory/armband/science, null, VENDOR_ITEM_REGULAR), list("Yellow Armband", 6, /obj/item/clothing/accessory/armband/engine, null, VENDOR_ITEM_REGULAR), list("Green Armband", 6, /obj/item/clothing/accessory/armband/medgreen, null, VENDOR_ITEM_REGULAR), + list("Blue Tie", 6, /obj/item/clothing/accessory/blue, null, VENDOR_ITEM_REGULAR), + list("Green Tie", 6, /obj/item/clothing/accessory/green, null, VENDOR_ITEM_REGULAR), + list("Black Tie", 6, /obj/item/clothing/accessory/black, null, VENDOR_ITEM_REGULAR), + list("Gold Tie", 6, /obj/item/clothing/accessory/gold, null, VENDOR_ITEM_REGULAR), + list("Red Tie", 6, /obj/item/clothing/accessory/red, null, VENDOR_ITEM_REGULAR), + list("Purple Tie", 6, /obj/item/clothing/accessory/purple, null, VENDOR_ITEM_REGULAR), + list("Stethoscope", 6, /obj/item/clothing/accessory/stethoscope, null, VENDOR_ITEM_REGULAR), list("Dress Gloves", 6, /obj/item/clothing/gloves/marine/dress, null, VENDOR_ITEM_REGULAR), )) diff --git a/code/game/machinery/vending/vendor_types/requisitions.dm b/code/game/machinery/vending/vendor_types/requisitions.dm index a8d44a8b5012..5c5362257da2 100644 --- a/code/game/machinery/vending/vendor_types/requisitions.dm +++ b/code/game/machinery/vending/vendor_types/requisitions.dm @@ -55,6 +55,7 @@ list("M74 AGM-Smoke Airburst Grenade", floor(scale * 4), /obj/item/explosive/grenade/smokebomb/airburst, VENDOR_ITEM_REGULAR), list("M74 AGM-Star Shell", floor(scale * 2), /obj/item/explosive/grenade/high_explosive/airburst/starshell, VENDOR_ITEM_REGULAR), list("M74 AGM-Hornet Shell", floor(scale * 4), /obj/item/explosive/grenade/high_explosive/airburst/hornet_shell, VENDOR_ITEM_REGULAR), + list("G2 Electroshock Grenade", round(scale * 5), /obj/item/explosive/grenade/sebb, VENDOR_ITEM_REGULAR), list("M40 HIRR Baton Slug", floor(scale * 8), /obj/item/explosive/grenade/slug/baton, VENDOR_ITEM_REGULAR), list("M40 MFHS Metal Foam Grenade", floor(scale * 6), /obj/item/explosive/grenade/metal_foam, VENDOR_ITEM_REGULAR), list("Plastic Explosives", floor(scale * 3), /obj/item/explosive/plastic, VENDOR_ITEM_REGULAR), @@ -154,6 +155,7 @@ list("M74 AGM-Airburst Smoke Grenade Packet", 0, /obj/item/storage/box/packet/airburst_smoke, VENDOR_ITEM_REGULAR), list("M74 AGM-S Star Shell Packet", 0, /obj/item/storage/box/packet/flare, VENDOR_ITEM_REGULAR), list("M74 AGM-H Hornet Shell Packet", 0, /obj/item/storage/box/packet/hornet, VENDOR_ITEM_REGULAR), + list("G2 Electroshock grenade packet", 0, /obj/item/storage/box/packet/sebb, VENDOR_ITEM_REGULAR), list("M20 mine box", 0, /obj/item/storage/box/explosive_mines, VENDOR_ITEM_REGULAR), list("OTHER BOXES", -1, null, null), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm index aaf134c4a459..9c19a5b172c6 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm @@ -35,6 +35,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_engi, list( list("M74 AGM-Hornet Airburst Packet (x3 airburst grenades", 20, /obj/item/storage/box/packet/hornet, null, VENDOR_ITEM_REGULAR), list("M20 Mine Box (x4 mines)", 18, /obj/item/storage/box/explosive_mines, null, VENDOR_ITEM_REGULAR), list("M40 MFHS Metal Foam Grenade", 5, /obj/item/explosive/grenade/metal_foam, null, VENDOR_ITEM_REGULAR), + list("G2 Electroshock Grenade Packet (x3 grenades)", 16, /obj/item/storage/box/packet/sebb, null, VENDOR_ITEM_REGULAR), list("PRIMARY AMMUNITION", 0, null, null, null), list("M4RA AP Magazine (10x24mm)", 6, /obj/item/ammo_magazine/rifle/m4ra/ap, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm index 17d3419ac2f8..7f8d70db4328 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm @@ -61,6 +61,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_leader, list( list("M74 AGM-Hornet Airburst Packet (x3 airburst grenades", 20, /obj/item/storage/box/packet/hornet, null, VENDOR_ITEM_REGULAR), list("M20 Mine Box (x4 mines)", 20, /obj/item/storage/box/explosive_mines, null, VENDOR_ITEM_REGULAR), list("M40 MFHS Metal Foam Grenade", 5, /obj/item/explosive/grenade/metal_foam, null, VENDOR_ITEM_REGULAR), + list("G2 Electroshock Grenade Packet (x3 grenades)", 16, /obj/item/storage/box/packet/sebb, null, VENDOR_ITEM_REGULAR), list("MEDICAL SUPPLIES", 0, null, null, null), list("Burn Kit", 2, /obj/item/stack/medical/advanced/ointment, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm index a73df202d4ef..e9d69ad396de 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm @@ -57,6 +57,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_medic, list( list("M74 AGM-Smoke Airburst Packet (x3 airburst grenades)", 10, /obj/item/storage/box/packet/airburst_smoke, null, VENDOR_ITEM_REGULAR), list("M74 AGM-Hornet Airburst Packet (x3 airburst grenades", 20, /obj/item/storage/box/packet/hornet, null, VENDOR_ITEM_REGULAR), list("M20 Mine Box (x4 mines)", 20, /obj/item/storage/box/explosive_mines, null, VENDOR_ITEM_REGULAR), + list("G2 Electroshock Grenade Packet (x3 grenades)", 16, /obj/item/storage/box/packet/sebb, null, VENDOR_ITEM_REGULAR), list("PRIMARY AMMUNITION", 0, null, null, null), list("M4RA AP Magazine (10x24mm)", 6, /obj/item/ammo_magazine/rifle/m4ra/ap, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm index 4d14b7b89ccd..8fbf574d36d7 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm @@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_spec, list( list("M74 AGM-F Fragmentation Grenades x6", 40, /obj/effect/essentials_set/agmf_6_pack, null, VENDOR_ITEM_REGULAR), list("M74 AGM-I Incendiary Grenades x6", 40, /obj/effect/essentials_set/agmi_6_pack, null, VENDOR_ITEM_REGULAR), list("M74 AGM-S Smoke Grenades x6", 20, /obj/effect/essentials_set/agms_6_pack, null, VENDOR_ITEM_REGULAR), + list("G2 Electroshock Grenade Pack x6", 40, /obj/effect/essentials_set/sebb_6_pack, null, VENDOR_ITEM_REGULAR), list("EXTRA FLAMETHROWER TANKS", 0, null, null, null), list("Large Incinerator Tank", 40, /obj/item/ammo_magazine/flamer_tank/large, null, VENDOR_ITEM_REGULAR), @@ -249,3 +250,13 @@ GLOBAL_LIST_INIT(cm_vending_clothing_specialist, list( /obj/item/explosive/grenade/smokebomb/airburst, /obj/item/explosive/grenade/smokebomb/airburst, ) + +/obj/effect/essentials_set/sebb_6_pack + spawned_gear_list = list( + /obj/item/explosive/grenade/sebb, + /obj/item/explosive/grenade/sebb, + /obj/item/explosive/grenade/sebb, + /obj/item/explosive/grenade/sebb, + /obj/item/explosive/grenade/sebb, + /obj/item/explosive/grenade/sebb, + ) diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm index c37dd98ed263..73efbe1148e5 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm @@ -12,6 +12,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_tl, list( list("M74 AGM-Hornet Airburst Packet (x3 airburst grenades", 20, /obj/item/storage/box/packet/hornet, null, VENDOR_ITEM_REGULAR), list("M20 Mine Box (x4 mines)", 20, /obj/item/storage/box/explosive_mines, null, VENDOR_ITEM_REGULAR), list("M40 MFHS Metal Foam Grenade", 5, /obj/item/explosive/grenade/metal_foam, null, VENDOR_ITEM_REGULAR), + list("G2 Electroshock Grenade Packet (x3 grenades)", 16, /obj/item/storage/box/packet/sebb, null, VENDOR_ITEM_REGULAR), list("PRIMARY AMMUNITION", 0, null, null, null), list("M4RA AP Magazine (10x24mm)", 10, /obj/item/ammo_magazine/rifle/m4ra/ap, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm index 10d4e8d098fb..34da5e3d2623 100644 --- a/code/game/objects/effects/aliens.dm +++ b/code/game/objects/effects/aliens.dm @@ -597,7 +597,7 @@ total_hits++ - var/datum/action/xeno_action/activable/boiler_trap/trap = get_xeno_action_by_type(linked_xeno, /datum/action/xeno_action/activable/boiler_trap) + var/datum/action/xeno_action/activable/boiler_trap/trap = get_action(linked_xeno, /datum/action/xeno_action/activable/boiler_trap) trap.reduce_cooldown(total_hits*4 SECONDS) diff --git a/code/game/objects/effects/effect_system/particle_effects.dm b/code/game/objects/effects/effect_system/particle_effects.dm index 972d242bf359..9440c16f2d4e 100644 --- a/code/game/objects/effects/effect_system/particle_effects.dm +++ b/code/game/objects/effects/effect_system/particle_effects.dm @@ -8,10 +8,10 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT unacidable = TRUE // So effect are not targeted by alien acid. -/obj/effect/particle_effect/initialize_pass_flags(datum/pass_flags_container/PF) +/obj/effect/particle_effect/initialize_pass_flags(datum/pass_flags_container/pass_flags) ..() - if (PF) - PF.flags_pass = PASS_OVER|PASS_AROUND|PASS_UNDER|PASS_THROUGH|PASS_MOB_THRU + if (pass_flags) + pass_flags.flags_pass = PASS_OVER|PASS_AROUND|PASS_UNDER|PASS_THROUGH|PASS_MOB_THRU //Water @@ -22,17 +22,14 @@ var/life = 15 mouse_opacity = MOUSE_OPACITY_TRANSPARENT -/obj/effect/particle_effect/water/initialize_pass_flags(datum/pass_flags_container/PF) +/obj/effect/particle_effect/water/initialize_pass_flags(datum/pass_flags_container/pass_flags) ..() - if (PF) - PF.flags_pass = PASS_THROUGH|PASS_OVER|PASS_MOB_THRU|PASS_UNDER + if (pass_flags) + pass_flags.flags_pass = PASS_THROUGH|PASS_OVER|PASS_MOB_THRU|PASS_UNDER /obj/effect/particle_effect/water/Move(turf/newloc) - //var/turf/T = src.loc - //if (istype(T, /turf)) - // T.firelevel = 0 //TODO: FIX - if (--src.life < 1) - //SN src = null + life -= 1 + if (life < 1) qdel(src) if(newloc.density) return 0 diff --git a/code/game/objects/effects/effect_system/smoke.dm b/code/game/objects/effects/effect_system/smoke.dm index d4152bdee37e..d0ea5d2ed5ef 100644 --- a/code/game/objects/effects/effect_system/smoke.dm +++ b/code/game/objects/effects/effect_system/smoke.dm @@ -731,7 +731,7 @@ location = get_turf(loca) if(direct) direction = direct - if(lifetime) + if(smoke_time) lifetime = smoke_time radius = min(radius, 10) amount = radius diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index ce0fd5506cd7..d559137f79b1 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -223,6 +223,7 @@ icon_state = "empdisable" name = "emp sparks" effect_duration = 10 + mouse_opacity = MOUSE_OPACITY_TRANSPARENT /obj/effect/overlay/temp/emp_sparks/New(loc) setDir(pick(GLOB.cardinals)) @@ -234,8 +235,12 @@ icon_state = "emppulse" effect_duration = 20 - - +/obj/effect/overlay/temp/elec_arc + icon = 'icons/effects/effects.dmi' + icon_state = "electricity" + name = "electric arc" + effect_duration = 3 SECONDS + mouse_opacity = MOUSE_OPACITY_TRANSPARENT //gib animation diff --git a/code/game/objects/explosion_recursive.dm b/code/game/objects/explosion_recursive.dm index 2ec61b0cc1f1..855f6c2f43c7 100644 --- a/code/game/objects/explosion_recursive.dm +++ b/code/game/objects/explosion_recursive.dm @@ -71,7 +71,9 @@ explosion resistance exactly as much as their health falloff = max(falloff0, power/100) //prevent explosions with a range larger than 100 tiles minimum_spread_power = -power * reflection_amplification_limit - msg_admin_attack("Explosion with Power: [power], Falloff: [falloff] in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]).", src.loc.x, src.loc.y, src.loc.z) + var/obj/causing_obj = explosion_cause_data?.resolve_cause() + var/mob/causing_mob = explosion_cause_data?.resolve_mob() + msg_admin_attack("Explosion with Power: [power], Falloff: [falloff],[causing_obj ? " from [causing_obj]" : ""][causing_mob ? " by [key_name(causing_mob)]" : ""] in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]).", loc.x, loc.y, loc.z) playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(power^2,1)) playsound(epicenter, "explosion", 90, 1, max(round(power,1),7) ) diff --git a/code/game/objects/items/devices/RCD.dm b/code/game/objects/items/devices/RCD.dm deleted file mode 100644 index 00e569800314..000000000000 --- a/code/game/objects/items/devices/RCD.dm +++ /dev/null @@ -1,194 +0,0 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/* -CONTAINS: -RCD -*/ -/obj/item/device/rcd - name = "rapid-construction-device (RCD)" - desc = "A device used to rapidly build walls/floor." - icon = 'icons/obj/items/devices.dmi' - icon_state = "rcd" - opacity = FALSE - density = FALSE - anchored = FALSE - flags_atom = FPRINT|CONDUCT - force = 10 - throwforce = 10 - throw_speed = SPEED_FAST - throw_range = 5 - w_class = SIZE_MEDIUM - matter = list("metal" = 50000) - - var/datum/effect_system/spark_spread/spark_system - var/stored_matter = 0 - var/working = 0 - var/mode = 1 - var/canRwall = 0 - var/disabled = 0 - - -/obj/item/device/rcd/New() - desc = "A RCD. It currently holds [stored_matter]/30 matter-units." - src.spark_system = new /datum/effect_system/spark_spread - spark_system.set_up(5, 0, src) - spark_system.attach(src) - return - -/obj/item/device/rcd/Destroy() - QDEL_NULL(spark_system) - return ..() - - -/obj/item/device/rcd/attackby(obj/item/W, mob/user) - ..() - if(istype(W, /obj/item/ammo_rcd)) - if((stored_matter + 10) > 30) - to_chat(user, SPAN_NOTICE("The RCD cant hold any more matter-units.")) - return - user.drop_held_item() - qdel(W) - stored_matter += 10 - playsound(src.loc, 'sound/machines/click.ogg', 15, 1) - to_chat(user, SPAN_NOTICE("The RCD now holds [stored_matter]/30 matter-units.")) - desc = "A RCD. It currently holds [stored_matter]/30 matter-units." - return - - -/obj/item/device/rcd/attack_self(mob/user) - ..() - - //Change the mode - playsound(src.loc, 'sound/effects/pop.ogg', 15, 0) - switch(mode) - if(1) - mode = 2 - to_chat(user, SPAN_NOTICE("Changed mode to 'Airlock'")) - if(prob(20)) - src.spark_system.start() - return - if(2) - mode = 3 - to_chat(user, SPAN_NOTICE("Changed mode to 'Deconstruct'")) - if(prob(20)) - src.spark_system.start() - return - if(3) - mode = 1 - to_chat(user, SPAN_NOTICE("Changed mode to 'Floor & Walls'")) - if(prob(20)) - src.spark_system.start() - return - -/obj/item/device/rcd/proc/activate() - playsound(src.loc, 'sound/items/Deconstruct.ogg', 25, 1) - - -/obj/item/device/rcd/afterattack(atom/A, mob/user, proximity) - if(!proximity) return - if(disabled) - return 0 - if(istype(A,/area/shuttle) || istype(A,/turf/open/space/transit)) - return 0 - if(!(istype(A, /turf) || istype(A, /obj/structure/machinery/door/airlock))) - return 0 - - switch(mode) - if(1) - if(istype(A, /turf/open/space)) - if(useResource(1, user)) - to_chat(user, "Building Floor...") - activate() - A:ChangeTurf(/turf/open/floor/plating/airless) - return 1 - return 0 - - if(istype(A, /turf/open/floor)) - if(checkResource(3, user)) - to_chat(user, "Building Wall ...") - playsound(src.loc, 'sound/machines/click.ogg', 15, 1) - if(do_after(user, 20, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) - if(!useResource(3, user)) return 0 - activate() - A:ChangeTurf(/turf/closed/wall) - return 1 - return 0 - - if(2) - if(istype(A, /turf/open/floor)) - if(checkResource(10, user)) - to_chat(user, "Building Airlock...") - playsound(src.loc, 'sound/machines/click.ogg', 15, 1) - if(do_after(user, 50, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) - if(!useResource(10, user)) return 0 - activate() - var/obj/structure/machinery/door/airlock/T = new /obj/structure/machinery/door/airlock( A ) - T.autoclose = 1 - return 1 - return 0 - return 0 - - if(3) - if(istype(A, /turf/closed/wall)) - var/turf/closed/wall/WL = A - if(WL.hull) - return 0 - if(istype(A, /turf/closed/wall/r_wall) && !canRwall) - return 0 - if(checkResource(5, user)) - to_chat(user, "Deconstructing Wall...") - playsound(src.loc, 'sound/machines/click.ogg', 15, 1) - if(do_after(user, 40, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) - if(!useResource(5, user)) return 0 - activate() - A:ChangeTurf(/turf/open/floor/plating/airless) - return 1 - return 0 - - if(istype(A, /turf/open/floor) && !istype(A, /turf/open/floor/plating)) - if(checkResource(5, user)) - to_chat(user, "Deconstructing Floor...") - playsound(src.loc, 'sound/machines/click.ogg', 15, 1) - if(do_after(user, 50, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) - if(!useResource(5, user)) return 0 - activate() - A:ChangeTurf(/turf/open/floor/plating/airless) - return 1 - return 0 - - if(istype(A, /obj/structure/machinery/door/airlock)) - if(checkResource(10, user)) - to_chat(user, "Deconstructing Airlock...") - playsound(src.loc, 'sound/machines/click.ogg', 15, 1) - if(do_after(user, 50, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) - if(!useResource(10, user)) return 0 - activate() - qdel(A) - return 1 - return 0 - return 0 - else - to_chat(user, "ERROR: RCD in MODE: [mode] attempted use by [user]. Send this text #coderbus or an admin.") - return 0 - -/obj/item/device/rcd/proc/useResource(amount, mob/user) - if(stored_matter < amount) - return 0 - stored_matter -= amount - desc = "A RCD. It currently holds [stored_matter]/30 matter-units." - return 1 - -/obj/item/device/rcd/proc/checkResource(amount, mob/user) - return stored_matter >= amount - -/obj/item/ammo_rcd - name = "compressed matter cartridge" - desc = "Highly compressed matter for the RCD." - icon = 'icons/obj/items/weapons/guns/legacy/old_bayguns.dmi' - icon_state = "rcd" - item_state = "rcdammo" - opacity = FALSE - density = FALSE - anchored = FALSE - - matter = list("metal" = 30000,"glass" = 15000) diff --git a/code/game/objects/items/devices/RSF.dm b/code/game/objects/items/devices/RSF.dm deleted file mode 100644 index 29f84c7c6d0c..000000000000 --- a/code/game/objects/items/devices/RSF.dm +++ /dev/null @@ -1,98 +0,0 @@ -/* -CONTAINS: -RSF - -*/ - -/obj/item/device/rsf - name = "\improper Rapid-Service-Fabricator" - desc = "A device used to rapidly deploy service items." - icon = 'icons/obj/items/devices.dmi' - icon_state = "rcd" - opacity = FALSE - density = FALSE - anchored = FALSE - var/stored_matter = 30 - var/mode = 1 - w_class = SIZE_MEDIUM - -/obj/item/device/rsf/get_examine_text(mob/user) - . = ..() - . += "It currently holds [stored_matter]/30 fabrication-units." - -/obj/item/device/rsf/attackby(obj/item/W, mob/user) - ..() - if (istype(W, /obj/item/ammo_rcd)) - - if ((stored_matter + 10) > 30) - to_chat(user, "The RSF can't hold any more matter.") - return - - qdel(W) - - stored_matter += 10 - playsound(src.loc, 'sound/machines/click.ogg', 15, 1) - to_chat(user, "The RSF now holds [stored_matter]/30 fabrication-units.") - return - -/obj/item/device/rsf/attack_self(mob/user) - ..() - playsound(src.loc, 'sound/effects/pop.ogg', 15, 0) - if (mode == 1) - mode = 2 - to_chat(user, "Changed dispensing mode to 'Drinking Glass'") - return - if (mode == 2) - mode = 3 - to_chat(user, "Changed dispensing mode to 'Paper'") - return - if (mode == 3) - mode = 4 - to_chat(user, "Changed dispensing mode to 'Pen'") - return - if (mode == 4) - mode = 5 - to_chat(user, "Changed dispensing mode to 'Dice Pack'") - return - if (mode == 5) - mode = 6 - to_chat(user, "Changed dispensing mode to 'Cigarette'") - return - if (mode == 6) - mode = 1 - to_chat(user, "Changed dispensing mode to 'Dosh'") - return - // Change mode - -/obj/item/device/rsf/afterattack(atom/A, mob/user, proximity) - - if(!proximity) return - - if(stored_matter <= 0) - return - - if(!istype(A, /obj/structure/surface/table) && !istype(A, /turf/open/floor)) - return - - playsound(src.loc, 'sound/machines/click.ogg', 25, 1) - var/obj/product - - switch(mode) - if(1) - product = new /obj/item/spacecash/c10() - if(2) - product = new /obj/item/reagent_container/food/drinks/drinkingglass() - if(3) - product = new /obj/item/paper() - if(4) - product = new /obj/item/tool/pen() - if(5) - product = new /obj/item/storage/pill_bottle/dice() - if(6) - product = new /obj/item/clothing/mask/cigarette() - - to_chat(user, "Dispensing [product ? product : "product"]...") - product.forceMove(get_turf(A)) - - stored_matter-- - to_chat(user, "The RSF now holds [stored_matter]/30 fabrication-units.") diff --git a/code/game/objects/items/devices/RSP.dm b/code/game/objects/items/devices/RSP.dm deleted file mode 100644 index cb61de1a77cc..000000000000 --- a/code/game/objects/items/devices/RSP.dm +++ /dev/null @@ -1,11 +0,0 @@ -/obj/item/device/rsp - name = "\improper Rapid-Seed-Producer (RSP)" - desc = "A device used to rapidly deploy seeds." - icon = 'icons/obj/items/devices.dmi' - icon_state = "rsp" - opacity = FALSE - density = FALSE - anchored = FALSE - var/stored_matter = 0 - var/mode = 1 - w_class = SIZE_MEDIUM diff --git a/code/game/objects/items/devices/binoculars.dm b/code/game/objects/items/devices/binoculars.dm index 5da4704e0e78..3248115adfa8 100644 --- a/code/game/objects/items/devices/binoculars.dm +++ b/code/game/objects/items/devices/binoculars.dm @@ -403,6 +403,7 @@ COOLDOWN_START(designator, spotting_cooldown, 0) /datum/action/item_action/specialist/spotter_target/action_activate() + . = ..() if(!ishuman(owner)) return var/mob/living/carbon/human/human = owner diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 8d5e3cc752ff..e506f51ce21c 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -15,7 +15,7 @@ ground_offset_x = 2 ground_offset_y = 6 - actions_types = list(/datum/action/item_action) + actions_types = list(/datum/action/item_action/toggle) var/on = FALSE var/raillight_compatible = TRUE //Can this be turned into a rail light ? var/toggleable = TRUE diff --git a/code/game/objects/items/devices/helmet_visors.dm b/code/game/objects/items/devices/helmet_visors.dm index 8f921a62f3f5..e2005a841bc3 100644 --- a/code/game/objects/items/devices/helmet_visors.dm +++ b/code/game/objects/items/devices/helmet_visors.dm @@ -146,6 +146,7 @@ return /datum/action/item_action/view_publications/helmet_visor/action_activate() + . = ..() var/obj/item/device/helmet_visor/medical/advanced/medical_visor = locate() in holder_item if(!medical_visor) diff --git a/code/game/objects/items/devices/motion_detector.dm b/code/game/objects/items/devices/motion_detector.dm index 3551e3a02bef..f68295001f92 100644 --- a/code/game/objects/items/devices/motion_detector.dm +++ b/code/game/objects/items/devices/motion_detector.dm @@ -33,9 +33,9 @@ var/long_range_cooldown = 2 var/blip_type = "detector" var/iff_signal = FACTION_MARINE - actions_types = list(/datum/action/item_action) + actions_types = list(/datum/action/item_action/toggle) var/scanning = FALSE // controls if MD is in process of scan - var/datum/shape/rectangle/range_bounds + var/datum/shape/rectangle/square/range_bounds var/long_range_locked = FALSE //only long-range MD var/ping_overlay @@ -48,7 +48,7 @@ /obj/item/device/motiondetector/Initialize() . = ..() - range_bounds = new //Just creating a rectangle datum + range_bounds = new //Just creating a square datum update_icon() /obj/item/device/motiondetector/Destroy() @@ -215,12 +215,7 @@ if(!istype(cur_turf)) return - if(!range_bounds) - range_bounds = new/datum/shape/rectangle - range_bounds.center_x = cur_turf.x - range_bounds.center_y = cur_turf.y - range_bounds.width = detector_range * 2 - range_bounds.height = detector_range * 2 + range_bounds.set_shape(cur_turf.x, cur_turf.y, detector_range * 2) var/list/ping_candidates = SSquadtree.players_in_range(range_bounds, cur_turf.z, QTREE_EXCLUDE_OBSERVER | QTREE_SCAN_MOBS) diff --git a/code/game/objects/items/devices/suit_cooling.dm b/code/game/objects/items/devices/suit_cooling.dm deleted file mode 100644 index 564b3e41f591..000000000000 --- a/code/game/objects/items/devices/suit_cooling.dm +++ /dev/null @@ -1,179 +0,0 @@ -/obj/item/device/suit_cooling_unit - name = "portable suit cooling unit" - desc = "A portable heat sink and liquid cooled radiator that can be hooked up to a space suit's existing temperature controls to provide industrial levels of cooling." - w_class = SIZE_LARGE - icon_state = "suitcooler0" - flags_equip_slot = SLOT_BACK //you can carry it on your back if you want, but it won't do anything unless attached to suit storage - - //copied from tank.dm - flags_atom = FPRINT|CONDUCT - force = 5 - throwforce = 10 - throw_speed = SPEED_FAST - throw_range = 4 - - - - var/on = 0 //is it turned on? - var/cover_open = 0 //is the cover open? - var/obj/item/cell/cell - var/max_cooling = 12 //in degrees per second - probably don't need to mess with heat capacity here - var/charge_consumption = 16.6 //charge per second at max_cooling - var/thermostat = T20C - - //TODO: make it heat up the surroundings when not in space - -/obj/item/device/suit_cooling_unit/Initialize(mapload, ...) - . = ..() - - START_PROCESSING(SSobj, src) - - cell = new/obj/item/cell(src) //comes with the crappy default power cell - high-capacity ones shouldn't be hard to find - -/obj/item/device/suit_cooling_unit/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/device/suit_cooling_unit/process() - if (!on || !cell) - return - - if (!ismob(loc)) - return - - if (!attached_to_suit(loc)) //make sure they have a suit and we are attached to it - return - - var/mob/living/carbon/human/H = loc - - var/efficiency = 1 - H.get_pressure_weakness() //you need to have a good seal for effective cooling - var/env_temp = get_environment_temperature() //wont save you from a fire - var/temp_adj = min(H.bodytemperature - max(thermostat, env_temp), max_cooling) - - if (temp_adj < 0.5) //only cools, doesn't heat, also we don't need extreme precision - return - - var/charge_usage = (temp_adj/max_cooling)*charge_consumption - - H.bodytemperature -= temp_adj*efficiency - H.recalculate_move_delay = TRUE - - cell.use(charge_usage) - - if(cell.charge <= 0) - turn_off() - -/obj/item/device/suit_cooling_unit/proc/get_environment_temperature() - if (ishuman(loc)) - var/mob/living/carbon/human/H = loc - return H.return_temperature() - - var/turf/T = get_turf(src) - return T.return_temperature() - -/obj/item/device/suit_cooling_unit/proc/attached_to_suit(mob/M) - if (!ishuman(M)) - return 0 - - var/mob/living/carbon/human/H = M - - if (!H.wear_suit || H.s_store != src) - return 0 - - return 1 - -/obj/item/device/suit_cooling_unit/proc/turn_on() - if(!cell) - return - if(cell.charge <= 0) - return - - on = 1 - updateicon() - -/obj/item/device/suit_cooling_unit/proc/turn_off() - if (ismob(src.loc)) - var/mob/M = src.loc - M.show_message("\The [src] clicks and whines as it powers down.", SHOW_MESSAGE_AUDIBLE) //let them know in case it's run out of power. - on = 0 - updateicon() - -/obj/item/device/suit_cooling_unit/attack_self(mob/user) - ..() - - if(cover_open && cell) - if(ishuman(user)) - user.put_in_hands(cell) - else - cell.forceMove(get_turf(loc)) - - cell.add_fingerprint(user) - cell.update_icon() - - to_chat(user, "You remove [cell].") - src.cell = null - updateicon() - return - - //TODO use a UI like the air tanks - if(on) - turn_off() - else - turn_on() - if (on) - to_chat(user, "You switch on [src].") - -/obj/item/device/suit_cooling_unit/attackby(obj/item/W as obj, mob/user as mob) - if (HAS_TRAIT(W, TRAIT_TOOL_SCREWDRIVER)) - if(cover_open) - cover_open = 0 - to_chat(user, "You screw the panel into place.") - else - cover_open = 1 - to_chat(user, "You unscrew the panel.") - updateicon() - return - - if (istype(W, /obj/item/cell)) - if(cover_open) - if(cell) - to_chat(user, "There is \a [cell] already installed here.") - else - if(user.drop_held_item()) - W.forceMove(src) - cell = W - to_chat(user, "You insert [cell].") - updateicon() - return - - return ..() - -/obj/item/device/suit_cooling_unit/proc/updateicon() - if (cover_open) - if (cell) - icon_state = "suitcooler1" - else - icon_state = "suitcooler2" - else - icon_state = "suitcooler0" - -/obj/item/device/suit_cooling_unit/get_examine_text(mob/user) - . = ..() - if (on) - if (attached_to_suit(src.loc)) - . += "It's switched on and running." - else - . += "It's switched on, but not attached to anything." - else - . += "It is switched off." - - if (cover_open) - if(cell) - . += "The panel is open, exposing [cell]." - else - . += "The panel is open." - - if (cell) - . += "The charge meter reads [floor(cell.percent())]%." - else - . += "It doesn't have a power cell installed." diff --git a/code/game/objects/items/devices/walkman.dm b/code/game/objects/items/devices/walkman.dm index 42c03d757dbd..bef8e8f5ff79 100644 --- a/code/game/objects/items/devices/walkman.dm +++ b/code/game/objects/items/devices/walkman.dm @@ -269,6 +269,7 @@ button.name = name /datum/action/item_action/walkman/play_pause/action_activate() + . = ..() if(target) var/obj/item/device/walkman/WM = target WM.attack_self(owner) @@ -282,6 +283,7 @@ button.name = name /datum/action/item_action/walkman/next_song/action_activate() + . = ..() if(target) var/obj/item/device/walkman/WM = target WM.next_song(owner) @@ -295,6 +297,7 @@ button.name = name /datum/action/item_action/walkman/restart_song/action_activate() + . = ..() if(target) var/obj/item/device/walkman/WM = target WM.restart_song(owner) diff --git a/code/game/objects/items/devices/whistle.dm b/code/game/objects/items/devices/whistle.dm index 331df3ffa006..07196a3e1bb9 100644 --- a/code/game/objects/items/devices/whistle.dm +++ b/code/game/objects/items/devices/whistle.dm @@ -5,7 +5,7 @@ w_class = SIZE_TINY flags_atom = FPRINT|CONDUCT flags_equip_slot = SLOT_FACE - actions_types = list(/datum/action/item_action) + actions_types = list(/datum/action/item_action/toggle/use) var/volume = 60 var/spam_cooldown_time = 10 SECONDS @@ -51,7 +51,6 @@ usr.put_in_l_hand(src) add_fingerprint(usr) - /obj/item/device/hailer name = "hailer" desc = "Used by obese officers to save their breath for running." diff --git a/code/game/objects/items/explosives/grenades/marines.dm b/code/game/objects/items/explosives/grenades/marines.dm index 1cd3e1577c57..09c0197cda7f 100644 --- a/code/game/objects/items/explosives/grenades/marines.dm +++ b/code/game/objects/items/explosives/grenades/marines.dm @@ -465,6 +465,187 @@ icon_state = "grenade_phos_clf" item_state = "grenade_phos_clf" +/obj/item/explosive/grenade/sebb + name = "\improper G2 Electroshock grenade" + desc = "This is a G2 Electroshock Grenade. Produced by Armat Battlefield Systems, it's sometimes referred to as the Sonic Electric Ball Breaker, \ + after a rash of incidents where the intense 1.2 gV sonic payload caused... rupturing. \ + A bounding landmine mode is available for this weapon which activates a small drill to self-bury itself when planted. Simply plant it at your feet and walk away." + icon_state = "grenade_sebb" + item_state = "grenade_sebb" + det_time = 3 SECONDS + underslug_launchable = TRUE + /// Maximum range of effect + var/range = 5 + /// Maximum possible damage before falloff. + var/damage = 110 + /// Factor to mutiply the effect range has on damage. + var/falloff_dam_reduction_mult = 20 + /// Post falloff calc damage is divided by this to get xeno slowdown + var/xeno_slowdown_numerator = 12 + /// Post falloff calc damage is multipled by this to get human stamina damage + var/human_stam_dam_factor = 0.9 + +/obj/item/explosive/grenade/sebb/get_examine_text(mob/user) + . = ..() + . += SPAN_NOTICE("To put into mine mode, plant at feet.") + +/obj/item/explosive/grenade/sebb/afterattack(atom/target, mob/user, proximity) + var/turf/user_turf = get_turf(user) + if(active) + return + + if(!isturf(target)) + return + + if(user.action_busy) + return + + if(target != get_turf(user)) + return + + if(locate(/obj/item/explosive/mine) in get_turf(src)) + to_chat(user, SPAN_WARNING("There already is a mine at this position!")) + return + + if(antigrief_protection && user.faction == FACTION_MARINE && explosive_antigrief_check(src, user)) + to_chat(user, SPAN_WARNING("\The [name]'s safe-area accident inhibitor prevents you from planting!")) + msg_admin_niche("[key_name(user)] attempted to plant \a [name] in [get_area(src)] [ADMIN_JMP(src.loc)]") + return + + if(ishuman(user)) + var/mob/living/carbon/human/human = user + if(!human.allow_gun_usage) + to_chat(user, SPAN_WARNING("Your programming prevents you from using this!")) + return + + if(user_turf && (user_turf.density || locate(/obj/structure/fence) in user_turf)) + to_chat(user, SPAN_WARNING("You can't plant a mine here.")) + return + + if(Adjacent(/obj/item/explosive/mine)) // bit more strict on this than normal mines + to_chat(user, SPAN_WARNING("Too close to another mine! Plant it somewhere less obvious.")) + return + + user.visible_message(SPAN_NOTICE("[user] starts deploying [src]."), + SPAN_NOTICE("You switch [src] into landmine mode and start placing it...")) + playsound(user.loc, 'sound/effects/thud.ogg', 40) + if(!do_after(user, 5 SECONDS * user.get_skill_duration_multiplier(SKILL_CONSTRUCTION), INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) + to_chat(user, SPAN_NOTICE("You stop planting.")) + return + + user.visible_message(SPAN_NOTICE("[user] finishes deploying [src]."), + SPAN_NOTICE("You finish deploying [src].")) + var/obj/item/explosive/mine/sebb/planted = new /obj/item/explosive/mine/sebb(get_turf(user)) + planted.activate_sensors() + planted.iff_signal = user.faction // assuring IFF is set + planted.pixel_x += rand(-5, 5) + planted.pixel_y += rand(-5, 5) + qdel(src) + +/obj/item/explosive/grenade/sebb/activate() + ..() + var/beeplen = 6 // Actual length of the sound rounded up to nearest decisecond + var/soundtime = det_time - beeplen + if(det_time < beeplen) // just play sound if detonation shorter than the sound + playsound(loc, 'sound/effects/sebb_explode.ogg', 90, 0, 10) + else + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), loc, 'sound/effects/sebb_beep.ogg', 60, 0, 10), soundtime) + + + +/obj/item/explosive/grenade/sebb/prime() + var/datum/effect_system/spark_spread/sparka = new + var/turf/sebb_turf = get_turf(src) + var/list/full_range = oview(range, src) // Fill a list of stuff in the range so we won't have to spam oview + new /obj/effect/overlay/temp/sebb(sebb_turf) + + playsound(src.loc, 'sound/effects/sebb_explode.ogg', 90, 0, 10) + + for(var/obj/structure/machinery/defenses/sentry/sentry_stun in full_range) + sentry_stun.sentry_range = 0 // Temporarily "disable" the sentry by killing its range then setting it back. + new /obj/effect/overlay/temp/elec_arc(get_turf(sentry_stun)) // sprites are meh but we need visual indication that the sentry was messed up + addtimer(VARSET_CALLBACK(sentry_stun, sentry_range, initial(sentry_stun.sentry_range)), 5 SECONDS) // assure to set it back + sentry_stun.visible_message(SPAN_DANGER("[src]'s screen flickes violently as it's shocked!")) + sentry_stun.visible_message(SPAN_DANGER("[src] says \"ERROR: Fire control system resetting due to critical voltage flucuation!\"")) + sparka.set_up(1, 1, sentry_stun) + sparka.start() + + for(var/turf/turf in full_range) + if(prob(8)) + var/datum/effect_system/spark_spread/sparkTurf = new //using a different spike system because the spark system doesn't like when you reuse it for differant things + sparkTurf.set_up(1, 1, turf) + sparkTurf.start() + if(prob(10)) + new /obj/effect/overlay/temp/emp_sparks(turf) + + for(var/mob/living/carbon/mob in full_range) // no legacy mob support + + var/mob_dist = get_dist(src, mob) // Distance from mob + + /** + * Damage equation: damage - (mob distance * falloff_dam_reduction_mult) + * Example: A marine is 3 tiles out, the distance (3) is multiplied by falloff_dam_reduction_mult to get falloff. + * The raw damage is minused by falloff to get actual damage + */ + + var/falloff = mob_dist * falloff_dam_reduction_mult + var/damage_applied = damage - falloff // Final damage applied after falloff calc + sparka.set_up(1, 1, mob) + sparka.start() + shake_camera(mob, 1, 1) + if(ishuman(mob)) + var/mob/living/carbon/human/shocked_human = mob + if(isspeciessynth(shocked_human)) // Massive overvoltage to ungrounded robots is pretty bad + shocked_human.Stun(1 + (damage_applied/40)) + damage_applied *= 1.5 + new /obj/effect/overlay/temp/elec_arc(get_turf(shocked_human)) + to_chat(mob, SPAN_HIGHDANGER("All of your systems jam up as your main bus is overvolted by [damage_applied*2] volts.")) + mob.visible_message(SPAN_WARNING("[mob] seizes up from the elctric shock")) + shocked_human.take_overall_armored_damage(damage_applied, ARMOR_ENERGY, BURN, 90) // 90% chance to be on additional limbs + shocked_human.make_dizzy(damage_applied) + mob.apply_stamina_damage(damage_applied*human_stam_dam_factor) // Stamina damage + shocked_human.emote("pain") + else //nonhuman damage + slow + mob.apply_damage(damage_applied, BURN) + if((mob_dist < (range-3))) // 2 tiles around small superslow + mob.Superslow(2) + mob.Slow(damage_applied/11) + + if(mob_dist < 1) // Range based stuff, standing ontop of the equivalent of a canned lighting bolt should mess you up. + mob.Superslow(3) // Note that humans will likely be in stamcrit so it's always worse for them when ontop of it and we can just balancing it on xenos. + mob.eye_blurry = damage_applied/4 + mob.Daze(1) + else if((mob_dist < (range-1)) && (mob.mob_size < MOB_SIZE_XENO_VERY_SMALL)) // Flicker stun humans that are closer to the grenade and larvas too. + mob.apply_effect(1 + (damage_applied/100),WEAKEN) // 1 + damage/40 + mob.eye_blurry = damage_applied/8 + + else + to_chat(mob, SPAN_HIGHDANGER("Your entire body seizes up as a powerful shock courses through it!")) + + + new /obj/effect/overlay/temp/emp_sparks(mob) + mob.make_jittery(damage_applied*2) + empulse(src, 1, 2) // mini EMP + qdel(src) + + +/obj/item/explosive/grenade/sebb/primed + desc = "A G2 Electroshock Grenade, looks like it's quite angry! Oh shit!" + det_time = 7 // 0.7 seconds to blow up. We want them to get caught if they go through. + +/obj/item/explosive/grenade/sebb/primed/Initialize() + . = ..() + src.visible_message(SPAN_HIGHDANGER("[src] pops out of the ground!")) + activate() + +/obj/effect/overlay/temp/sebb + icon = 'icons/effects/sebb.dmi' + icon_state = "sebb_explode" + layer = ABOVE_LIGHTING_PLANE + pixel_x = -175 // We need these offsets to force center the sprite because BYOND is dumb + pixel_y = -175 + appearance_flags = RESET_COLOR + /* //================================================ Nerve Gas Grenades diff --git a/code/game/objects/items/explosives/mine.dm b/code/game/objects/items/explosives/mine.dm index 45065a2de1de..6e7aa2bdccc3 100644 --- a/code/game/objects/items/explosives/mine.dm +++ b/code/game/objects/items/explosives/mine.dm @@ -14,6 +14,7 @@ throw_speed = SPEED_VERY_FAST unacidable = TRUE flags_atom = FPRINT|CONDUCT + antigrief_protection = TRUE allowed_sensors = list(/obj/item/device/assembly/prox_sensor) max_container_volume = 120 reaction_limits = list( "max_ex_power" = 105, "base_ex_falloff" = 60, "max_ex_shards" = 32, @@ -71,7 +72,12 @@ if(active || user.action_busy) return - user.visible_message(SPAN_NOTICE("[user] starts deploying [src]."), \ + if(antigrief_protection && user.faction == FACTION_MARINE && explosive_antigrief_check(src, user)) + to_chat(user, SPAN_WARNING("\The [name]'s safe-area accident inhibitor prevents you from planting!")) + msg_admin_niche("[key_name(user)] attempted to plant \a [name] in [get_area(src)] [ADMIN_JMP(src.loc)]") + return + + user.visible_message(SPAN_NOTICE("[user] starts deploying [src]."), SPAN_NOTICE("You start deploying [src].")) if(!do_after(user, 40, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE)) user.visible_message(SPAN_NOTICE("[user] stops deploying [src]."), \ @@ -317,3 +323,19 @@ customizable = TRUE matter = list("metal" = 3750) has_blast_wave_dampener = TRUE + +/obj/item/explosive/mine/sebb + name = "\improper G2 Electroshock grenade" + icon_state = "grenade_sebb_planted" + desc = "A G2 electroshock grenade planted as a landmine." + pixel_y = -5 + anchored = TRUE // this is supposed to be planeted already when spawned + +/obj/item/explosive/mine/sebb/disarm() + . = ..() + new /obj/item/explosive/grenade/sebb(get_turf(src)) + qdel(src) + +/obj/item/explosive/mine/sebb/prime() + new /obj/item/explosive/grenade/sebb/primed(get_turf(src)) + qdel(src) diff --git a/code/game/objects/items/hoverpack.dm b/code/game/objects/items/hoverpack.dm index 02a2d4be779a..65406eb15dc6 100644 --- a/code/game/objects/items/hoverpack.dm +++ b/code/game/objects/items/hoverpack.dm @@ -208,6 +208,7 @@ return TRUE /datum/action/item_action/hover/action_activate() + . = ..() var/mob/living/carbon/human/H = owner if(H.selected_ability == src) to_chat(H, "You will no longer use [name] with \ diff --git a/code/game/objects/items/reagent_containers/reagent_container.dm b/code/game/objects/items/reagent_containers/reagent_container.dm index 5207df4ca7bb..37029ff247d6 100644 --- a/code/game/objects/items/reagent_containers/reagent_container.dm +++ b/code/game/objects/items/reagent_containers/reagent_container.dm @@ -109,5 +109,6 @@ button.overlays += IMG /datum/action/item_action/reagent_container/set_transfer_amount/action_activate() + . = ..() var/obj/item/reagent_container/cont = holder_item cont.set_APTFT() diff --git a/code/game/objects/items/stacks/flags.dm b/code/game/objects/items/stacks/flags.dm index 484d2779f5f8..14833812b06c 100644 --- a/code/game/objects/items/stacks/flags.dm +++ b/code/game/objects/items/stacks/flags.dm @@ -76,3 +76,208 @@ newflag.icon_state = "[newflag.base_state]_open" newflag.visible_message("[user] plants [newflag] firmly in the ground.") src.use(1) + + +/// PLANTABLE FLAG + +/obj/structure/flag/plantable + name = "flag" + desc = "A flag of something. This one looks like you could dismantle it." + icon = 'icons/obj/structures/plantable_flag.dmi' + pixel_x = 9 // All flags need to be offset to the right by 9 to be centered. + layer = ABOVE_XENO_LAYER + health = 150 + unacidable = TRUE + + /// The typepath for the flag item that gets spawned when the flag is taken down. + var/flag_type = /obj/item/flag/plantable + /// Used to limit the spam of the warcry_extra_sound + COOLDOWN_DECLARE(warcry_cooldown_struc) + +/obj/structure/flag/plantable/attack_hand(mob/user) + ..() + disassemble(user, flag_type) + +/// Proc for dismantling the flag into an item that can be picked up. +/obj/structure/flag/plantable/proc/disassemble(mob/user, flag_type) + if(user.action_busy) + return + + user.visible_message(SPAN_NOTICE("[user] starts taking [src] down..."), SPAN_NOTICE("You start taking [src] down...")) + + playsound(loc, 'sound/effects/flag_raising.ogg', 30) + if(!do_after(user, 6 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC) || QDELETED(src)) + return + + playsound(loc, 'sound/effects/flag_raised.ogg', 30) + user.visible_message(SPAN_NOTICE("[user] starts takes [src] down!"), SPAN_NOTICE("You take [src] down!")) + var/obj/item/flag/plantable/flag_item = new flag_type(loc) + user.put_in_hands(flag_item) + COOLDOWN_START(flag_item, warcry_cooldown_item, COOLDOWN_TIMELEFT(src, warcry_cooldown_struc)) + qdel(src) + +/// Proc for when the flag gets forcefully dismantled (due to general damage, explosions, etc.) +/obj/structure/flag/plantable/proc/demolish(flag_type) + playsound(loc, 'sound/effects/flag_raised.ogg', 30) + visible_message(SPAN_WARNING("[src] crumples to the ground!")) + var/obj/item/flag/plantable/flag_item = new flag_type(loc) + COOLDOWN_START(flag_item, warcry_cooldown_item, COOLDOWN_TIMELEFT(src, warcry_cooldown_struc)) + qdel(src) + +// Procs for handling damage. +/obj/structure/flag/plantable/update_health(damage) + if(damage) + health -= damage + if(health <= 0) + demolish(flag_type) + +/obj/structure/flag/plantable/ex_act(severity) + if(health <= 0) + return + update_health(severity) + +/obj/structure/flag/plantable/attack_alien(mob/living/carbon/xenomorph/xeno) + if(xeno.a_intent == INTENT_HARM) + if(unslashable) + return + xeno.animation_attack_on(src) + playsound(loc, 'sound/effects/metalhit.ogg', 25, 1) + xeno.visible_message(SPAN_DANGER("[xeno] slashes [src]!"), SPAN_DANGER("We slash [src]!"), null, 5, CHAT_TYPE_XENO_COMBAT) + update_health(rand(xeno.melee_damage_lower, xeno.melee_damage_upper)) + return XENO_ATTACK_ACTION + else + to_chat(xeno, SPAN_WARNING("We stare at [src] cluelessly.")) + return XENO_NONCOMBAT_ACTION + +/obj/structure/flag/plantable/bullet_act(obj/projectile/bullet) + bullet_ping(bullet) + visible_message(SPAN_DANGER("[src] is hit by [bullet]!"), null, 4, CHAT_TYPE_TAKING_HIT) + update_health(bullet.damage) + return TRUE + +/obj/structure/flag/plantable/attackby(obj/item/weapon, mob/living/user) + if(!indestructible) + visible_message(SPAN_DANGER("[src] has been hit by [user] with [weapon]!"), null, 5, CHAT_TYPE_MELEE_HIT) + user.animation_attack_on(src) + playsound(loc, 'sound/effects/metalhit.ogg', 25, 1) + update_health(weapon.force * weapon.demolition_mod) + +/obj/item/flag/plantable + name = "plantable flag" + desc = "A flag of something. This one looks ready to be planted into the ground." + w_class = SIZE_LARGE + throw_range = 2 + icon = 'icons/obj/structures/plantable_flag.dmi' + inhand_x_dimension = 64 + inhand_y_dimension = 64 + force = 15 + throwforce = 5 + hitsound = "swing_hit" + unacidable = TRUE + indestructible = TRUE + item_icons = list( + WEAR_L_HAND = 'icons/mob/humans/onmob/items_lefthand_64.dmi', + WEAR_R_HAND = 'icons/mob/humans/onmob/items_righthand_64.dmi' + ) + + /// The typepath of the flag structure that gets spawned when the flag is planted. + var/flag_type = /obj/structure/flag/plantable + /// Used to check if nearby mobs belong to a faction when calculating for the stronger warcry. + var/faction + /// Does the flag play a unique warcry when planted? (Only while on harm intent.) + var/play_warcry = FALSE + /// The warcry's sound path. + var/warcry_sound + /// When there are more than 14 allies nearby, play this stronger warcry. + var/warcry_extra_sound + /// How many nearby allies do we need for the stronger warcry to be played? + var/allies_required = 14 + /// Used to limit the spam of the warcry_extra_sound + COOLDOWN_DECLARE(warcry_cooldown_item) + +/obj/item/flag/plantable/get_examine_text(mob/user) + . = ..() + if(play_warcry && user.faction == faction) + . += SPAN_NOTICE("Planting the flag while in HARM intent will cause you to bellow out a rallying warcry!") + +/// Proc for turning the flag item into a structure. +/obj/item/flag/plantable/proc/plant_flag(mob/living/user, play_warcry = FALSE, warcry_sound, warcry_extra_sound, faction) + if(user.action_busy) + return + + if(SSinterior.in_interior(user)) + to_chat(usr, SPAN_WARNING("There's no way to plant [src] in here!")) + return + + var/turf/turf_to_plant = get_step(user, user.dir) + if(istype(turf_to_plant, /turf/open)) + var/turf/open/floor = turf_to_plant + if(!floor.allow_construction || istype(floor, /turf/open/space)) + to_chat(user, SPAN_WARNING("You cannot deploy [src] here, find a more secure surface!")) + return + else + to_chat(user, SPAN_WARNING("[turf_to_plant] is blocking you from deploying [src]!")) + return + + for(var/obj/object in turf_to_plant) + if(object.density) + to_chat(usr, SPAN_WARNING("You need a clear, open area to plant [src], something is blocking the way in front of you!")) + return + + user.visible_message(SPAN_NOTICE("[user] starts planting [src] into the ground..."), SPAN_NOTICE("You start planting [src] into the ground...")) + playsound(user, 'sound/effects/flag_raising.ogg', 30) + if(!do_after(user, 6 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC)) + return + + user.visible_message(SPAN_NOTICE("[user] plants [src] into the ground!"), SPAN_NOTICE("You plant [src] into the ground!")) + var/obj/structure/flag/plantable/planted_flag = new flag_type(turf_to_plant) + + // If there are more than 14 allies nearby, play a stronger rallying cry. + // Otherwise, play the default warcry sound if there is one. If not, play a generic flag raising sfx. + if(play_warcry && user.faction == faction && user.a_intent == INTENT_HARM) + var/allies_nearby = 0 + if(COOLDOWN_FINISHED(src, warcry_cooldown_item)) + for(var/mob/living/carbon/human in orange(planted_flag, 7)) + if(human.is_dead() || human.faction != faction) + continue + allies_nearby++ + + user.show_speech_bubble("warcry") + if(allies_nearby >= allies_required) + playsound(user, warcry_extra_sound, 40) + // Start a cooldown on the flag structure. This way we can keep track of the cooldown when the flag is hoisted and taken down. + COOLDOWN_START(planted_flag, warcry_cooldown_struc, 90 SECONDS) + user.manual_emote("shouts an invigorating rallying cry!") + else + playsound(user, warcry_sound, 30) + user.manual_emote("shouts an inspiring cry!") + // Ditto. If the cooldown isn't finished we have to transfer the leftover time to the structure. + COOLDOWN_START(planted_flag, warcry_cooldown_struc, COOLDOWN_TIMELEFT(src, warcry_cooldown_item)) + else + playsound(loc, 'sound/effects/flag_raised.ogg', 30) + + qdel(src) + +/obj/item/flag/plantable/attack_self(mob/user) + ..() + plant_flag(user, play_warcry, warcry_sound, warcry_extra_sound, faction) + +// UNITED AMERICAS FLAG // +////////////////////////// + +/obj/item/flag/plantable/ua + name = "\improper United Americas flag" + desc = "The flag of the United Americas. This one looks ready to be planted into the ground." + icon = 'icons/obj/structures/plantable_flag.dmi' + icon_state = "flag_ua" + flag_type = /obj/structure/flag/plantable/ua + faction = FACTION_MARINE + play_warcry = TRUE + warcry_sound = 'sound/effects/flag_warcry_ua.ogg' + warcry_extra_sound = 'sound/effects/flag_warcry_ua_extra.ogg' + +/obj/structure/flag/plantable/ua + name = "\improper United Americas flag" + desc = "The flag of the United Americas. Semper fi." + icon_state = "flag_ua_planted" + flag_type = /obj/item/flag/plantable/ua diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index baa91db19396..06636d2c3f76 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -268,6 +268,7 @@ return TRUE /datum/action/item_action/specialist/santabag/action_activate() + . = ..() var/obj/item/storage/backpack/santabag/santa_bag = holder_item santa_bag.refill_santa_bag(owner) update_button_icon() @@ -537,6 +538,7 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r button.overlays += IMG /datum/action/item_action/rto_pack/use_phone/action_activate() + . = ..() for(var/obj/item/storage/backpack/marine/satchel/rto/radio_backpack in owner) radio_backpack.use_phone(owner) return @@ -870,6 +872,7 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r return TRUE /datum/action/item_action/specialist/toggle_cloak/action_activate() + . = ..() var/obj/item/storage/backpack/marine/satchel/scout_cloak/SC = holder_item SC.camouflage() diff --git a/code/game/objects/items/storage/large_holster.dm b/code/game/objects/items/storage/large_holster.dm index 02983e1552ed..d8e1ee51d0d8 100644 --- a/code/game/objects/items/storage/large_holster.dm +++ b/code/game/objects/items/storage/large_holster.dm @@ -375,6 +375,7 @@ return TRUE /datum/action/item_action/specialist/toggle_fuel/action_activate() + . = ..() var/obj/item/storage/large_holster/fuelpack/FP = holder_item if (!istype(FP)) return diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm deleted file mode 100644 index 3a5afef6cf1e..000000000000 --- a/code/game/objects/items/tanks/jetpack.dm +++ /dev/null @@ -1,85 +0,0 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/tank/jetpack - name = "Jetpack (Empty)" - desc = "A tank of compressed gas for use as propulsion in zero-gravity areas. Use with caution." - icon_state = "jetpack" - w_class = SIZE_LARGE - item_state = "jetpack" - distribute_pressure = ONE_ATMOSPHERE*O2STANDARD - var/datum/effect_system/ion_trail_follow/ion_trail - var/on = 0 - var/stabilization_on = 0 - var/volume_rate = 500 //Needed for borg jetpack transfer - actions_types = list(/datum/action/item_action) - -/obj/item/tank/jetpack/Initialize() - . = ..() - src.ion_trail = new /datum/effect_system/ion_trail_follow() - src.ion_trail.set_up(src) - -/obj/item/tank/jetpack/Destroy() - QDEL_NULL(ion_trail) - return ..() - - -/obj/item/tank/jetpack/verb/toggle_rockets() - set name = "Toggle Jetpack Stabilization" - set category = "Object" - set src in usr - src.stabilization_on = !( src.stabilization_on ) - to_chat(usr, "You toggle the stabilization [stabilization_on? "on":"off"].") - -/obj/item/tank/jetpack/verb/toggle() - set name = "Toggle Jetpack" - set category = "Object" - set src in usr - on = !on - if(on) - icon_state = "[icon_state]-on" - ion_trail.start() - else - icon_state = initial(icon_state) - ion_trail.stop() - - if (ismob(usr)) - var/mob/M = usr - M.update_inv_back() - - for(var/X in actions) - var/datum/action/A = X - A.update_button_icon() - -/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user) - if(!(src.on)) - return 0 - - if(pressure > 5) - return 1 - else - ion_trail.stop() - return 0 - - -/obj/item/tank/jetpack/ui_action_click() - toggle() - - -/obj/item/tank/jetpack/void - name = "Void Jetpack (Oxygen)" - desc = "It works well in a void." - icon_state = "jetpack-void" - item_state = "jetpack-void" - -/obj/item/tank/jetpack/oxygen - name = "Jetpack (Oxygen)" - desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas. Use with caution." - icon_state = "jetpack" - item_state = "jetpack" - -/obj/item/tank/jetpack/carbondioxide - name = "Jetpack (Carbon Dioxide)" - desc = "A tank of compressed carbon dioxide for use as propulsion in zero-gravity areas. Painted black to indicate that it should not be used as a source for internals." - distribute_pressure = 0 - icon_state = "jetpack-black" - item_state = "jetpack-black" diff --git a/code/game/objects/items/tools/kitchen_tools.dm b/code/game/objects/items/tools/kitchen_tools.dm index d6473b156a67..a4c4925fba2c 100644 --- a/code/game/objects/items/tools/kitchen_tools.dm +++ b/code/game/objects/items/tools/kitchen_tools.dm @@ -48,7 +48,7 @@ var/fullness = M.nutrition + (M.reagents.get_reagent_amount("nutriment") * 25) if(fullness > NUTRITION_HIGH) to_chat(user, SPAN_WARNING("[user == M ? "You" : "They"] don't feel like eating more right now.")) - return ..() + return reagents.set_source_mob(user) reagents.trans_to_ingest(M, reagents.total_volume) if(M == user) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index f93f2dab0984..2dc064aa86d4 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -416,7 +416,7 @@ var/offset_x = worn_x_dimension var/offset_y = worn_y_dimension - if(inhands) + if(inhands == 1 || inhands == 0) offset_x = inhand_x_dimension offset_y = inhand_y_dimension diff --git a/code/game/objects/structures/crates_lockers/closets/malfunction.dm b/code/game/objects/structures/crates_lockers/closets/malfunction.dm deleted file mode 100644 index 704e2c79157a..000000000000 --- a/code/game/objects/structures/crates_lockers/closets/malfunction.dm +++ /dev/null @@ -1,16 +0,0 @@ - -/obj/structure/closet/malf/suits - desc = "It's a storage unit for operational gear." - icon_state = "syndicate" - icon_closed = "syndicate" - icon_opened = "syndicate_open" - -/obj/structure/closet/malf/suits/Initialize() - . = ..() - new /obj/item/tank/jetpack/void(src) - new /obj/item/clothing/mask/breath(src) - new /obj/item/clothing/head/helmet/space/uscm(src) - new /obj/item/clothing/suit/space/uscm(src) - new /obj/item/tool/crowbar(src) - new /obj/item/cell(src) - new /obj/item/device/multitool(src) diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm index b000fd5733a2..0bf39322d107 100644 --- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm @@ -23,7 +23,7 @@ . = ..() #ifndef UNIT_TESTS - switch (pickweight(list("small" = 55, "aid" = 25, "tank" = 10, "both" = 10, "nothing" = 0, "delete" = 0))) + switch (pick_weight(list("small" = 55, "aid" = 25, "tank" = 10, "both" = 10, "nothing" = 1, "delete" = 1))) #else var/test = "both" switch (test) // We don't want randomness in tests diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index d891119a8404..8a10cd4d93ea 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -277,13 +277,6 @@ name = "RCD crate" desc = "A crate for the storage of the RCD." -/obj/structure/closet/crate/rcd/Initialize() - . = ..() - new /obj/item/ammo_rcd(src) - new /obj/item/ammo_rcd(src) - new /obj/item/ammo_rcd(src) - new /obj/item/device/rcd(src) - /obj/structure/closet/crate/freezer/rations //Fpr use in the escape shuttle desc = "A crate of emergency rations." name = "Emergency Rations" diff --git a/code/game/objects/structures/roof.dm b/code/game/objects/structures/roof.dm new file mode 100644 index 000000000000..e302133f0c9a --- /dev/null +++ b/code/game/objects/structures/roof.dm @@ -0,0 +1,165 @@ +/obj/structure/roof + name = "roof" + desc = "A roof" + icon = 'icons/turf/almayer.dmi' + icon_state = "plating_catwalk" + density = FALSE + layer = ABOVE_XENO_LAYER + health = 6000 + var/image/under_image //immage that is used when there is mob on connected node, displayed only to mobs under it not others + var/image/normal_image + var/datum/roof_master_node/linked_master + var/lazy_nodes = TRUE //if roof should create nodes that watch around it on spawn + + +/obj/structure/roof/Initialize() + . = ..() + under_image = image(icon, src, icon_state, layer = layer) + under_image.alpha = 127 + + normal_image = image(icon, src, icon_state, layer = layer) + + icon_state = null + + RegisterSignal(SSdcs, COMSIG_GLOB_MOB_LOGGED_IN, PROC_REF(add_default_image)) + + for(var/icon in GLOB.player_list) + add_default_image(SSdcs, icon) + if(lazy_nodes) //creates new node on each surounding tile if there is not one already + var/obj/effect/roof_node/neighbor = locate() in loc + if(!neighbor) + neighbor = new(loc) + for(var/direction in CARDINAL_ALL_DIRS) + var/adjacent_loc = get_step(src, direction) + neighbor = locate() in adjacent_loc + if(!neighbor) + neighbor = new(adjacent_loc) + return INITIALIZE_HINT_LATELOAD + +/obj/structure/roof/LateInitialize() //we use late init to allow for lazy nodes to spawn first on mapload + . = ..() + if(linked_master) + return + for(var/direction in CARDINAL_ALL_DIRS) //this searches if there is lattice with master already, to work with runtime creation + for(var/obj/structure/roof/roof in get_step(src,direction)) + if(roof.linked_master) + roof.linked_master.connect(loc) + return + var/datum/roof_master_node/roof_master_node = new(loc) //no master and no lattice to connect to, create new master + roof_master_node.connect(loc) + +/obj/structure/roof/Destroy(force, ...) + if(linked_master) + linked_master.remove_roof(src) + for(var/icon in GLOB.player_list) + var/mob/mob = icon + mob.client.images -= normal_image + return ..() + +/obj/structure/roof/proc/add_default_image(subsystem, mob/mob) + SIGNAL_HANDLER + mob.client.images += normal_image + +/obj/structure/roof/proc/link_master(datum/roof_master_node/master) //performs bfs and connects to master + if(linked_master != null) + return + master.connected_roof += src + linked_master = master + for(var/direction in CARDINAL_ALL_DIRS) + for(var/obj/structure/roof/roof in get_step(src,direction)) + roof.link_master(master) + + +/obj/effect/roof_node //used for observing if mob is near the roof + name = "roof_node" + anchored = TRUE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + invisibility = 101 + unacidable = TRUE + var/datum/roof_master_node/linked_master + +/obj/effect/roof_node/Crossed(atom/movable/mover, target_dir) + if(!linked_master) + return + if(isliving(mover)) + var/mob/living/mob = mover + linked_master.add_under_roof(mob) + +/obj/effect/roof_node/Destroy(force, ...) + if(linked_master) + if(linked_master.connected_nodes) + linked_master.connected_nodes -= src + return ..() + +/obj/effect/roof_node/proc/link_master(datum/roof_master_node/master) //performs bfs and connects to master + if(linked_master) + return + master.connected_nodes += src + linked_master = master + for(var/direction in CARDINAL_ALL_DIRS) + for(var/obj/effect/roof_node/node in get_step(src,direction)) + node.link_master(master) + + +/datum/roof_master_node //maintains one block of roof + var/list/connected_nodes = list() + var/list/connected_roof = list() + var/list/mobs_under = list() + var/location + +/datum/roof_master_node/Destroy(force, ...) + if(connected_nodes) + for(var/obj/effect/roof_node/roof_node in connected_nodes) + qdel(roof_node) + if(connected_nodes) + for(var/obj/structure/roof/roof in connected_roof) + qdel(roof) + return ..() + +/datum/roof_master_node/proc/add_under_roof(mob/living/living) //mob crossed connected node + if(living in mobs_under) + return + mobs_under += living + RegisterSignal(living, COMSIG_PARENT_QDELETING, PROC_REF(remove_under_roof)) + RegisterSignal(living, COMSIG_MOB_LOGGED_IN, PROC_REF(add_client)) + RegisterSignal(living, COMSIG_MOVABLE_MOVED, PROC_REF(check_under_roof)) + + if(living.client) + add_client(living) + +/datum/roof_master_node/proc/add_client(mob/living/mob) + SIGNAL_HANDLER + for(var/obj/structure/roof/roof in connected_roof) + mob.client.images -= roof.normal_image + mob.client.images += roof.under_image + +/datum/roof_master_node/proc/remove_under_roof(mob/living/living) //mob is no longer under roof + SIGNAL_HANDLER + if(living.client) + for(var/obj/structure/roof/roof in connected_roof) + living.client.images -= roof.under_image + roof.add_default_image(SSdcs, living) + mobs_under -= living + UnregisterSignal(living, list( + COMSIG_PARENT_QDELETING, + COMSIG_MOB_LOGGED_IN, + COMSIG_MOVABLE_MOVED, + )) + +/datum/roof_master_node/proc/check_under_roof(mob/living/living) //check if the mob is under connected roof + SIGNAL_HANDLER + for(var/obj/effect/roof_node/roof in connected_nodes) + if(living.loc == roof.loc) + return + remove_under_roof(living) + +/datum/roof_master_node/proc/connect(location) + for(var/obj/effect/roof_node/node in location) + node.link_master(src) + for(var/obj/structure/roof/roof in location) + roof.link_master(src) + +/datum/roof_master_node/proc/remove_roof(obj/structure/roof/roof) //roof tile got removed + connected_roof -= roof + if(!length(connected_roof)) + qdel(src) diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm index 986ae99739aa..f71882374518 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm @@ -36,12 +36,12 @@ move_delay += 4 //harder to move a wheelchair with a single hand working_hands-- else if((left_hand.status & LIMB_BROKEN) && !(left_hand.status & LIMB_SPLINTED)) - move_delay++ + move_delay ++ if(!right_hand || (right_hand.status & LIMB_DESTROYED)) move_delay += 4 working_hands-- else if((right_hand.status & LIMB_BROKEN) && !(right_hand.status & LIMB_SPLINTED)) - move_delay += 2 + move_delay++ if(!working_hands) return // No hands to drive your chair? Tough luck! if(driver.pulling && driver.pulling.drag_delay && driver.get_pull_miltiplier()) //Dragging stuff can slow you down a bit. diff --git a/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm b/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm index c3f0b97e509a..68b899f78f15 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm @@ -245,6 +245,7 @@ do_buckle(mob, user) ADD_TRAIT(mob, TRAIT_NESTED, TRAIT_SOURCE_BUCKLE) + ADD_TRAIT(mob, TRAIT_NO_STRAY, TRAIT_SOURCE_BUCKLE) SEND_SIGNAL(mob, COMSIG_MOB_NESTED, user) if(!human) @@ -275,6 +276,7 @@ buckled_mob.pixel_y = 0 buckled_mob.old_y = 0 REMOVE_TRAIT(buckled_mob, TRAIT_NESTED, TRAIT_SOURCE_BUCKLE) + REMOVE_TRAIT(buckled_mob, TRAIT_NO_STRAY, TRAIT_SOURCE_BUCKLE) var/mob/living/carbon/human/buckled_human = buckled_mob var/mob/dead/observer/G = ghost_of_buckled_mob diff --git a/code/game/objects/structures/vulture_spotter.dm b/code/game/objects/structures/vulture_spotter.dm index dc341edf0446..dcbfd88c9c08 100644 --- a/code/game/objects/structures/vulture_spotter.dm +++ b/code/game/objects/structures/vulture_spotter.dm @@ -313,6 +313,7 @@ tripod = WEAKREF(spotting_tripod) /datum/action/vulture_tripod_unscope/action_activate() + . = ..() if(!tripod) return diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index c5a675b531d2..8974eb36187f 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -532,7 +532,7 @@ GLOBAL_DATUM_INIT(supply_controller, /datum/controller/supply, new()) for(var/datum/supply_packs_asrs/crate in cratelist) var/weight = (floor(10000/crate.cost)) weighted_crate_list[crate] = weight - return pickweight(weighted_crate_list) + return pick_weight(weighted_crate_list) //To stop things being sent to centcomm which should not be sent to centcomm. Recursively checks for these types. /datum/controller/supply/proc/forbidden_atoms_check(atom/A) @@ -1115,7 +1115,7 @@ GLOBAL_DATUM_INIT(supply_controller, /datum/controller/supply, new()) else if (href_list["rreq"]) var/ordernum = text2num(href_list["rreq"]) temp = "Invalid Request.
" - for(var/i=1, length(i<=GLOB.supply_controller.requestlist), i++) + for(var/i=1, i<=length(GLOB.supply_controller.requestlist), i++) var/datum/supply_order/SO = GLOB.supply_controller.requestlist[i] if(SO.ordernum == ordernum) GLOB.supply_controller.requestlist.Cut(i,i+1) diff --git a/code/game/turfs/transit.dm b/code/game/turfs/transit.dm index 00175ac5e365..5b4645805d3b 100644 --- a/code/game/turfs/transit.dm +++ b/code/game/turfs/transit.dm @@ -138,6 +138,12 @@ clear_active_explosives() ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) ADD_TRAIT(src, TRAIT_UNDENSE, TRAIT_SOURCE_DROPSHIP_INTERACTION) + ADD_TRAIT(src, TRAIT_NO_STRAY, TRAIT_SOURCE_DROPSHIP_INTERACTION) + RegisterSignal(src, COMSIG_MOVABLE_FORCEMOVE_PRE_CROSSED, PROC_REF(cancel_cross)) + RegisterSignal(src, list( + COMSIG_LIVING_FLAMER_FLAMED, + COMSIG_LIVING_PREIGNITION + ), PROC_REF(cancel_fire)) var/image/cables = image('icons/obj/structures/droppod_32x64.dmi', src, "chute_cables_static") overlays += cables var/image/chute = image('icons/obj/structures/droppod_64x64.dmi', src, "chute_static") @@ -163,8 +169,18 @@ return REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) REMOVE_TRAIT(src, TRAIT_UNDENSE, TRAIT_SOURCE_DROPSHIP_INTERACTION) + REMOVE_TRAIT(src, TRAIT_NO_STRAY, TRAIT_SOURCE_DROPSHIP_INTERACTION) + UnregisterSignal(src, list( + COMSIG_MOVABLE_FORCEMOVE_PRE_CROSSED, + COMSIG_LIVING_FLAMER_FLAMED, + COMSIG_LIVING_PREIGNITION + )) overlays -= cables overlays -= chute + for(var/atom/movable/atom in loc) + if(atom == src) + continue + atom.Cross(src) /atom/movable/proc/clear_active_explosives() for(var/obj/item/explosive/explosive in contents) @@ -232,6 +248,13 @@ death(last_damage_data) status_flags |= PERMANENTLY_DEAD +/atom/movable/proc/cancel_cross() + SIGNAL_HANDLER + return COMPONENT_IGNORE_CROSS + +/atom/movable/proc/cancel_fire() + SIGNAL_HANDLER + return COMPONENT_NO_BURN /turf/open/space/transit/dropship/alamo shuttle_tag = DROPSHIP_ALAMO diff --git a/code/game/verbs/who.dm b/code/game/verbs/who.dm deleted file mode 100644 index 3a9274dbec62..000000000000 --- a/code/game/verbs/who.dm +++ /dev/null @@ -1,209 +0,0 @@ -/client/verb/who()//likely don't touch any... this is easy can die. (:troll_fale:) - set name = "Who" - set category = "OOC" - - var/list/counted_humanoids = list( - "Observers" = 0, - "Admin observers" = 0, - "Humans" = 0, - "Infected humans" = 0, - FACTION_MARINE = 0, - "USCM Marines" = 0, - "Lobby" = 0, - - FACTION_YAUTJA = 0, - "Infected preds" = 0, - - FACTION_PMC = 0, - FACTION_CLF = 0, - FACTION_UPP = 0, - FACTION_TWE = 0, - FACTION_FREELANCER = 0, - FACTION_SURVIVOR = 0, - FACTION_WY_DEATHSQUAD = 0, - FACTION_COLONIST = 0, - FACTION_MERCENARY = 0, - FACTION_DUTCH = 0, - FACTION_HEFA = 0, - FACTION_GLADIATOR = 0, - FACTION_PIRATE = 0, - FACTION_PIZZA = 0, - FACTION_SOUTO = 0, - - FACTION_NEUTRAL = 0, - - FACTION_ZOMBIE = 0 - ) - - var/list/counted_xenos = list() - - var/players = length(GLOB.clients) - - var/dat = "Current Players:
" - var/list/Lines = list() - if(admin_holder && ((R_ADMIN & admin_holder.rights) || (R_MOD & admin_holder.rights))) - for(var/client/C in GLOB.clients) - if(!CLIENT_HAS_RIGHTS(src, R_STEALTH) && (CLIENT_IS_STEALTHED(C))) - continue - var/entry = "[C.key]" - if(C.mob) //Juuuust in case - if(istype(C.mob, /mob/new_player)) - entry += " - In Lobby" - counted_humanoids["Lobby"]++ - else - entry += " - Playing as [C.mob.real_name]" - - if(isobserver(C.mob)) - counted_humanoids["Observers"]++ - if(C.admin_holder?.rights & R_MOD) - counted_humanoids["Admin observers"]++ - counted_humanoids["Observers"]-- - var/mob/dead/observer/O = C.mob - if(O.started_as_observer) - entry += " - Observing" - else - entry += " - DEAD" - else - switch(C.mob.stat) - if(UNCONSCIOUS) - entry += " - Unconscious" - if(DEAD) - entry += " - DEAD" - - if(C.mob && C.mob.stat != DEAD) - if(ishuman(C.mob)) - if(C.mob.faction == FACTION_ZOMBIE) - counted_humanoids[FACTION_ZOMBIE]++ - entry += " - Zombie" - else if(C.mob.faction == FACTION_YAUTJA) - counted_humanoids[FACTION_YAUTJA]++ - entry += " - Predator" - if(C.mob.status_flags & XENO_HOST) - counted_humanoids["Infected preds"]++ - else - counted_humanoids["Humans"]++ - if(C.mob.status_flags & XENO_HOST) - counted_humanoids["Infected humans"]++ - if(C.mob.faction == FACTION_MARINE) - counted_humanoids[FACTION_MARINE]++ - if(C.mob.job in (GLOB.ROLES_MARINES)) - counted_humanoids["USCM Marines"]++ - else - counted_humanoids[C.mob.faction]++ - else if(isxeno(C.mob)) - var/mob/living/carbon/xenomorph/X = C.mob - counted_xenos[X.hivenumber]++ - if(X.faction == FACTION_PREDALIEN) - counted_xenos[FACTION_PREDALIEN]++ - entry += " - Xenomorph" - entry += " (?)" - Lines += entry - - for(var/line in sortList(Lines)) - dat += "[line]
" - dat += "Total Players: [players]" - dat += "
In Lobby: [counted_humanoids["Lobby"]]" - dat += "
Observers: [counted_humanoids["Observers"]] players and [counted_humanoids["Admin observers"]] staff members" - dat += "
Humans: [counted_humanoids["Humans"]] (Infected: [counted_humanoids["Infected humans"]])" - if(counted_humanoids[FACTION_MARINE]) - dat += "
USCM personnel: [counted_humanoids[FACTION_MARINE]] (Marines: [counted_humanoids["USCM Marines"]])" - if(counted_humanoids[FACTION_YAUTJA]) - dat += "
Predators: [counted_humanoids[FACTION_YAUTJA]] [counted_humanoids["Infected preds"] ? "(Infected: [counted_humanoids["Infected preds"]])" : ""]" - if(counted_humanoids[FACTION_ZOMBIE]) - dat += "
Zombies: [counted_humanoids[FACTION_ZOMBIE]]" - - var/show_fact = TRUE - for(var/i in 10 to LAZYLEN(counted_humanoids) - 2) - if(counted_humanoids[counted_humanoids[i]]) - if(show_fact) - dat += "

Other factions:" - show_fact = FALSE - dat += "
[counted_humanoids[i]]: [counted_humanoids[counted_humanoids[i]]]" - if(counted_humanoids[FACTION_NEUTRAL]) - dat += "
[FACTION_NEUTRAL] Humans: [counted_humanoids[FACTION_NEUTRAL]]" - - show_fact = TRUE - var/datum/hive_status/hive - for(var/hivenumber in counted_xenos) - // Print predalien counts last - if(hivenumber == FACTION_PREDALIEN) - continue - if(show_fact) - dat += "

Xenomorphs:" - show_fact = FALSE - hive = GLOB.hive_datum[hivenumber] - if(hive) - dat += "
[hive.name]: [counted_xenos[hivenumber]] (Queen: [hive.living_xeno_queen ? "Alive" : "Dead"])" - else - dat += "
Error: no hive datum detected for [hivenumber]." - hive = null - if(counted_xenos[FACTION_PREDALIEN]) - dat += "
Predaliens: [counted_xenos[FACTION_PREDALIEN]]" - - else - for(var/client/C in GLOB.clients) - if((C.admin_holder && C.admin_holder.fakekey) || (CLIENT_IS_STEALTHED(C))) - continue - - Lines += C.key - for(var/line in sortList(Lines)) - dat += "[line]
" - dat += "Total Players: [players]
" - - dat += "" - show_browser(usr, dat, "Who", "who", "size=600x800") - - -/client/verb/staffwho() - set name = "Staffwho" - set category = "Admin" - - var/dat = "" - var/list/mappings - if(CONFIG_GET(flag/show_manager)) - LAZYSET(mappings, "Management", R_PERMISSIONS) - if(CONFIG_GET(flag/show_devs)) - LAZYSET(mappings, "Maintainers", R_PROFILER) - LAZYSET(mappings, "Admins", R_ADMIN) - if(CONFIG_GET(flag/show_mods)) - LAZYSET(mappings, "Moderators", R_MOD) - if(CONFIG_GET(flag/show_mentors)) - LAZYSET(mappings, "Mentors", R_MENTOR) - - var/list/listings - for(var/category in mappings) - LAZYSET(listings, category, list()) - - for(var/client/C in GLOB.admins) - if(CLIENT_IS_STEALTHED(C) && !CLIENT_HAS_RIGHTS(src, R_STEALTH)) - continue - if(C.admin_holder?.fakekey && !CLIENT_IS_STAFF(src)) - continue - for(var/category in mappings) - if(CLIENT_HAS_RIGHTS(C, mappings[category])) - LAZYADD(listings[category], C) - break - - for(var/category in listings) - dat += "
Current [category] ([length(listings[category])]):
\n" - for(var/client/entry in listings[category]) - dat += "\t[entry.key] is \a [entry.admin_holder.rank]" - if(LAZYLEN(entry.admin_holder.extra_titles)) - for(var/srank in entry.admin_holder.extra_titles) - dat += " & [srank]" - if(CLIENT_IS_STAFF(src)) - if(CLIENT_IS_STEALTHED(entry)) - dat += " (STEALTHED)" - else if(entry.admin_holder?.fakekey) - dat += " (HIDDEN)" - if(istype(entry.mob, /mob/dead/observer)) - dat += " - Observing" - else if(istype(entry.mob, /mob/new_player)) - dat += " - Lobby" - else - dat += " - Playing" - if(entry.is_afk()) - dat += " (AFK)" - dat += "
" - dat += "" - show_browser(usr, dat, "Staffwho", "staffwho", "size=600x800") diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm index 0b27cf268a12..e826b0b64767 100644 --- a/code/modules/asset_cache/asset_list_items.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -367,6 +367,10 @@ retrieved_icon.Scale(128, 128) Insert("intents", retrieved_icon) + retrieved_icon = icon('icons/mob/xenos/predalien.dmi', "Normal Predalien Walking") + retrieved_icon.Scale(128, 128) + Insert("predalien", retrieved_icon) + return ..() diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index 7406e6baa754..6e086e651a10 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -40,6 +40,7 @@ return TRUE /datum/action/item_action/view_publications/action_activate() + . = ..() var/obj/item/clothing/glasses/hud/health/hud = holder_item hud.tgui_interact(owner) diff --git a/code/modules/clothing/glasses/night.dm b/code/modules/clothing/glasses/night.dm index b2b6f8406dcc..984a906eabed 100644 --- a/code/modules/clothing/glasses/night.dm +++ b/code/modules/clothing/glasses/night.dm @@ -184,6 +184,7 @@ button.overlays += image('icons/mob/hud/actions.dmi', button, action_icon_state) /datum/action/item_action/m56_goggles/far_sight/action_activate() + . = ..() if(target) var/obj/item/clothing/glasses/night/m56_goggles/G = target G.set_far_sight(owner, !G.far_sight) diff --git a/code/modules/clothing/gloves/boom_glove.dm b/code/modules/clothing/gloves/boom_glove.dm index 8cc3e8d910f6..ddddc5ecef5e 100644 --- a/code/modules/clothing/gloves/boom_glove.dm +++ b/code/modules/clothing/gloves/boom_glove.dm @@ -12,7 +12,7 @@ var/cooldown = 50 var/last_use = 0 - actions_types = list(/datum/action/item_action) + actions_types = list(/datum/action/item_action/toggle/use) /obj/item/clothing/gloves/marine/boom_glove/item_action_slot_check(mob/user, slot) if(!ishuman(user)) return FALSE diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index e52032d0cba6..463a4b16f7ec 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -354,7 +354,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( armor_melee = CLOTHING_ARMOR_MEDIUM armor_bullet = CLOTHING_ARMOR_MEDIUM armor_laser = CLOTHING_ARMOR_MEDIUMLOW - armor_energy = CLOTHING_ARMOR_NONE + armor_energy = CLOTHING_ARMOR_LOW armor_bomb = CLOTHING_ARMOR_LOW armor_bio = CLOTHING_ARMOR_MEDIUM armor_rad = CLOTHING_ARMOR_LOW diff --git a/code/modules/clothing/spacesuits/spacesuits.dm b/code/modules/clothing/spacesuits/spacesuits.dm index 9c28ca42bc41..a8b056d0bb9d 100644 --- a/code/modules/clothing/spacesuits/spacesuits.dm +++ b/code/modules/clothing/spacesuits/spacesuits.dm @@ -32,7 +32,7 @@ gas_transfer_coefficient = 0.01 permeability_coefficient = 0.02 flags_armor_protection = BODY_FLAG_CHEST|BODY_FLAG_GROIN|BODY_FLAG_LEGS|BODY_FLAG_FEET|BODY_FLAG_ARMS|BODY_FLAG_HANDS - allowed = list(/obj/item/device/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit) + allowed = list(/obj/item/device/flashlight,/obj/item/tank/emergency_oxygen) slowdown = 3 armor_melee = CLOTHING_ARMOR_NONE armor_bullet = CLOTHING_ARMOR_NONE diff --git a/code/modules/clothing/suits/marine_armor/_marine_armor.dm b/code/modules/clothing/suits/marine_armor/_marine_armor.dm index e6cf78611a7f..8a8d5934b506 100644 --- a/code/modules/clothing/suits/marine_armor/_marine_armor.dm +++ b/code/modules/clothing/suits/marine_armor/_marine_armor.dm @@ -50,7 +50,7 @@ armor_melee = CLOTHING_ARMOR_MEDIUM armor_bullet = CLOTHING_ARMOR_MEDIUM armor_laser = CLOTHING_ARMOR_MEDIUMLOW - armor_energy = CLOTHING_ARMOR_NONE + armor_energy = CLOTHING_ARMOR_LOW armor_bomb = CLOTHING_ARMOR_MEDIUMLOW armor_bio = CLOTHING_ARMOR_MEDIUM armor_rad = CLOTHING_ARMOR_MEDIUMLOW @@ -361,6 +361,7 @@ armor_bomb = CLOTHING_ARMOR_MEDIUM armor_bio = CLOTHING_ARMOR_MEDIUMHIGH armor_internaldamage = CLOTHING_ARMOR_MEDIUMHIGH + armor_energy = CLOTHING_ARMOR_MEDIUM specialty = "B12 pattern marine" light_range = 5 @@ -547,6 +548,7 @@ armor_bomb = CLOTHING_ARMOR_HIGHPLUS armor_bio = CLOTHING_ARMOR_MEDIUMHIGH armor_rad = CLOTHING_ARMOR_MEDIUM + armor_energy = CLOTHING_ARMOR_MEDIUMLOW armor_internaldamage = CLOTHING_ARMOR_MEDIUMHIGH storage_slots = 2 slowdown = SLOWDOWN_ARMOR_LOWHEAVY @@ -591,6 +593,7 @@ armor_bio = CLOTHING_ARMOR_MEDIUMLOW armor_rad = CLOTHING_ARMOR_MEDIUMHIGH armor_internaldamage = CLOTHING_ARMOR_MEDIUMHIGH + armor_energy = CLOTHING_ARMOR_MEDIUM storage_slots = 2 flags_inventory = BLOCKSHARPOBJ|BLOCK_KNOCKDOWN flags_armor_protection = BODY_FLAG_CHEST|BODY_FLAG_GROIN|BODY_FLAG_ARMS|BODY_FLAG_LEGS|BODY_FLAG_FEET @@ -632,6 +635,7 @@ armor_bullet = CLOTHING_ARMOR_MEDIUMHIGH armor_bomb = CLOTHING_ARMOR_VERYHIGH armor_bio = CLOTHING_ARMOR_MEDIUMLOW + armor_energy = CLOTHING_ARMOR_MEDIUM armor_internaldamage = CLOTHING_ARMOR_MEDIUMHIGH flags_inventory = BLOCKSHARPOBJ|BLOCK_KNOCKDOWN flags_item = MOB_LOCK_ON_EQUIP|NO_CRYO_STORE diff --git a/code/modules/clothing/suits/marine_armor/ghillie.dm b/code/modules/clothing/suits/marine_armor/ghillie.dm index 1f1b71227655..44729ac16b2f 100644 --- a/code/modules/clothing/suits/marine_armor/ghillie.dm +++ b/code/modules/clothing/suits/marine_armor/ghillie.dm @@ -150,6 +150,7 @@ return TRUE /datum/action/item_action/specialist/prepare_position/action_activate() + . = ..() var/obj/item/clothing/suit/storage/marine/ghillie/GS = holder_item GS.camouflage() diff --git a/code/modules/clothing/suits/marine_armor/intel.dm b/code/modules/clothing/suits/marine_armor/intel.dm index b3f0f93e004d..12aa824648d1 100644 --- a/code/modules/clothing/suits/marine_armor/intel.dm +++ b/code/modules/clothing/suits/marine_armor/intel.dm @@ -18,6 +18,7 @@ update_icon() /datum/action/item_action/intel/action_activate() + . = ..() if(!ishuman(owner)) return diff --git a/code/modules/clothing/suits/marine_armor/spec_fire.dm b/code/modules/clothing/suits/marine_armor/spec_fire.dm index 52343a204f68..c3f2863b3545 100644 --- a/code/modules/clothing/suits/marine_armor/spec_fire.dm +++ b/code/modules/clothing/suits/marine_armor/spec_fire.dm @@ -145,6 +145,7 @@ return TRUE /datum/action/item_action/specialist/fire_shield/action_activate() + . = ..() var/obj/item/clothing/suit/storage/marine/M35/armor = holder_item if (!istype(armor)) return diff --git a/code/modules/clothing/under/marine_uniform.dm b/code/modules/clothing/under/marine_uniform.dm index c7353840d439..74cb5ea552ee 100644 --- a/code/modules/clothing/under/marine_uniform.dm +++ b/code/modules/clothing/under/marine_uniform.dm @@ -1210,6 +1210,7 @@ button.overlays += button_overlay /datum/action/item_action/specialist/toggle_cbrn_hood/action_activate() + . = ..() var/obj/item/clothing/under/marine/cbrn/armor = holder_item if(!istype(armor)) return diff --git a/code/modules/cm_aliens/structures/fruit.dm b/code/modules/cm_aliens/structures/fruit.dm index f555cac64b8c..b2a0fd27d65b 100644 --- a/code/modules/cm_aliens/structures/fruit.dm +++ b/code/modules/cm_aliens/structures/fruit.dm @@ -185,7 +185,7 @@ bound_xeno.current_fruits.Remove(src) var/number_of_fruit = length(bound_xeno.current_fruits) - var/datum/action/xeno_action/onclick/plant_resin_fruit/plant_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/plant_resin_fruit) + var/datum/action/xeno_action/onclick/plant_resin_fruit/plant_action = get_action(bound_xeno, /datum/action/xeno_action/onclick/plant_resin_fruit) plant_action.button.set_maptext(SMALL_FONTS_COLOR(7, number_of_fruit, "#e69d00"), 19, 2) plant_action.update_button_icon() @@ -377,7 +377,7 @@ /obj/item/reagent_container/food/snacks/resin_fruit/proc/delete_fruit() if(bound_xeno) bound_xeno.current_fruits.Remove(src) - var/datum/action/xeno_action/onclick/plant_resin_fruit/prf = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/plant_resin_fruit) + var/datum/action/xeno_action/onclick/plant_resin_fruit/prf = get_action(bound_xeno, /datum/action/xeno_action/onclick/plant_resin_fruit) var/number_of_fruit = length(bound_xeno.current_fruits) prf.button.set_maptext(SMALL_FONTS_COLOR(7, number_of_fruit, "#e69d00"), 19, 2) prf.update_button_icon() diff --git a/code/modules/cm_aliens/structures/special/egg_morpher.dm b/code/modules/cm_aliens/structures/special/egg_morpher.dm index c4fb5c0a900c..ac501bb5c970 100644 --- a/code/modules/cm_aliens/structures/special/egg_morpher.dm +++ b/code/modules/cm_aliens/structures/special/egg_morpher.dm @@ -14,14 +14,14 @@ var/huggers_to_grow_max = 12 var/huggers_reserved = 0 var/mob/captured_mob - var/datum/shape/rectangle/range_bounds + var/datum/shape/range_bounds appearance_flags = KEEP_TOGETHER layer = FACEHUGGER_LAYER /obj/effect/alien/resin/special/eggmorph/Initialize(mapload, hive_ref) . = ..() - range_bounds = RECT(x, y, EGGMORPG_RANGE, EGGMORPG_RANGE) + range_bounds = SQUARE(x, y, EGGMORPG_RANGE) /obj/effect/alien/resin/special/eggmorph/Destroy() if (stored_huggers && linked_hive) @@ -158,7 +158,7 @@ /obj/effect/alien/resin/special/eggmorph/proc/check_facehugger_target() if(!range_bounds) - range_bounds = RECT(x, y, EGGMORPG_RANGE, EGGMORPG_RANGE) + range_bounds = SQUARE(x, y, EGGMORPG_RANGE) var/list/targets = SSquadtree.players_in_range(range_bounds, z, QTREE_SCAN_MOBS | QTREE_EXCLUDE_OBSERVER) if(isnull(targets) || !length(targets)) diff --git a/code/modules/cm_marines/equipment/guncases.dm b/code/modules/cm_marines/equipment/guncases.dm index 22999e97fda2..cbbb791f8f0b 100644 --- a/code/modules/cm_marines/equipment/guncases.dm +++ b/code/modules/cm_marines/equipment/guncases.dm @@ -67,7 +67,6 @@ new /obj/item/ammo_magazine/rifle/lmg(src) new /obj/item/ammo_magazine/rifle/lmg/holo_target(src) new /obj/item/attachable/flashlight - new /obj/item/attachable/bipod //------------ /obj/item/storage/box/guncase/m41aMK1 diff --git a/code/modules/cm_marines/equipment/kit_boxes.dm b/code/modules/cm_marines/equipment/kit_boxes.dm index 5ba670d89bc1..2a2c2d450523 100644 --- a/code/modules/cm_marines/equipment/kit_boxes.dm +++ b/code/modules/cm_marines/equipment/kit_boxes.dm @@ -248,12 +248,9 @@ return TRUE /obj/item/spec_kit/proc/select_and_spawn(mob/living/carbon/human/user) - var/selection = tgui_input_list(user, "Pick your specialist equipment type.", "Specialist Kit Selection", GLOB.available_specialist_kit_boxes) + var/selection = tgui_input_list(user, "Pick your specialist equipment type.", "Specialist Kit Selection", GLOB.available_specialist_kit_boxes, 10 SECONDS) if(!selection || QDELETED(src)) return FALSE - if(!skillcheckexplicit(user, SKILL_SPEC_WEAPONS, SKILL_SPEC_TRAINED) && !skillcheckexplicit(user, SKILL_SPEC_WEAPONS, SKILL_SPEC_ALL)) - to_chat(user, SPAN_WARNING("You already unwrapped your [name], give this one to someone else!")) - return if(!GLOB.available_specialist_kit_boxes[selection] || GLOB.available_specialist_kit_boxes[selection] <= 0) to_chat(user, SPAN_WARNING("No more kits of this type may be chosen!")) return FALSE @@ -299,6 +296,7 @@ user.put_in_hands(spec_box) card.set_assignment((user.assigned_squad && squad_assignment_update ? (user.assigned_squad.name + " ") : "") + card.assignment + " ([specialist_assignment])") GLOB.data_core.manifest_modify(user.real_name, WEAKREF(user), card.assignment) + GLOB.available_specialist_kit_boxes[selection]-- return TRUE return FALSE @@ -425,7 +423,6 @@ new /obj/item/weapon/gun/rifle/lmg(src) new /obj/item/ammo_magazine/rifle/lmg(src) new /obj/item/ammo_magazine/rifle/lmg/holo_target(src) - new /obj/item/attachable/bipod(src) new /obj/item/stack/folding_barricade/three(src) new /obj/item/clothing/glasses/welding(src) new /obj/item/tool/weldingtool(src) diff --git a/code/modules/cm_marines/equipment/mortar/mortar_shells.dm b/code/modules/cm_marines/equipment/mortar/mortar_shells.dm index dae0910cc9b4..1cb93c6a809e 100644 --- a/code/modules/cm_marines/equipment/mortar/mortar_shells.dm +++ b/code/modules/cm_marines/equipment/mortar/mortar_shells.dm @@ -167,23 +167,43 @@ return ..() /obj/item/mortar_shell/flamer_fire_act(dam, datum/cause_data/flame_cause_data) + addtimer(VARSET_CALLBACK(src, burning, FALSE), 5 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_DELETE_ME) + if(burning) return burning = TRUE cause_data = create_cause_data("Burning Mortar Shell", flame_cause_data.resolve_mob(), src) - handle_fire() + handle_fire(cause_data) -/obj/item/mortar_shell/proc/handle_fire() - visible_message(SPAN_WARNING("[src] catches on fire and starts cooking off! It's gonna blow!")) - anchored = TRUE // don't want other explosions launching it elsewhere +/obj/item/mortar_shell/proc/can_explode() + return TRUE - var/datum/effect_system/spark_spread/sparks = new() - sparks.set_up(n = 10, loca = loc) - sparks.start() - new /obj/effect/warning/explosive(loc, 5 SECONDS) +/obj/item/mortar_shell/custom/can_explode() + for(var/obj/item/reagent_container/glass/container in warhead?.containers) + for(var/datum/reagent/reagent in container?.reagents?.reagent_list) + if(reagent.explosive) + return TRUE - addtimer(CALLBACK(src, PROC_REF(detonate), loc), 5 SECONDS) - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (src)), 5.5 SECONDS) + return FALSE + +/obj/item/mortar_shell/flare/can_explode() + return FALSE + +/obj/item/mortar_shell/proc/handle_fire(cause_data) + if(can_explode()) + visible_message(SPAN_WARNING("[src] catches on fire and starts cooking off! It's gonna blow!")) + anchored = TRUE // don't want other explosions launching it elsewhere + var/datum/effect_system/spark_spread/sparks = new() + sparks.set_up(n = 10, loca = loc) + sparks.start() + new /obj/effect/warning/explosive(loc, 5 SECONDS) + + addtimer(CALLBACK(src, PROC_REF(explode), cause_data), 5 SECONDS) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (src)), 5.5 SECONDS) + + +/obj/item/mortar_shell/proc/explode(flame_cause_data) + cell_explosion(src, 100, 25, EXPLOSION_FALLOFF_SHAPE_LINEAR, null, flame_cause_data) /obj/structure/closet/crate/secure/mortar_ammo name = "\improper M402 mortar ammo crate" diff --git a/code/modules/cm_preds/yaut_actions.dm b/code/modules/cm_preds/yaut_actions.dm index f55f58e0a557..0d260363ab15 100644 --- a/code/modules/cm_preds/yaut_actions.dm +++ b/code/modules/cm_preds/yaut_actions.dm @@ -49,6 +49,7 @@ return TRUE /datum/action/predator_action/action_activate() + . = ..() if(!can_use_action()) return FALSE @@ -248,6 +249,7 @@ action_icon_state = "looc_toggle" /datum/action/yautja_emote_panel/action_activate() + . = ..() var/mob/living/carbon/human/human_owner = owner var/datum/species/yautja/yautja_species = human_owner.species yautja_species.open_emote_panel() diff --git a/code/modules/cm_preds/yaut_bracers.dm b/code/modules/cm_preds/yaut_bracers.dm index 5577691d64c2..77efbb7ad4ef 100644 --- a/code/modules/cm_preds/yaut_bracers.dm +++ b/code/modules/cm_preds/yaut_bracers.dm @@ -556,7 +556,7 @@ set src in usr . = cloaker_internal(usr, FALSE) -/obj/item/clothing/gloves/yautja/hunter/proc/cloaker_internal(mob/caller, forced = FALSE) +/obj/item/clothing/gloves/yautja/hunter/proc/cloaker_internal(mob/caller, forced = FALSE, silent = FALSE, instant = FALSE) . = check_random_function(caller, forced) if(.) return @@ -600,15 +600,21 @@ M.see_invisible = SEE_INVISIBLE_LEVEL_ONE log_game("[key_name_admin(usr)] has enabled their cloaking device.") - M.visible_message(SPAN_WARNING("[M] vanishes into thin air!"), SPAN_NOTICE("You are now invisible to normal detection.")) - playsound(M.loc,'sound/effects/pred_cloakon.ogg', 15, 1) - animate(M, alpha = new_alpha, time = 1.5 SECONDS, easing = SINE_EASING|EASE_OUT) + if(!silent) + M.visible_message(SPAN_WARNING("[M] vanishes into thin air!"), SPAN_NOTICE("You are now invisible to normal detection.")) + playsound(M.loc,'sound/effects/pred_cloakon.ogg', 15, 1) + + if(!instant) + animate(M, alpha = new_alpha, time = 1.5 SECONDS, easing = SINE_EASING|EASE_OUT) + else + M.alpha = new_alpha var/datum/mob_hud/security/advanced/SA = GLOB.huds[MOB_HUD_SECURITY_ADVANCED] SA.remove_from_hud(M) var/datum/mob_hud/xeno_infection/XI = GLOB.huds[MOB_HUD_XENO_INFECTION] XI.remove_from_hud(M) - anim(M.loc,M,'icons/mob/mob.dmi',,"cloak",,M.dir) + if(!instant) + anim(M.loc,M,'icons/mob/mob.dmi',,"cloak",,M.dir) var/datum/action/predator_action/bracer/cloak/cloak_action for(cloak_action as anything in M.actions) @@ -634,6 +640,8 @@ if(!user) return + SEND_SIGNAL(src, COMSIG_PRED_BRACER_DECLOAKED) + UnregisterSignal(user, COMSIG_HUMAN_EXTINGUISH) UnregisterSignal(user, COMSIG_HUMAN_PRE_BULLET_ACT) UnregisterSignal(user, COMSIG_MOB_EFFECT_CLOAK_CANCEL) diff --git a/code/modules/cm_preds/yaut_weapons.dm b/code/modules/cm_preds/yaut_weapons.dm index 2db3c2ca4b68..3bbbd11c0784 100644 --- a/code/modules/cm_preds/yaut_weapons.dm +++ b/code/modules/cm_preds/yaut_weapons.dm @@ -486,7 +486,7 @@ throw_range = 6 hitsound = 'sound/weapons/slash.ogg' attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - actions_types = list(/datum/action/item_action) + actions_types = list(/datum/action/item_action/toggle/use) unacidable = TRUE /obj/item/weapon/yautja/knife/attack(mob/living/target, mob/living/carbon/human/user) @@ -584,7 +584,6 @@ SPAN_DANGER("[victim] is missing \his head. Pelts like this just aren't the same... You peel the skin around the stump loose with your [tool.name].")) else victim.apply_damage(10, BRUTE, v_head, sharp = TRUE) - v_head.disfigured = TRUE create_leftovers(victim, has_meat = FALSE, skin_amount = 1) if(victim.h_style == "Bald") //you can't scalp someone with no hair. user.visible_message(SPAN_DANGER("[user] makes some rough cuts on [victim]'s head and face with \a [tool]."), diff --git a/code/modules/cm_tech/hologram.dm b/code/modules/cm_tech/hologram.dm index 1fcba71a4560..1d85df9e49ad 100644 --- a/code/modules/cm_tech/hologram.dm +++ b/code/modules/cm_tech/hologram.dm @@ -102,6 +102,7 @@ GLOBAL_LIST_EMPTY_TYPED(hologram_list, /mob/hologram) var/mob/hologram/linked_hologram /datum/action/leave_hologram/action_activate() + . = ..() qdel(src) /datum/action/leave_hologram/Destroy() diff --git a/code/modules/cm_tech/implements/adv_weapon.dm b/code/modules/cm_tech/implements/adv_weapon.dm index 3cc8f1ceb4d6..f7b1008e0882 100644 --- a/code/modules/cm_tech/implements/adv_weapon.dm +++ b/code/modules/cm_tech/implements/adv_weapon.dm @@ -130,6 +130,7 @@ name = "Start Charging" /datum/action/item_action/techweb_railgun_start_charge/action_activate() + . = ..() if (target) var/obj/item/weapon/gun/rifle/techweb_railgun/TR = target TR.start_charging(owner) @@ -138,6 +139,7 @@ name = "Abort Charge" /datum/action/item_action/techweb_railgun_abort_charge/action_activate() + . = ..() if (target) var/obj/item/weapon/gun/rifle/techweb_railgun/TR = target TR.abort_charge(owner) diff --git a/code/modules/defenses/bell_tower.dm b/code/modules/defenses/bell_tower.dm index 68d58f02b481..7ce252b3f4d7 100644 --- a/code/modules/defenses/bell_tower.dm +++ b/code/modules/defenses/bell_tower.dm @@ -257,7 +257,7 @@ STOP_PROCESSING(SSobj, src) return - var/list/targets = SSquadtree.players_in_range(RECT(M.x, M.y, area_range, area_range), M.z, QTREE_SCAN_MOBS | QTREE_EXCLUDE_OBSERVER) + var/list/targets = SSquadtree.players_in_range(SQUARE(M.x, M.y, area_range), M.z, QTREE_SCAN_MOBS | QTREE_EXCLUDE_OBSERVER) if(!targets) return diff --git a/code/modules/defenses/planted_flag.dm b/code/modules/defenses/planted_flag.dm index d2b9b23e8f3b..d44f22f38b68 100644 --- a/code/modules/defenses/planted_flag.dm +++ b/code/modules/defenses/planted_flag.dm @@ -7,7 +7,7 @@ desc = "A planted flag with the iconic USCM flag plastered all over it, you feel a burst of energy by its mere sight." handheld_type = /obj/item/defenses/handheld/planted_flag disassemble_time = 10 - var/datum/shape/rectangle/range_bounds + var/datum/shape/range_bounds var/area_range = PLANTED_FLAG_RANGE var/buff_intensity = PLANTED_FLAG_BUFF health = 200 @@ -33,7 +33,7 @@ apply_area_effect() start_processing() - range_bounds = RECT(x, y, PLANTED_FLAG_RANGE, PLANTED_FLAG_RANGE) + range_bounds = SQUARE(x, y, PLANTED_FLAG_RANGE) update_icon() /obj/structure/machinery/defenses/planted_flag/Destroy() @@ -70,9 +70,9 @@ /obj/structure/machinery/defenses/planted_flag/proc/apply_area_effect() if(!range_bounds) - range_bounds = RECT(x, y, area_range, area_range) + range_bounds = SQUARE(x, y, area_range) - var/list/targets = SSquadtree.players_in_range(RECT(x, y, area_range, area_range), z, QTREE_SCAN_MOBS | QTREE_EXCLUDE_OBSERVER) + var/list/targets = SSquadtree.players_in_range(SQUARE(x, y, area_range), z, QTREE_SCAN_MOBS | QTREE_EXCLUDE_OBSERVER) if(!targets) return @@ -180,7 +180,7 @@ if(!M.x && !M.y && !M.z) return - var/list/targets = SSquadtree.players_in_range(RECT(M.x, M.y, area_range, area_range), M.z, QTREE_SCAN_MOBS | QTREE_EXCLUDE_OBSERVER) + var/list/targets = SSquadtree.players_in_range(SQUARE(M.x, M.y, area_range), M.z, QTREE_SCAN_MOBS | QTREE_EXCLUDE_OBSERVER) targets |= M for(var/mob/living/carbon/human/H in targets) diff --git a/code/modules/defenses/sentry.dm b/code/modules/defenses/sentry.dm index 695b3387d909..8ad4cd407e75 100644 --- a/code/modules/defenses/sentry.dm +++ b/code/modules/defenses/sentry.dm @@ -12,7 +12,7 @@ var/list/targets = list() // Lists of current potential targets var/list/other_targets = list() //List of special target types to shoot at, if needed. var/atom/movable/target = null - var/datum/shape/rectangle/range_bounds + var/datum/shape/range_bounds var/datum/effect_system/spark_spread/spark_system //The spark system, used for generating... sparks? var/last_fired = 0 var/fire_delay = 4 @@ -93,17 +93,17 @@ /obj/structure/machinery/defenses/sentry/proc/set_range() if(omni_directional) - range_bounds = RECT(x, y, 8, 8) + range_bounds = SQUARE(x, y, 8) return switch(dir) if(EAST) - range_bounds = RECT(x + 4, y, 7, 7) + range_bounds = SQUARE(x + 4, y, 7) if(WEST) - range_bounds = RECT(x - 4, y, 7, 7) + range_bounds = SQUARE(x - 4, y, 7) if(NORTH) - range_bounds = RECT(x, y + 4, 7, 7) + range_bounds = SQUARE(x, y + 4, 7) if(SOUTH) - range_bounds = RECT(x, y - 4, 7, 7) + range_bounds = SQUARE(x, y - 4, 7) /obj/structure/machinery/defenses/sentry/proc/unset_range() SIGNAL_HANDLER @@ -614,17 +614,17 @@ var/dbl_range = range * 2 if(omni_directional) - range_bounds = RECT(x, y, dbl_range, dbl_range) + range_bounds = SQUARE(x, y, dbl_range) return switch(dir) if(EAST) - range_bounds = RECT(x+range, y, dbl_range, dbl_range) + range_bounds = SQUARE(x+range, y, dbl_range) if(WEST) - range_bounds = RECT(x-range, y, dbl_range, dbl_range) + range_bounds = SQUARE(x-range, y, dbl_range) if(NORTH) - range_bounds = RECT(x, y+range, dbl_range, dbl_range) + range_bounds = SQUARE(x, y+range, dbl_range) if(SOUTH) - range_bounds = RECT(x, y-range, dbl_range, dbl_range) + range_bounds = SQUARE(x, y-range, dbl_range) //the turret inside the shuttle sentry deployment system /obj/structure/machinery/defenses/sentry/premade/dropship @@ -672,13 +672,13 @@ /obj/structure/machinery/defenses/sentry/dmr/set_range() switch(dir) if(EAST) - range_bounds = RECT(x + (SENTRY_SNIPER_RANGE/2), y, SENTRY_SNIPER_RANGE, SENTRY_SNIPER_RANGE) + range_bounds = SQUARE(x + (SENTRY_SNIPER_RANGE/2), y, SENTRY_SNIPER_RANGE) if(WEST) - range_bounds = RECT(x - (SENTRY_SNIPER_RANGE/2), y, SENTRY_SNIPER_RANGE, SENTRY_SNIPER_RANGE) + range_bounds = SQUARE(x - (SENTRY_SNIPER_RANGE/2), y, SENTRY_SNIPER_RANGE) if(NORTH) - range_bounds = RECT(x, y + (SENTRY_SNIPER_RANGE/2), SENTRY_SNIPER_RANGE, SENTRY_SNIPER_RANGE) + range_bounds = SQUARE(x, y + (SENTRY_SNIPER_RANGE/2), SENTRY_SNIPER_RANGE) if(SOUTH) - range_bounds = RECT(x, y - (SENTRY_SNIPER_RANGE/2), SENTRY_SNIPER_RANGE, SENTRY_SNIPER_RANGE) + range_bounds = SQUARE(x, y - (SENTRY_SNIPER_RANGE/2), SENTRY_SNIPER_RANGE) #undef SENTRY_SNIPER_RANGE /obj/structure/machinery/defenses/sentry/shotgun diff --git a/code/modules/defenses/sentry_computer.dm b/code/modules/defenses/sentry_computer.dm index 59c6409d552c..639a74e6ba30 100644 --- a/code/modules/defenses/sentry_computer.dm +++ b/code/modules/defenses/sentry_computer.dm @@ -402,8 +402,7 @@ var/obj/structure/machinery/defenses/sentry/defense = sentry if (defense.has_camera) defense.set_range() - var/datum/shape/rectangle/current_bb = defense.range_bounds - SEND_SIGNAL(src, COMSIG_CAMERA_SET_AREA, current_bb.center_x, current_bb.center_y, defense.loc.z, current_bb.width, current_bb.height) + SEND_SIGNAL(src, COMSIG_CAMERA_SET_AREA, defense.range_bounds, defense.loc.z) return TRUE if("ping") diff --git a/code/modules/defenses/sentry_flamer.dm b/code/modules/defenses/sentry_flamer.dm index 979d18eb41d1..2c5e9ae62677 100644 --- a/code/modules/defenses/sentry_flamer.dm +++ b/code/modules/defenses/sentry_flamer.dm @@ -90,13 +90,13 @@ /obj/structure/machinery/defenses/sentry/flamer/plasma/set_range() switch(dir) if(EAST) - range_bounds = RECT(x + (FLAMER_SENTRY_SNIPER_RANGE/2), y, FLAMER_SENTRY_SNIPER_RANGE, FLAMER_SENTRY_SNIPER_RANGE) + range_bounds = SQUARE(x + (FLAMER_SENTRY_SNIPER_RANGE/2), y, FLAMER_SENTRY_SNIPER_RANGE) if(WEST) - range_bounds = RECT(x - (FLAMER_SENTRY_SNIPER_RANGE/2), y, FLAMER_SENTRY_SNIPER_RANGE, FLAMER_SENTRY_SNIPER_RANGE) + range_bounds = SQUARE(x - (FLAMER_SENTRY_SNIPER_RANGE/2), y, FLAMER_SENTRY_SNIPER_RANGE) if(NORTH) - range_bounds = RECT(x, y + (FLAMER_SENTRY_SNIPER_RANGE/2), FLAMER_SENTRY_SNIPER_RANGE, FLAMER_SENTRY_SNIPER_RANGE) + range_bounds = SQUARE(x, y + (FLAMER_SENTRY_SNIPER_RANGE/2), FLAMER_SENTRY_SNIPER_RANGE) if(SOUTH) - range_bounds = RECT(x, y - (FLAMER_SENTRY_SNIPER_RANGE/2), FLAMER_SENTRY_SNIPER_RANGE, FLAMER_SENTRY_SNIPER_RANGE) + range_bounds = SQUARE(x, y - (FLAMER_SENTRY_SNIPER_RANGE/2), FLAMER_SENTRY_SNIPER_RANGE) #undef FLAMER_SENTRY_SNIPER_RANGE diff --git a/code/modules/economy/TradeDestinations.dm b/code/modules/economy/TradeDestinations.dm deleted file mode 100644 index 94ead45bf13e..000000000000 --- a/code/modules/economy/TradeDestinations.dm +++ /dev/null @@ -1,110 +0,0 @@ - -GLOBAL_LIST_EMPTY(weighted_randomevent_locations) -GLOBAL_LIST_EMPTY(weighted_mundaneevent_locations) - -/datum/trade_destination - var/name = "" - var/description = "" - var/distance = 0 - var/list/willing_to_buy = list() - var/list/willing_to_sell = list() - var/can_shuttle_here = 0 //one day crew from the exodus will be able to travel to this destination - var/list/viable_random_events = list() - var/list/temp_price_change[BIOMEDICAL] - var/list/viable_mundane_events = list() - -/datum/trade_destination/proc/get_custom_eventstring(event_type) - return null - -//distance is measured in AU and co-relates to travel time -/datum/trade_destination/centcomm - name = "CentComm" - description = "Weyland-Yutani's administrative centre for Tau Ceti." - distance = 1.2 - willing_to_buy = list() - willing_to_sell = list() - viable_random_events = list(SECURITY_BREACH, CORPORATE_ATTACK, AI_LIBERATION) - viable_mundane_events = list(ELECTION, RESIGNATION, CELEBRITY_DEATH) - -/datum/trade_destination/anansi - name = "NSS Anansi" - description = "Medical station ran by Second Red Cross (but owned by WY) for handling emergency cases from nearby colonies." - distance = 1.7 - willing_to_buy = list() - willing_to_sell = list() - viable_random_events = list(SECURITY_BREACH, CULT_CELL_REVEALED, BIOHAZARD_OUTBREAK, PIRATES, ALIEN_RAIDERS) - viable_mundane_events = list(RESEARCH_BREAKTHROUGH, RESEARCH_BREAKTHROUGH, BARGAINS, GOSSIP) - -/datum/trade_destination/anansi/get_custom_eventstring(event_type) - if(event_type == RESEARCH_BREAKTHROUGH) - return "Thanks to research conducted on the NSS Anansi, Second Red Cross Society wishes to announce a major breakthough in the field of \ - [pick("mind-machine interfacing","neuroscience","nano-augmentation","genetics")]. Weyland-Yutani is expected to announce a co-exploitation deal within the fortnight." - return null - -/datum/trade_destination/icarus - name = "NMV Icarus" - description = "Corvette assigned to patrol NSS Exodus local space." - distance = 0.1 - willing_to_buy = list() - willing_to_sell = list() - viable_random_events = list(SECURITY_BREACH, AI_LIBERATION, PIRATES) - -/datum/trade_destination/redolant - name = "OAV Redolant" - description = "Osiris Atmospherics station in orbit around the only gas giant insystem. They retain tight control over shipping rights, and Osiris warships protecting their prize are not an uncommon sight in Tau Ceti." - distance = 0.6 - willing_to_buy = list() - willing_to_sell = list() - viable_random_events = list(INDUSTRIAL_ACCIDENT, PIRATES, CORPORATE_ATTACK) - viable_mundane_events = list(RESEARCH_BREAKTHROUGH, RESEARCH_BREAKTHROUGH) - -/datum/trade_destination/redolant/get_custom_eventstring(event_type) - if(event_type == RESEARCH_BREAKTHROUGH) - return "Thanks to research conducted on the OAV Redolant, Osiris Atmospherics wishes to announce a major breakthough in the field of \ - [pick("phoron research","high energy flux capacitance","super-compressed materials","theoretical particle physics")]. Weyland-Yutani is expected to announce a co-exploitation deal within the fortnight." - return null - -/datum/trade_destination/beltway - name = "Beltway mining chain" - description = "A co-operative effort between Beltway and Weyland-Yutani to exploit the rich outer asteroid belt of the Tau Ceti system." - distance = 7.5 - willing_to_buy = list() - willing_to_sell = list() - viable_random_events = list(PIRATES, INDUSTRIAL_ACCIDENT) - viable_mundane_events = list(TOURISM) - -/datum/trade_destination/biesel - name = "Biesel" - description = "Large ship yards, strong economy and a stable, well-educated populace, Biesel largely owes allegiance to Sol / Vessel Contracting and begrudgingly tolerates WY. Capital is Lowell City." - distance = 2.3 - willing_to_buy = list() - willing_to_sell = list() - viable_random_events = list(RIOTS, INDUSTRIAL_ACCIDENT, BIOHAZARD_OUTBREAK, CULT_CELL_REVEALED, FESTIVAL, MOURNING) - viable_mundane_events = list(BARGAINS, GOSSIP, SONG_DEBUT, MOVIE_RELEASE, ELECTION, TOURISM, RESIGNATION, CELEBRITY_DEATH) - -/datum/trade_destination/new_gibson - name = "New Gibson" - description = "Heavily industrialised rocky planet containing the majority of the planet-bound resources in the system, New Gibson is torn by unrest and has very little wealth to call it's own except in the hands of the corporations who jostle with WY for control." - distance = 6.6 - willing_to_buy = list() - willing_to_sell = list() - viable_random_events = list(RIOTS, INDUSTRIAL_ACCIDENT, BIOHAZARD_OUTBREAK, CULT_CELL_REVEALED, FESTIVAL, MOURNING) - viable_mundane_events = list(ELECTION, TOURISM, RESIGNATION) - -/datum/trade_destination/luthien - name = "Luthien" - description = "A small colony established on a feral, untamed world (largely jungle). Savages and wild beasts attack the outpost regularly, although WY maintains tight military control." - distance = 8.9 - willing_to_buy = list() - willing_to_sell = list() - viable_random_events = list(WILD_ANIMAL_ATTACK, CULT_CELL_REVEALED, FESTIVAL, MOURNING, ANIMAL_RIGHTS_RAID, ALIEN_RAIDERS) - viable_mundane_events = list(ELECTION, TOURISM, BIG_GAME_HUNTERS, RESIGNATION) - -/datum/trade_destination/reade - name = "Reade" - description = "A cold, metal-deficient world, WY maintains large pastures in whatever available space in an attempt to salvage something from this profitless colony." - distance = 7.5 - willing_to_buy = list() - willing_to_sell = list() - viable_random_events = list(WILD_ANIMAL_ATTACK, CULT_CELL_REVEALED, FESTIVAL, MOURNING, ANIMAL_RIGHTS_RAID, ALIEN_RAIDERS) - viable_mundane_events = list(ELECTION, TOURISM, BIG_GAME_HUNTERS, RESIGNATION) diff --git a/code/modules/economy/economy_misc.dm b/code/modules/economy/economy_misc.dm index d65799f8f96f..afd2b1b8ad36 100644 --- a/code/modules/economy/economy_misc.dm +++ b/code/modules/economy/economy_misc.dm @@ -75,11 +75,6 @@ GLOBAL_VAR_INIT(economy_init, FALSE) if(GLOB.economy_init) return 2 - for(var/loc_type in typesof(/datum/trade_destination) - /datum/trade_destination) - var/datum/trade_destination/D = new loc_type - GLOB.weighted_randomevent_locations[D] = length(D.viable_random_events) - GLOB.weighted_mundaneevent_locations[D] = length(D.viable_mundane_events) - create_station_account() create_department_account("Vendor") diff --git a/code/modules/gear_presets/_select_equipment.dm b/code/modules/gear_presets/_select_equipment.dm index 5311a7a79a3b..138e091ad5a4 100644 --- a/code/modules/gear_presets/_select_equipment.dm +++ b/code/modules/gear_presets/_select_equipment.dm @@ -138,6 +138,9 @@ new_human.set_languages(languages) /datum/equipment_preset/proc/load_preset(mob/living/carbon/human/new_human, randomise = FALSE, count_participant = FALSE, client/mob_client, show_job_gear = TRUE) + if(!new_human.hud_used) + new_human.create_hud() + load_race(new_human, mob_client) if(randomise || uses_special_name) load_name(new_human, randomise, mob_client) diff --git a/code/modules/gear_presets/other.dm b/code/modules/gear_presets/other.dm index 9ea05749fe0d..4d7ef9bda559 100644 --- a/code/modules/gear_presets/other.dm +++ b/code/modules/gear_presets/other.dm @@ -504,29 +504,6 @@ new_human.equip_if_possible(new /obj/item/clothing/glasses/sunglasses, WEAR_EYES) new_human.equip_if_possible(new /obj/item/clipboard, WEAR_WAIST) -//*****************************************************************************************************/ - -/datum/equipment_preset/other/compression_suit - name = "Mk50 Compression Suit" - flags = EQUIPMENT_PRESET_EXTRA - faction = FACTION_PMC - skills = /datum/skills/pfc - idtype = /obj/item/card/id/data - -/datum/equipment_preset/other/compression_suit/load_gear(mob/living/carbon/human/new_human) - //TODO: add backpacks and satchels - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots, WEAR_FEET) - - new_human.equip_to_slot_or_del(new /obj/item/clothing/under/colonist, WEAR_BODY) - new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/space/compression, WEAR_JACKET) - new_human.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/compression, WEAR_HEAD) - var /obj/item/tank/jetpack/J = new /obj/item/tank/jetpack/oxygen(new_human) - new_human.equip_to_slot_or_del(J, WEAR_BACK) - J.toggle() - new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/breath, WEAR_FACE) - J.Topic(null, list("stat" = 1)) - spawn_merc_weapon(new_human) - //*****************************************************************************************************/ diff --git a/code/modules/mentor/looc_toggle.dm b/code/modules/mentor/looc_toggle.dm index 7c5b95b1fcb0..b224e72e79d2 100644 --- a/code/modules/mentor/looc_toggle.dm +++ b/code/modules/mentor/looc_toggle.dm @@ -13,6 +13,7 @@ // Called when the action is clicked on. /datum/action/looc_toggle/action_activate() + . = ..() if(owner.looc_overhead) button.icon_state = "template" owner.looc_overhead = FALSE diff --git a/code/modules/mob/camera/imaginary_friend.dm b/code/modules/mob/camera/imaginary_friend.dm index 4e7be80056de..0a4d5ee65c5c 100644 --- a/code/modules/mob/camera/imaginary_friend.dm +++ b/code/modules/mob/camera/imaginary_friend.dm @@ -280,6 +280,7 @@ action_icon_state = "joinmob" /datum/action/innate/imaginary_orbit/action_activate() + . = ..() var/mob/camera/imaginary_friend/friend = owner friend.recall() @@ -288,6 +289,7 @@ action_icon_state = "hidemob" /datum/action/innate/imaginary_hide/action_activate() + . = ..() var/mob/camera/imaginary_friend/friend = owner if(friend.hidden) friend.hidden = FALSE diff --git a/code/modules/mob/dead/observer/actions.dm b/code/modules/mob/dead/observer/actions.dm index 7daae802dc7a..192c6cd1e3b8 100644 --- a/code/modules/mob/dead/observer/actions.dm +++ b/code/modules/mob/dead/observer/actions.dm @@ -3,6 +3,7 @@ action_icon_state = "ghost" /datum/action/ghost/action_activate() + . = ..() if(!owner.client) return @@ -38,6 +39,7 @@ qdel(src) /datum/action/join_ert/action_activate() + . = ..() if(!owner.client) return @@ -50,6 +52,7 @@ listen_signal = COMSIG_KB_OBSERVER_JOIN_PREDATOR /datum/action/join_predator/action_activate() + . = ..() var/mob/dead/observer/activator = owner activator.join_as_yautja() @@ -58,6 +61,7 @@ action_icon_state = "view_crew_manifest" /datum/action/observer_action/view_crew_manifest/action_activate() + . = ..() show_browser(owner, GLOB.data_core.get_manifest(), "Crew Manifest", "manifest", "size=450x750") /datum/action/observer_action/view_hive_status @@ -65,6 +69,7 @@ action_icon_state = "view_hive_status" /datum/action/observer_action/view_hive_status/action_activate() + . = ..() var/mob/dead/observer/activator = owner activator.hive_status() @@ -74,6 +79,7 @@ listen_signal = COMSIG_KB_OBSERVER_JOIN_XENO /datum/action/observer_action/join_xeno/action_activate() + . = ..() if(!owner.client) return @@ -90,6 +96,7 @@ listen_signal = COMSIG_KB_OBSERVER_JOIN_LESSER_DRONE /datum/action/observer_action/join_lesser_drone/action_activate() + . = ..() if(!owner.client) return diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 213d037afe6e..2c5ddf44b3ee 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -350,10 +350,10 @@ return "[face_name] (as [id_name])" return face_name -//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable +//Returns "Unknown" if facially unidentifiable and real_name if not. Useful for setting name when headless or when updating a human's name variable /mob/living/carbon/human/proc/get_face_name() var/obj/limb/head/head = get_limb("head") - if(!head || head.disfigured || (head.status & LIMB_DESTROYED) || !real_name) //disfigured. use id-name if possible + if(!head || (head.status & LIMB_DESTROYED) || !real_name) //unidentifiable. use id-name if possible return "Unknown" return real_name @@ -907,9 +907,6 @@ var/obj/limb/head/h = get_limb("head") if(QDELETED(h)) h = get_limb("synthetic head") - else - h.disfigured = 0 - name = get_visible_name() if(species && !(species.flags & NO_BLOOD)) restore_blood() @@ -1712,15 +1709,15 @@ /mob/living/carbon/human/on_knockedout_trait_gain(datum/source) . = ..() - + update_execute_hud() - + return . /mob/living/carbon/human/on_knockedout_trait_loss(datum/source) . = ..() update_execute_hud() - + return . - + diff --git a/code/modules/mob/living/carbon/human/human_abilities.dm b/code/modules/mob/living/carbon/human/human_abilities.dm index 76ebbed06de6..9976fe37a4ff 100644 --- a/code/modules/mob/living/carbon/human/human_abilities.dm +++ b/code/modules/mob/living/carbon/human/human_abilities.dm @@ -20,6 +20,7 @@ cooldown = COMMAND_ORDER_COOLDOWN /datum/action/human_action/issue_order/action_activate() + . = ..() if(!ishuman(owner)) return var/mob/living/carbon/human/H = owner @@ -58,6 +59,7 @@ return FALSE /datum/action/human_action/smartpack/action_activate() + . = ..() if(!istype(owner, /mob/living/carbon/human)) return var/mob/living/carbon/human/H = owner @@ -129,6 +131,7 @@ CULT // Called when the action is clicked on. /datum/action/human_action/activable/action_activate() + . = ..() if(!ishuman(owner)) return var/mob/living/carbon/human/H = owner @@ -286,6 +289,7 @@ CULT action_icon_state = "cultist_channel_hivemind" /datum/action/human_action/activable/cult/speak_hivemind/action_activate() + . = ..() if(!can_use_action()) return @@ -316,6 +320,7 @@ CULT var/list/items_to_spawn = list(/obj/item/clothing/suit/cultist_hoodie/, /obj/item/clothing/head/cultist_hood/) /datum/action/human_action/activable/cult/obtain_equipment/action_activate() + . = ..() if(!can_use_action()) return @@ -515,6 +520,7 @@ CULT action_icon_state = "mutineer_begin" /datum/action/human_action/activable/mutineer/mutineer_begin/action_activate() + . = ..() if(!can_use_action()) return @@ -549,6 +555,7 @@ CULT UnregisterSignal(L, COMSIG_MOB_RESET_VIEW) /datum/action/human_action/cancel_view/action_activate() + . = ..() if(!can_use_action()) return @@ -575,6 +582,7 @@ CULT UnregisterSignal(L, COMSIG_MOB_RESET_VIEW) /datum/action/human_action/vehicle_unbuckle/action_activate() + . = ..() if(!can_use_action()) return @@ -600,6 +608,7 @@ CULT action_icon_state = "cancel_view" /datum/action/human_action/mg_exit/action_activate() + . = ..() if(!can_use_action()) return @@ -619,6 +628,7 @@ CULT UnregisterSignal(user, COMSIG_MOB_RESET_VIEW) /datum/action/human_action/toggle_arc_antenna/action_activate() + . = ..() if(!can_use_action()) return diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 8a528df92de5..48dea97699ea 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -335,7 +335,11 @@ In most cases it makes more sense to use apply_damage() instead! And make sure t for(var/obj/limb/L as anything in parts) var/armor = getarmor(L, armour_type) var/modified_damage = armor_damage_reduction(armour_config, damage, armor, penetration, 0, 0) - L.take_damage(modified_damage / amount_of_parts) + if(damage_type == BURN) + L.take_damage(burn = modified_damage / amount_of_parts) + else + L.take_damage(modified_damage / amount_of_parts) + updatehealth() UpdateDamageIcon() diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 7cb2d04e67de..c9a36d283794 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -105,12 +105,6 @@ //Can we act if(is_mob_restrained()) return 0 - //Do we have a working jetpack - if(istype(back, /obj/item/tank/jetpack)) - var/obj/item/tank/jetpack/J = back - if(((!check_drift) || (check_drift && J.stabilization_on)) && (body_position == STANDING_UP) && (J.allow_thrust(0.01, src))) - inertia_dir = 0 - return 1 // if(!check_drift && J.allow_thrust(0.01, src)) // return 1 diff --git a/code/modules/mob/living/carbon/human/life/life_helpers.dm b/code/modules/mob/living/carbon/human/life/life_helpers.dm index cab3ae21a782..9388204a967d 100644 --- a/code/modules/mob/living/carbon/human/life/life_helpers.dm +++ b/code/modules/mob/living/carbon/human/life/life_helpers.dm @@ -6,25 +6,6 @@ * Mostly for procs that are not called in the direct Life() loop, except for exact functionality matches (handle_breath, breathe, get_breath_from_internal for example) */ -//Calculate how vulnerable the human is to under- and overpressure. -//Returns 0 (equals 0 %) if sealed in an undamaged suit, 1 if unprotected (equals 100%). -//Suitdamage can modifiy this in 10% steps. -/mob/living/carbon/human/proc/get_pressure_weakness() - - var/pressure_adjustment_coefficient = 1 // Assume no protection at first. - - if(wear_suit && (wear_suit.flags_inventory & NOPRESSUREDMAGE) && head && (head.flags_inventory & NOPRESSUREDMAGE)) //Complete set of pressure-proof suit worn, assume fully sealed. - pressure_adjustment_coefficient = 0 - - //Handles breaches in your space suit. 10 suit damage equals a 100% loss of pressure protection. - if(istype(wear_suit, /obj/item/clothing/suit/space)) - var/obj/item/clothing/suit/space/S = wear_suit - if(S.can_breach && S.damage) - pressure_adjustment_coefficient += S.damage * 0.1 - - pressure_adjustment_coefficient = min(1, max(pressure_adjustment_coefficient, 0)) //So it isn't less than 0 or larger than 1. - return pressure_adjustment_coefficient - /mob/living/carbon/human/proc/stabilize_body_temperature() diff --git a/code/modules/mob/living/carbon/human/species/working_joe/_species.dm b/code/modules/mob/living/carbon/human/species/working_joe/_species.dm index c032e25708eb..f2c0e8d4cf26 100644 --- a/code/modules/mob/living/carbon/human/species/working_joe/_species.dm +++ b/code/modules/mob/living/carbon/human/species/working_joe/_species.dm @@ -50,6 +50,7 @@ /datum/action/joe_emote_panel/action_activate() + . = ..() if(!can_use_action()) return diff --git a/code/modules/mob/living/carbon/xenomorph/Embryo.dm b/code/modules/mob/living/carbon/xenomorph/Embryo.dm index d0890bd3cf37..61ba87cd001b 100644 --- a/code/modules/mob/living/carbon/xenomorph/Embryo.dm +++ b/code/modules/mob/living/carbon/xenomorph/Embryo.dm @@ -191,7 +191,7 @@ if(!picked) // Get a candidate from observers - var/list/candidates = get_alien_candidates(hive) + var/list/candidates = get_alien_candidates(hive, abomination = (isyautja(affected_mob) || (flags_embryo & FLAG_EMBRYO_PREDATOR))) if(candidates && length(candidates)) // If they were facehugged by a player thats still in queue, they get second dibs on the new larva. if(hugger_ckey) diff --git a/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm b/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm index 1fb48f699efa..3f37845380f0 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm @@ -18,6 +18,7 @@ return TRUE /datum/action/xeno_action/watch_xeno/action_activate() + . = ..() var/mob/living/carbon/xenomorph/X = owner if (!X.check_state(TRUE)) return FALSE diff --git a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm index f0fd8a4d86a7..e7320b17c333 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm @@ -264,7 +264,7 @@ /mob/living/carbon/xenomorph/proc/pounced_mob(mob/living/L) // This should only be called back by a mob that has pounce, so no need to check - var/datum/action/xeno_action/activable/pounce/pounceAction = get_xeno_action_by_type(src, /datum/action/xeno_action/activable/pounce) + var/datum/action/xeno_action/activable/pounce/pounceAction = get_action(src, /datum/action/xeno_action/activable/pounce) // Unconscious or dead, or not throwing but used pounce. if(!check_state() || (!throwing && !pounceAction.action_cooldown_check())) @@ -336,7 +336,7 @@ pounced_mob(L) /mob/living/carbon/xenomorph/proc/pounced_obj(obj/O) - var/datum/action/xeno_action/activable/pounce/pounceAction = get_xeno_action_by_type(src, /datum/action/xeno_action/activable/pounce) + var/datum/action/xeno_action/activable/pounce/pounceAction = get_action(src, /datum/action/xeno_action/activable/pounce) // Unconscious or dead, or not throwing but used pounce if(!check_state() || (!throwing && !pounceAction.action_cooldown_check())) diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm index b07f766b179d..eed2dce5f7a8 100644 --- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm @@ -343,6 +343,8 @@ var/atom/movable/vis_obj/xeno_wounds/wound_icon_holder var/atom/movable/vis_obj/xeno_pack/backpack_icon_holder + /// If TRUE, the xeno cannot slash anything + var/cannot_slash = FALSE /mob/living/carbon/xenomorph/Initialize(mapload, mob/living/carbon/xenomorph/old_xeno, hivenumber) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/boiler/boiler_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/boiler/boiler_powers.dm index c749b0adb5ba..2431e4629876 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/boiler/boiler_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/boiler/boiler_powers.dm @@ -108,7 +108,7 @@ var/mob/living/carbon/xenomorph/xeno = owner if(!action_cooldown_check()) // activate c/d only if we already spit for (var/action_type in action_types_to_cd) - var/datum/action/xeno_action/xeno_action = get_xeno_action_by_type(xeno, action_type) + var/datum/action/xeno_action/xeno_action = get_action(xeno, action_type) if (!istype(xeno_action)) continue @@ -149,7 +149,7 @@ to_chat(xeno, SPAN_XENOHIGHDANGER("We dump our acid through our pores, creating a shroud of gas!")) for (var/action_type in action_types_to_cd) - var/datum/action/xeno_action/xeno_action = get_xeno_action_by_type(xeno, action_type) + var/datum/action/xeno_action/xeno_action = get_action(xeno, action_type) if (!istype(xeno_action)) continue @@ -218,7 +218,7 @@ empowered = FALSE empowering_charge_counter = 0 button.overlays -= "+empowered" - var/datum/action/xeno_action/activable/acid_mine/mine = get_xeno_action_by_type(xeno, /datum/action/xeno_action/activable/acid_mine) + var/datum/action/xeno_action/activable/acid_mine/mine = get_action(xeno, /datum/action/xeno_action/activable/acid_mine) if(!mine.empowered) mine.empowered = TRUE mine.button.overlays += "+empowered" diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/crusher/crusher_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/crusher/crusher_powers.dm index e1af5e36a40f..1dd4dc5a1c87 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/crusher/crusher_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/crusher/crusher_powers.dm @@ -82,7 +82,7 @@ // This ties the pounce/throwing backend into the old collision backend /mob/living/carbon/xenomorph/crusher/pounced_obj(obj/O) - var/datum/action/xeno_action/activable/pounce/crusher_charge/CCA = get_xeno_action_by_type(src, /datum/action/xeno_action/activable/pounce/crusher_charge) + var/datum/action/xeno_action/activable/pounce/crusher_charge/CCA = get_action(src, /datum/action/xeno_action/activable/pounce/crusher_charge) if (istype(CCA) && !CCA.action_cooldown_check() && !(O.type in CCA.not_reducing_objects)) CCA.reduce_cooldown(50) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/defender/defender_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/defender/defender_powers.dm index d7a4f987623a..8736d612c822 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/defender/defender_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/defender/defender_powers.dm @@ -183,6 +183,7 @@ return ..() /datum/action/xeno_action/activable/fortify/action_activate() + . = ..() ..() var/mob/living/carbon/xenomorph/xeno = owner if(xeno.fortify && xeno.selected_ability != src) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm index c5988f12539d..b262624bfe01 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm @@ -485,6 +485,7 @@ listen_signal = COMSIG_KB_XENO_EVOLVE /datum/action/xeno_action/onclick/evolve/action_activate() + . = ..() var/mob/living/carbon/xenomorph/xeno = owner xeno.do_evolve() diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm index 014cb3d2f24b..843cfeac540b 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm @@ -398,7 +398,7 @@ return if(X.layer == XENO_HIDING_LAYER) //Xeno is currently hiding, unhide him - var/datum/action/xeno_action/onclick/xenohide/hide = get_xeno_action_by_type(X, /datum/action/xeno_action/onclick/xenohide) + var/datum/action/xeno_action/onclick/xenohide/hide = get_action(X, /datum/action/xeno_action/onclick/xenohide) if(hide) hide.post_attack() @@ -911,7 +911,7 @@ to_chat(stabbing_xeno, SPAN_XENOWARNING("We must be above ground to do this.")) return - if(!stabbing_xeno.check_state()) + if(!stabbing_xeno.check_state() || stabbing_xeno.cannot_slash) return FALSE var/pre_result = pre_ability_act(stabbing_xeno, targetted_atom) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_powers.dm index 094732300a1f..3c1d3a04543d 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_powers.dm @@ -13,7 +13,7 @@ break if(found) - var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis = get_xeno_action_by_type(xeno, /datum/action/xeno_action/onclick/lurker_invisibility) + var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis = get_action(xeno, /datum/action/xeno_action/onclick/lurker_invisibility) if(lurker_invis) lurker_invis.invisibility_off() // Full cooldown diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_abilities.dm index 199df345fb62..4fe0e9107995 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_abilities.dm @@ -87,7 +87,7 @@ if(!X.check_state(1)) return - var/datum/action/xeno_action/activable/cleave/cAction = get_xeno_action_by_type(X, /datum/action/xeno_action/activable/cleave) + var/datum/action/xeno_action/activable/cleave/cAction = get_action(X, /datum/action/xeno_action/activable/cleave) if (!istype(cAction)) return @@ -328,7 +328,7 @@ if(!X.check_state(1)) return - var/datum/action/xeno_action/activable/warden_heal/WH = get_xeno_action_by_type(X, /datum/action/xeno_action/activable/warden_heal) + var/datum/action/xeno_action/activable/warden_heal/WH = get_action(X, /datum/action/xeno_action/activable/warden_heal) if (!istype(WH)) return diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm index 4d3a792af89a..3cbf0769514f 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm @@ -418,8 +418,8 @@ shake_camera(target_carbon, 2, 1) - var/datum/action/xeno_action/activable/prae_abduct/abduct_action = get_xeno_action_by_type(oppressor_user, /datum/action/xeno_action/activable/prae_abduct) - var/datum/action/xeno_action/activable/tail_lash/tail_lash_action = get_xeno_action_by_type(oppressor_user, /datum/action/xeno_action/activable/tail_lash) + var/datum/action/xeno_action/activable/prae_abduct/abduct_action = get_action(oppressor_user, /datum/action/xeno_action/activable/prae_abduct) + var/datum/action/xeno_action/activable/tail_lash/tail_lash_action = get_action(oppressor_user, /datum/action/xeno_action/activable/tail_lash) if(abduct_action && !abduct_action.action_cooldown_check()) abduct_action.reduce_cooldown(5 SECONDS) if(tail_lash_action && !tail_lash_action.action_cooldown_check()) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/predalien/predalien_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/predalien/predalien_powers.dm index 3ec4855f9c3a..a240c3928a3c 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/predalien/predalien_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/predalien/predalien_powers.dm @@ -117,7 +117,7 @@ xeno.anchored = FALSE unroot_human(carbon, TRAIT_SOURCE_ABILITY("Devastate")) - return ..() + return ..() /datum/action/xeno_action/onclick/feralrush/use_ability(atom/A) @@ -149,6 +149,7 @@ predatoralien.recalculate_armor() playsound(predatoralien, 'sound/voice/predalien_growl.ogg', 75, 0, status = 0) apply_cooldown() + return ..() /datum/action/xeno_action/onclick/feralrush/proc/remove_rush_effects() @@ -180,7 +181,7 @@ if(!xeno.check_state()) return - var/datum/action/xeno_action/activable/feralfrenzy/guttype = get_xeno_action_by_type(xeno, /datum/action/xeno_action/activable/feralfrenzy) + var/datum/action/xeno_action/activable/feralfrenzy/guttype = get_action(xeno, /datum/action/xeno_action/activable/feralfrenzy) if(!guttype) return @@ -248,7 +249,7 @@ else predalien_smash.visible_message(SPAN_XENOWARNING("[predalien_smash]'s claws twitch."), SPAN_XENOWARNING("We couldn't grab our target. Wait a moment to try again.")) - return TRUE + return ..() /mob/living/carbon/xenomorph/predalien/stop_pulling() if(isliving(pulling) && smashing) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm index 381acba92a51..6ef111aed66f 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm @@ -401,6 +401,7 @@ remove_personal_ally() if("Clear Personal Allies") clear_personal_allies() + return ..() /datum/action/xeno_action/onclick/manage_hive/proc/add_personal_ally() var/mob/living/carbon/xenomorph/queen/user_xeno = owner diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm b/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm index 80cf5c1e37ac..bff59186fd04 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm @@ -51,6 +51,7 @@ // Any strain or caste-specific state should be stored on behavior_delegate objects // which use_ability invocations can modify using typechecks and typecasts where appropriate. /datum/action/xeno_action/proc/use_ability(atom/target) + SHOULD_CALL_PARENT(TRUE) if(!owner) return FALSE track_xeno_ability_stats() @@ -129,10 +130,17 @@ /// A wrapper for use_ability that sends a signal /datum/action/xeno_action/proc/use_ability_wrapper(...) // TODO: make hidden a part of can_use_action - if(!hidden && can_use_action() && use_ability(arglist(args))) + if(!can_use_action()) + SEND_SIGNAL(src, COMSIG_XENO_FAILED_ACTION_USED, owner) + return FALSE + + SEND_SIGNAL(src, COMSIG_XENO_PRE_ACTION_USED, owner) + + if(!hidden && use_ability(arglist(args))) SEND_SIGNAL(src, COMSIG_XENO_ACTION_USED, owner) return TRUE + SEND_SIGNAL(src, COMSIG_XENO_FAILED_ACTION_USED, owner) return FALSE // For actions that do something on each life tick @@ -150,6 +158,7 @@ // For non-activable Xeno actions, this is used to // actually DO the action. /datum/action/xeno_action/activable/action_activate() + . = ..() if(!owner) return if(hidden) @@ -201,6 +210,7 @@ no_cooldown_msg = TRUE /datum/action/xeno_action/onclick/action_activate() + . = ..() use_ability_wrapper(null) // Adds a cooldown to this @@ -362,17 +372,6 @@ deltimer(charge_timer_id) charge_timer_id = TIMER_ID_NULL -// Helper proc to get an action on a target Xeno by type. -// Used to interact with abilities from the outside -/proc/get_xeno_action_by_type(mob/living/carbon/xenomorph/X, typepath) - if (!istype(X)) - CRASH("xeno_action.dm: get_xeno_action_by_type invoked with non-xeno first argument.") - - for (var/datum/action/xeno_action/XA in X.actions) - if (istype(XA, typepath)) - return XA - return null - // Helper proc to check if there is anything blocking the way from mob M to the atom A // Max distance can be supplied to check some of the way instead of the whole way. /proc/check_clear_path_to_target(mob/M, atom/A, smash_windows = TRUE, max_distance = 1000) @@ -420,6 +419,7 @@ return FALSE /datum/action/xeno_action/active_toggle/action_activate() + . = ..() toggle_toggle() /datum/action/xeno_action/active_toggle/life_tick() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm b/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm index 24ac22d6bc52..a84b9965f9c3 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm @@ -261,11 +261,11 @@ H.apply_armoured_damage(get_xeno_damage_slash(H, damage), ARMOR_MELEE, BRUTE, bound_xeno.zone_selected) - var/datum/action/xeno_action/activable/pounce/crusher_charge/cAction = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/pounce/crusher_charge) + var/datum/action/xeno_action/activable/pounce/crusher_charge/cAction = get_action(bound_xeno, /datum/action/xeno_action/activable/pounce/crusher_charge) if (!cAction.action_cooldown_check()) cAction.reduce_cooldown(cdr_amount) - var/datum/action/xeno_action/onclick/crusher_shield/sAction = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/crusher_shield) + var/datum/action/xeno_action/onclick/crusher_shield/sAction = get_action(bound_xeno, /datum/action/xeno_action/onclick/crusher_shield) if (!sAction.action_cooldown_check()) sAction.reduce_cooldown(base_cdr_amount) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Hellhound.dm b/code/modules/mob/living/carbon/xenomorph/castes/Hellhound.dm index 93d40820bf7b..7df87f63cf3a 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Hellhound.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Hellhound.dm @@ -136,6 +136,6 @@ /datum/behavior_delegate/hellhound_base/melee_attack_additional_effects_self() ..() - var/datum/action/xeno_action/onclick/xenohide/hide = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/xenohide) + var/datum/action/xeno_action/onclick/xenohide/hide = get_action(bound_xeno, /datum/action/xeno_action/onclick/xenohide) if(hide) hide.post_attack() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm b/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm index 0ab9e9862b16..1dca7eb23f70 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm @@ -87,7 +87,7 @@ original_damage *= buffed_slash_damage_ratio target_carbon.set_effect(get_xeno_stun_duration(target_carbon, 3), SUPERSLOW) next_slash_buffed = FALSE - var/datum/action/xeno_action/onclick/lurker_assassinate/ability = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_assassinate) + var/datum/action/xeno_action/onclick/lurker_assassinate/ability = get_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_assassinate) if (ability) ability.button.icon_state = "template" @@ -114,19 +114,19 @@ /datum/behavior_delegate/lurker_base/melee_attack_additional_effects_self() ..() - var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) + var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis_action = get_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) if (lurker_invis_action) lurker_invis_action.invisibility_off() // Full cooldown /datum/behavior_delegate/lurker_base/proc/decloak_handler(mob/source) SIGNAL_HANDLER - var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) + var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis_action = get_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) if(istype(lurker_invis_action)) lurker_invis_action.invisibility_off(0.5) // Partial refund of remaining time /// Implementation for enabling invisibility. /datum/behavior_delegate/lurker_base/proc/on_invisibility() - var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/pounce/lurker) + var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_action(bound_xeno, /datum/action/xeno_action/activable/pounce/lurker) if(lurker_pounce_action) lurker_pounce_action.knockdown = TRUE // pounce knocks down lurker_pounce_action.freeze_self = TRUE @@ -137,7 +137,7 @@ /// Implementation for disabling invisibility. /datum/behavior_delegate/lurker_base/proc/on_invisibility_off() - var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/pounce/lurker) + var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_action(bound_xeno, /datum/action/xeno_action/activable/pounce/lurker) if(lurker_pounce_action) lurker_pounce_action.knockdown = FALSE // pounce no longer knocks down lurker_pounce_action.freeze_self = FALSE @@ -155,7 +155,7 @@ . += "Invisibility Remaining: [time_left] second\s." return - var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invisibility_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) + var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invisibility_action = get_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) if(!lurker_invisibility_action) return @@ -177,7 +177,7 @@ if(!bound_xeno || !bound_xeno.stealth) return - var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invisibility_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) + var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invisibility_action = get_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) if(!lurker_invisibility_action) return diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm b/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm index 830f4fc5a9cf..b60f150c442d 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm @@ -69,16 +69,19 @@ weed_food_states = list("Predalien_1","Predalien_2","Predalien_3") weed_food_states_flipped = list("Predalien_1","Predalien_2","Predalien_3") var/smashing = FALSE + /// If the pred alert/player notif should happen when the predalien spawns + var/should_announce_spawn = TRUE /mob/living/carbon/xenomorph/predalien/Initialize(mapload, mob/living/carbon/xenomorph/oldxeno, h_number) . = ..() - addtimer(CALLBACK(src, PROC_REF(announce_spawn)), 3 SECONDS) - hunter_data.dishonored = TRUE - hunter_data.dishonored_reason = "An abomination upon the honor of us all!" - hunter_data.dishonored_set = src - hud_set_hunter() + if(should_announce_spawn) + addtimer(CALLBACK(src, PROC_REF(announce_spawn)), 3 SECONDS) + hunter_data.dishonored = TRUE + hunter_data.dishonored_reason = "An abomination upon the honor of us all!" + hunter_data.dishonored_set = src + hud_set_hunter() AddComponent(/datum/component/footstep, 4, 25, 11, 2, "alien_footstep_medium") @@ -102,8 +105,20 @@ You must still listen to the queen. /mob/living/carbon/xenomorph/predalien/resist_fire() - ..() - SetKnockDown(0.1 SECONDS) + ..() + SetKnockDown(0.1 SECONDS) + +/mob/living/carbon/xenomorph/predalien/get_examine_text(mob/user) + . = ..() + var/datum/behavior_delegate/predalien_base/predalienkills = behavior_delegate + . += "It has [predalienkills.kills] kills to its name!" + +/mob/living/carbon/xenomorph/predalien/tutorial + should_announce_spawn = FALSE + +/mob/living/carbon/xenomorph/predalien/tutorial/gib(datum/cause_data/cause = create_cause_data("gibbing", src)) + death(cause, gibbed = TRUE) + /datum/behavior_delegate/predalien_base name = "Base Predalien Behavior Delegate" @@ -127,12 +142,3 @@ You must still listen to the queen. original_damage *= 1.5 return original_damage + kills * 2.5 - -/mob/living/carbon/xenomorph/predalien/get_examine_text(mob/user) - . = ..() - var/datum/behavior_delegate/predalien_base/predalienkills = behavior_delegate - var/kills = predalienkills.kills - . += "It has [kills] kills to its name!" - - - diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm b/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm index a66903a938c5..5b9c410e235a 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm @@ -468,6 +468,9 @@ /mob/living/carbon/xenomorph/queen/proc/make_combat_effective() queen_aged = TRUE + if(queen_age_timer_id != TIMER_ID_NULL) + deltimer(queen_age_timer_id) + queen_age_timer_id = TIMER_ID_NULL give_combat_abilities() recalculate_actions() @@ -545,9 +548,8 @@ . += "Pooled Larvae: [stored_larvae]" . += "Leaders: [xeno_leader_num] / [hive?.queen_leader_limit]" - if(queen_age_timer_id != TIMER_ID_NULL) - var/time_left = time2text(timeleft(queen_age_timer_id) + 1 MINUTES, "mm") // We add a minute so that it basically ceilings the value. - . += "Maturity: [time_left == 1? "[time_left] minute" : "[time_left] minutes"] remaining" + if(!queen_aged && queen_age_timer_id != TIMER_ID_NULL) + . += "Maturity: [time2text(timeleft(queen_age_timer_id), "mm:ss")] remaining" /mob/living/carbon/xenomorph/queen/proc/set_orders() set category = "Alien" diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm b/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm index 6e5da79fbed1..90614e338071 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm @@ -90,7 +90,7 @@ /datum/behavior_delegate/ravager_base/melee_attack_additional_effects_self() ..() - var/datum/action/xeno_action/activable/pounce/charge/cAction = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/pounce/charge) + var/datum/action/xeno_action/activable/pounce/charge/cAction = get_action(bound_xeno, /datum/action/xeno_action/activable/pounce/charge) if (!cAction.action_cooldown_check()) cAction.reduce_cooldown(slash_charge_cdr) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm index 8721294173e9..12fdb8d02843 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm @@ -91,6 +91,6 @@ /datum/behavior_delegate/runner_base/melee_attack_additional_effects_self() ..() - var/datum/action/xeno_action/onclick/xenohide/hide = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/xenohide) + var/datum/action/xeno_action/onclick/xenohide/hide = get_action(bound_xeno, /datum/action/xeno_action/onclick/xenohide) if(hide) hide.post_attack() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm b/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm index 01963496f967..3e7416f39fc5 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm @@ -95,7 +95,7 @@ addtimer(CALLBACK(src, PROC_REF(paralyzing_slash), carbon_target), NEURO_TOUCH_DELAY) next_slash_buffed = FALSE if(!next_slash_buffed) - var/datum/action/xeno_action/onclick/paralyzing_slash/ability = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/paralyzing_slash) + var/datum/action/xeno_action/onclick/paralyzing_slash/ability = get_action(bound_xeno, /datum/action/xeno_action/onclick/paralyzing_slash) if (ability && istype(ability)) ability.button.icon_state = "template" return original_damage diff --git a/code/modules/mob/living/carbon/xenomorph/hive_status_ui.dm b/code/modules/mob/living/carbon/xenomorph/hive_status_ui.dm index 360b4e8bbdde..eca88761ad9b 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_status_ui.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_status_ui.dm @@ -201,7 +201,7 @@ if(xenoSrc.stat == DEAD) return - var/datum/action/xeno_action/A = get_xeno_action_by_type(xenoSrc, /datum/action/xeno_action/activable/queen_give_plasma) + var/datum/action/xeno_action/A = get_action(xenoSrc, /datum/action/xeno_action/activable/queen_give_plasma) A?.use_ability_wrapper(xenoTarget) if("heal") @@ -214,7 +214,7 @@ if(xenoSrc.stat == DEAD) return - var/datum/action/xeno_action/A = get_xeno_action_by_type(xenoSrc, /datum/action/xeno_action/activable/queen_heal) + var/datum/action/xeno_action/A = get_action(xenoSrc, /datum/action/xeno_action/activable/queen_heal) A?.use_ability_wrapper(xenoTarget, TRUE) if("overwatch") diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm index f64bfd6b500f..857a76969354 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm @@ -73,7 +73,7 @@ found = trap break - var/datum/action/xeno_action/activable/boiler_trap/trap_ability = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/boiler_trap) + var/datum/action/xeno_action/activable/boiler_trap/trap_ability = get_action(bound_xeno, /datum/action/xeno_action/activable/boiler_trap) if (found) target_human.apply_armoured_damage(bonus_damage_shotgun_trapped, ARMOR_BIO, BURN) trap_ability.empowering_charge_counter = trap_ability.empower_charge_max diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm index 5ebafc88eaef..7ceaf2fed75e 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm @@ -276,9 +276,10 @@ addtimer(CALLBACK(xeno.hive, TYPE_PROC_REF(/datum/hive_status, free_respawn), xeno.client), 5 SECONDS) xeno.gib(create_cause_data("sacrificing itself", src)) + return ..() /datum/action/xeno_action/activable/healer_sacrifice/action_activate() - ..() + . = ..() var/mob/living/carbon/xenomorph/xeno = owner if(xeno.selected_ability != src) return diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/hivelord/resin_whisperer.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/hivelord/resin_whisperer.dm index 747463eb5ee5..89737f9ff595 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/hivelord/resin_whisperer.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/hivelord/resin_whisperer.dm @@ -43,19 +43,20 @@ name = "Coerce Resin (100)" action_icon_state = "secrete_resin" ability_name = "coerce resin" - var/last_use = 0 xeno_cooldown = 1 SECONDS thick = FALSE make_message = FALSE no_cooldown_msg = TRUE - var/care_about_adjacency = TRUE build_speed_mod = 2 // the actual building part takes twice as long macro_path = /datum/action/xeno_action/verb/verb_coerce_resin action_type = XENO_ACTION_CLICK + var/last_use = 0 + var/care_about_adjacency = TRUE + /datum/action/xeno_action/activable/secrete_resin/remote/use_ability(atom/target_atom, mods) if(!can_remote_build()) to_chat(owner, SPAN_XENONOTICE("We must be standing on weeds to establish a connection to the resin.")) @@ -70,8 +71,8 @@ var/turf/target_turf = get_turf(target_atom) if(!target_turf) return - - if(!(target_turf in view(10, owner))) + + if(care_about_adjacency && !(target_turf in view(10, owner))) to_chat(owner, SPAN_XENONOTICE("We must have a direct line of sight!")) return diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm index 310db35ab370..01f567398c44 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm @@ -54,7 +54,7 @@ last_combat_time = world.time /datum/behavior_delegate/praetorian_vanguard/proc/next_pierce_spin() - var/datum/action/xeno_action/activable/pierce/pAction = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/pierce) + var/datum/action/xeno_action/activable/pierce/pAction = get_action(bound_xeno, /datum/action/xeno_action/activable/pierce) if (istype(pAction)) pAction.should_spin_instead = TRUE @@ -62,7 +62,7 @@ return /datum/behavior_delegate/praetorian_vanguard/proc/next_pierce_normal() - var/datum/action/xeno_action/activable/pierce/pAction = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/pierce) + var/datum/action/xeno_action/activable/pierce/pAction = get_action(bound_xeno, /datum/action/xeno_action/activable/pierce) if (istype(pAction)) pAction.should_spin_instead = FALSE return @@ -88,6 +88,6 @@ new_shield.explosive_armor_amount = 1.5*XENO_EXPOSIVEARMOR_MOD_VERY_LARGE to_chat(praetorian, SPAN_XENOHIGHDANGER("We feel our defensive shell regenerate! It will block one hit!")) - var/datum/action/xeno_action/activable/cleave/caction = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/cleave) + var/datum/action/xeno_action/activable/cleave/caction = get_action(bound_xeno, /datum/action/xeno_action/activable/cleave) if (istype(caction)) caction.buffed = TRUE diff --git a/code/modules/movement/movement.dm b/code/modules/movement/movement.dm index e12a5b439296..8151d2df6707 100644 --- a/code/modules/movement/movement.dm +++ b/code/modules/movement/movement.dm @@ -140,11 +140,11 @@ destination.Entered(src, oldloc) if(destarea && (old_area != destarea || !isturf(oldloc))) destarea.Entered(src, oldloc) - - for(var/atom/movable/AM in destination) - if(AM == src) - continue - AM.Crossed(src, oldloc) + if(!(SEND_SIGNAL(src, COMSIG_MOVABLE_FORCEMOVE_PRE_CROSSED) & COMPONENT_IGNORE_CROSS)) + for(var/atom/movable/AM in destination) + if(AM == src) + continue + AM.Crossed(src, oldloc) Moved(oldloc, NONE, TRUE) . = TRUE diff --git a/code/modules/nightmare/nmnodes/flow.dm b/code/modules/nightmare/nmnodes/flow.dm index 1ca8c48f88b8..5f94326bbcaa 100644 --- a/code/modules/nightmare/nmnodes/flow.dm +++ b/code/modules/nightmare/nmnodes/flow.dm @@ -67,15 +67,14 @@ if(!.) return var/list/datum/nmnode/pickables = choices.Copy() for(var/datum/nmnode/node as anything in pickables) - if(isnum(node.raw["weight"])) - pickables[node] = node.raw["weight"] + pickables[node] = isnum(node.raw["weight"]) ? node.raw["weight"] : 1 var/list/datum/nmnode/picked = list() var/remaining = src.amount #if defined(UNIT_TESTS) remaining = length(pickables) // Force all to be picked for testing (this could potentially make false positives though) #endif while(length(pickables) && remaining > 0) - var/datum/nmnode/node = pickweight(pickables) + var/datum/nmnode/node = pick_weight(pickables) remaining-- pickables -= node picked += node diff --git a/code/modules/organs/limbs.dm b/code/modules/organs/limbs.dm index b4086ee898e2..879aeaf89634 100644 --- a/code/modules/organs/limbs.dm +++ b/code/modules/organs/limbs.dm @@ -1424,7 +1424,6 @@ treat_grafted var tells it to apply to grafted but unsalved wounds, for burn kit has_stump_icon = TRUE splint_icon_amount = 4 bandage_icon_amount = 4 - var/disfigured = 0 //whether the head is disfigured. var/eyes_r var/eyes_g @@ -1462,25 +1461,6 @@ treat_grafted var tells it to apply to grafted but unsalved wounds, for burn kit mob/attack_source = null,\ brute_reduced_by = -1, burn_reduced_by = -1) . = ..() - if (!disfigured) - if (brute_dam > 50 || brute_dam > 40 && prob(50)) - disfigure("brute") - if (burn_dam > 40) - disfigure("burn") - -/obj/limb/head/proc/disfigure(type = "brute") - if (disfigured) - return - if(type == "brute") - owner.visible_message(SPAN_DANGER("You hear a sickening cracking sound coming from \the [owner]'s face."), \ - SPAN_DANGER("Your face becomes an unrecognizible mangled mess!"), \ - SPAN_DANGER("You hear a sickening crack.")) - else - owner.visible_message(SPAN_DANGER("[owner]'s face melts away, turning into a mangled mess!"), \ - SPAN_DANGER("Your face melts off!"), \ - SPAN_DANGER("You hear a sickening sizzle.")) - disfigured = 1 - owner.name = owner.get_visible_name() /obj/limb/head/reset_limb_surgeries() for(var/zone in list("head", "eyes", "mouth")) diff --git a/code/modules/projectiles/ammo_boxes/grenade_packets.dm b/code/modules/projectiles/ammo_boxes/grenade_packets.dm index 5546fe3bc520..603e2e3a712f 100644 --- a/code/modules/projectiles/ammo_boxes/grenade_packets.dm +++ b/code/modules/projectiles/ammo_boxes/grenade_packets.dm @@ -109,6 +109,12 @@ GLOBAL_LIST_INIT(grenade_packets, list( icon_state = "general_packet" content_type = /obj/item/explosive/grenade/high_explosive/m15/rubber +/obj/item/storage/box/packet/sebb + name = "\improper G2 Electroshock grenade packet" + desc = "It contains three G2 Electroshock grenades. Handle with care." + icon_state = "sebb_packet" + content_type = /obj/item/explosive/grenade/sebb + /obj/item/storage/box/packet/airburst_he name = "\improper M74 airburst grenade packet" desc = "It contains three M74 airburst fragmentation grenades. This end towards the enemy." diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index 0e0fccf027db..5db904869973 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -365,7 +365,7 @@ Turn() or Shift() as there is virtually no overhead. ~N overlay_ammo_type = "_blank" overlay_gun_type = "_458" overlay_content = "_458" - magazine_type = /obj/item/ammo_magazine/handful/lever_action/xm88 + magazine_type = /obj/item/ammo_magazine/lever_action/xm88 /obj/item/ammo_box/magazine/lever_action/xm88/empty empty = TRUE diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index f7ffbf2875e2..d16f1b6fdd30 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -427,6 +427,10 @@ SEND_SIGNAL(src, COMSIG_GUN_RECALCULATE_ATTACHMENT_BONUSES) /obj/item/weapon/gun/proc/handle_random_attachments() + #ifdef AUTOWIKI // no randomness for my gun pictures, please + return + #endif + var/attachmentchoice var/randchance = random_spawn_chance diff --git a/code/modules/projectiles/gun_attachables.dm b/code/modules/projectiles/gun_attachables.dm index 7d015e4bac8d..e2108364e9ac 100644 --- a/code/modules/projectiles/gun_attachables.dm +++ b/code/modules/projectiles/gun_attachables.dm @@ -1054,6 +1054,7 @@ Defined in conflicts.dm of the #defines folder. button.name = name /datum/action/item_action/toggle_zoom_level/action_activate() + . = ..() var/obj/item/weapon/gun/G = holder_item var/obj/item/attachable/scope/variable_zoom/S = G.attachments["rail"] S.toggle_zoom_level() @@ -1674,6 +1675,7 @@ Defined in conflicts.dm of the #defines folder. /datum/action/item_action/vulture /datum/action/item_action/vulture/action_activate() + . = ..() var/obj/item/weapon/gun/gun_holder = holder_item var/obj/item/attachable/vulture_scope/scope = gun_holder.attachments["rail"] if(!istype(scope)) @@ -3515,6 +3517,7 @@ Defined in conflicts.dm of the #defines folder. button.overlays += image('icons/mob/hud/actions.dmi', button, action_icon_state) /datum/action/item_action/bipod/toggle_full_auto_switch/action_activate() + . = ..() var/obj/item/weapon/gun/holder_gun = holder_item var/obj/item/attachable/bipod/attached_bipod = holder_gun.attachments["under"] diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index b2ec3dea63ce..717914e38eba 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -268,6 +268,7 @@ /datum/action/item_action/taser/action_activate() + . = ..() var/obj/item/weapon/gun/energy/taser/taser = holder_item if(!ishuman(owner)) return diff --git a/code/modules/projectiles/guns/lever_action.dm b/code/modules/projectiles/guns/lever_action.dm index a8fb78f72a9c..179ce8d787d0 100644 --- a/code/modules/projectiles/guns/lever_action.dm +++ b/code/modules/projectiles/guns/lever_action.dm @@ -378,7 +378,6 @@ their unique feature is that a direct hit will buff your damage and firerate /obj/item/attachable/bayonet/upp, // Barrel /obj/item/attachable/bayonet, /obj/item/attachable/extended_barrel, - /obj/item/attachable/heavy_barrel, /obj/item/attachable/suppressor, /obj/item/attachable/compensator, /obj/item/attachable/reddot, // Rail @@ -393,9 +392,9 @@ their unique feature is that a direct hit will buff your damage and firerate /obj/item/weapon/gun/lever_action/xm88/set_gun_config_values() ..() - set_fire_delay(FIRE_DELAY_TIER_2) + set_fire_delay(FIRE_DELAY_TIER_2 + FIRE_DELAY_TIER_11) lever_delay = FIRE_DELAY_TIER_3 - accuracy_mult = BASE_ACCURACY_MULT + HIT_ACCURACY_MULT_TIER_5 + accuracy_mult = BASE_ACCURACY_MULT + HIT_ACCURACY_MULT_TIER_2 accuracy_mult_unwielded = BASE_ACCURACY_MULT - HIT_ACCURACY_MULT_TIER_10 scatter = SCATTER_AMOUNT_TIER_8 burst_scatter_mult = 0 diff --git a/code/modules/projectiles/guns/rifles.dm b/code/modules/projectiles/guns/rifles.dm index ad85220400fb..44d6ef845b94 100644 --- a/code/modules/projectiles/guns/rifles.dm +++ b/code/modules/projectiles/guns/rifles.dm @@ -557,6 +557,7 @@ //---ability actions--\\ /datum/action/item_action/m46c/action_activate() + . = ..() var/obj/item/weapon/gun/rifle/m46c/protag_gun = holder_item if(!ishuman(owner)) return @@ -1227,6 +1228,7 @@ fire_sound = 'sound/weapons/gun_hpr.ogg' aim_slowdown = SLOWDOWN_ADS_LMG current_mag = /obj/item/ammo_magazine/rifle/lmg + starting_attachment_types = list(/obj/item/attachable/bipod) attachable_allowed = list( /obj/item/attachable/suppressor, /obj/item/attachable/reddot, diff --git a/code/modules/projectiles/guns/shotguns.dm b/code/modules/projectiles/guns/shotguns.dm index b1b3bb3c2ab4..a0bb3f8f852c 100644 --- a/code/modules/projectiles/guns/shotguns.dm +++ b/code/modules/projectiles/guns/shotguns.dm @@ -838,6 +838,7 @@ can cause issues with ammo types getting mixed up during the burst. return TRUE /datum/action/item_action/specialist/twobore_brace/action_activate() + . = ..() var/obj/item/weapon/gun/shotgun/double/twobore/G = holder_item if(G.braced) return diff --git a/code/modules/projectiles/guns/smartgun.dm b/code/modules/projectiles/guns/smartgun.dm index e5c9fff3a126..7c628463b1ef 100644 --- a/code/modules/projectiles/guns/smartgun.dm +++ b/code/modules/projectiles/guns/smartgun.dm @@ -178,6 +178,7 @@ //---ability actions--\\ /datum/action/item_action/smartgun/action_activate() + . = ..() var/obj/item/weapon/gun/smartgun/G = holder_item if(!ishuman(owner)) return @@ -595,6 +596,7 @@ // ID lock action \\ /datum/action/item_action/co_sg/action_activate() + . = ..() var/obj/item/weapon/gun/smartgun/co/protag_gun = holder_item if(!ishuman(owner)) return diff --git a/code/modules/projectiles/guns/smgs.dm b/code/modules/projectiles/guns/smgs.dm index 69fd5d968750..466a09612c54 100644 --- a/code/modules/projectiles/guns/smgs.dm +++ b/code/modules/projectiles/guns/smgs.dm @@ -168,7 +168,8 @@ /obj/item/attachable/lasersight, // Under /obj/item/attachable/gyro, /obj/item/attachable/bipod, - /obj/item/attachable/burstfire_assembly + /obj/item/attachable/burstfire_assembly, + /obj/item/attachable/attached_gun/grenade/m203, ) flags_gun_features = GUN_CAN_POINTBLANK|GUN_ANTIQUE @@ -192,6 +193,13 @@ damage_mult = BASE_BULLET_DAMAGE_MULT + BULLET_DAMAGE_MULT_TIER_4 recoil_unwielded = RECOIL_AMOUNT_TIER_5 +/obj/item/weapon/gun/smg/mp5/Initialize(mapload, spawn_empty) + . = ..() + if(prob(10)) + var/obj/item/attachable/attached_gun/grenade/m203/UGL = new(src) + UGL.Attach(src) + update_attachable(UGL.slot) + //------------------------------------------------------- //MP27, based on the MP27, based on the M7. diff --git a/code/modules/projectiles/guns/specialist/launcher/grenade_launcher.dm b/code/modules/projectiles/guns/specialist/launcher/grenade_launcher.dm index e2643c580a16..06ac5428bfc6 100644 --- a/code/modules/projectiles/guns/specialist/launcher/grenade_launcher.dm +++ b/code/modules/projectiles/guns/specialist/launcher/grenade_launcher.dm @@ -222,6 +222,7 @@ update_icon() /datum/action/item_action/toggle_firing_level/action_activate() + . = ..() var/obj/item/weapon/gun/launcher/grenade/G = holder_item if(!ishuman(owner)) return diff --git a/code/modules/projectiles/guns/specialist/sniper.dm b/code/modules/projectiles/guns/specialist/sniper.dm index b40477a8a460..b400350e415b 100644 --- a/code/modules/projectiles/guns/specialist/sniper.dm +++ b/code/modules/projectiles/guns/specialist/sniper.dm @@ -62,6 +62,7 @@ ACTIONS SPECIALSIT SNIPER CAN TAKE */ /datum/action/item_action/specialist/aimed_shot/action_activate() + . = ..() if(!ishuman(owner)) return var/mob/living/carbon/human/H = owner @@ -276,6 +277,7 @@ return TRUE /datum/action/item_action/specialist/toggle_laser/action_activate() + . = ..() var/obj/item/weapon/gun/rifle/sniper/sniper_rifle = holder_item if(owner.get_held_item() != sniper_rifle) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 0e335aa81da3..d91e2ca47c1a 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -841,8 +841,8 @@ //mobs use get_projectile_hit_chance instead of get_projectile_hit_boolean /mob/living/proc/get_projectile_hit_chance(obj/projectile/P) - if((body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_NESTED)) && src != P.original) - return FALSE // Snowflake check for xeno nests, because we want bullets to fly through even though they're standing in it + if((body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_NO_STRAY)) && src != P.original) + return FALSE var/ammo_flags = P.ammo.flags_ammo_behavior | P.projectile_override_flags if(ammo_flags & AMMO_XENO) if((status_flags & XENO_HOST) && HAS_TRAIT(src, TRAIT_NESTED)) diff --git a/code/modules/reagents/Chemistry-Generator.dm b/code/modules/reagents/Chemistry-Generator.dm index 79efe2ef4453..813e0d9686bd 100644 --- a/code/modules/reagents/Chemistry-Generator.dm +++ b/code/modules/reagents/Chemistry-Generator.dm @@ -319,33 +319,6 @@ //*****************************************************************************************************/ /datum/reagent/proc/insert_property(property, level) - //The list below defines what properties should override each other. - var/list/conflicting_properties = list( PROPERTY_NUTRITIOUS = PROPERTY_HEMORRAGING, PROPERTY_NUTRITIOUS = PROPERTY_HEMOLYTIC, PROPERTY_TOXIC = PROPERTY_ANTITOXIC,\ - PROPERTY_CORROSIVE = PROPERTY_ANTICORROSIVE, PROPERTY_BIOCIDIC = PROPERTY_NEOGENETIC, PROPERTY_HYPERTHERMIC = PROPERTY_HYPOTHERMIC,\ - PROPERTY_NUTRITIOUS = PROPERTY_KETOGENIC, PROPERTY_PAINING = PROPERTY_PAINKILLING, PROPERTY_HALLUCINOGENIC = PROPERTY_ANTIHALLUCINOGENIC,\ - PROPERTY_HEPATOTOXIC = PROPERTY_HEPATOPEUTIC, PROPERTY_NEPHROTOXIC = PROPERTY_NEPHROPEUTIC, PROPERTY_PNEUMOTOXIC = PROPERTY_PNEUMOPEUTIC,\ - PROPERTY_OCULOTOXIC = PROPERTY_OCULOPEUTIC, PROPERTY_CARDIOTOXIC = PROPERTY_CARDIOPEUTIC, PROPERTY_NEUROTOXIC = PROPERTY_NEUROPEUTIC,\ - PROPERTY_FLUXING = PROPERTY_REPAIRING, PROPERTY_RELAXING = PROPERTY_MUSCLESTIMULATING, PROPERTY_HEMOGENIC = PROPERTY_HEMOLYTIC,\ - PROPERTY_HEMOGENIC = PROPERTY_HEMORRAGING, PROPERTY_NUTRITIOUS = PROPERTY_EMETIC,\ - PROPERTY_HYPERGENETIC = PROPERTY_NEOGENETIC, PROPERTY_HYPERGENETIC = PROPERTY_HEPATOPEUTIC, PROPERTY_HYPERGENETIC = PROPERTY_NEPHROPEUTIC,\ - PROPERTY_HYPERGENETIC = PROPERTY_PNEUMOPEUTIC, PROPERTY_HYPERGENETIC = PROPERTY_OCULOPEUTIC, PROPERTY_HYPERGENETIC = PROPERTY_CARDIOPEUTIC,\ - PROPERTY_HYPERGENETIC = PROPERTY_NEUROPEUTIC, PROPERTY_ADDICTIVE = PROPERTY_ANTIADDICTIVE, PROPERTY_NEUROSHIELDING = PROPERTY_NEUROTOXIC,\ - PROPERTY_HYPOMETABOLIC = PROPERTY_HYPERMETABOLIC, PROPERTY_HYPERTHROTTLING = PROPERTY_NEUROINHIBITING, - PROPERTY_FOCUSING = PROPERTY_NERVESTIMULATING, PROPERTY_THERMOSTABILIZING = PROPERTY_HYPERTHERMIC, PROPERTY_THERMOSTABILIZING = PROPERTY_HYPOTHERMIC, - PROPERTY_AIDING = PROPERTY_NEUROINHIBITING, PROPERTY_OXYGENATING = PROPERTY_HYPOXEMIC, PROPERTY_ANTICARCINOGENIC = PROPERTY_CARCINOGENIC, \ - PROPERTY_CIPHERING = PROPERTY_CIPHERING_PREDATOR, PROPERTY_TRANSFORMATIVE = PROPERTY_ANTITOXIC, PROPERTY_MUSCLESTIMULATING = PROPERTY_NERVESTIMULATING) - //The list below defines which properties should be combined into a combo property - var/list/combining_properties = list( PROPERTY_DEFIBRILLATING = list(PROPERTY_MUSCLESTIMULATING, PROPERTY_CARDIOPEUTIC),\ - PROPERTY_THANATOMETABOL = list(PROPERTY_HYPOXEMIC, PROPERTY_CRYOMETABOLIZING, PROPERTY_NEUROCRYOGENIC),\ - PROPERTY_HYPERDENSIFICATING = list(PROPERTY_MUSCLESTIMULATING, PROPERTY_BONEMENDING, PROPERTY_CARCINOGENIC),\ - PROPERTY_HYPERTHROTTLING = list(PROPERTY_PSYCHOSTIMULATING, PROPERTY_HALLUCINOGENIC),\ - PROPERTY_NEUROSHIELDING = list(PROPERTY_ALCOHOLIC, PROPERTY_BALDING),\ - PROPERTY_ANTIADDICTIVE = list(PROPERTY_PSYCHOSTIMULATING, PROPERTY_ANTIHALLUCINOGENIC),\ - PROPERTY_ADDICTIVE = list(PROPERTY_PSYCHOSTIMULATING, PROPERTY_NEUROTOXIC),\ - PROPERTY_CIPHERING_PREDATOR = list(PROPERTY_CIPHERING, PROPERTY_CROSSMETABOLIZING),\ - PROPERTY_FIRE_PENETRATING = list(PROPERTY_OXYGENATING, PROPERTY_VISCOUS),\ - PROPERTY_BONEMENDING = list(PROPERTY_HYPERDENSIFICATING, PROPERTY_NUTRITIOUS),\ - PROPERTY_ENCEPHALOPHRASIVE = list(PROPERTY_NERVESTIMULATING, PROPERTY_PSYCHOSTIMULATING)) var/datum/chem_property/match var/datum/chem_property/initial_property for(var/datum/chem_property/P in properties) @@ -353,8 +326,8 @@ match = P else //Handle properties that combine - for(var/C in combining_properties) - var/list/combo = combining_properties[C] + for(var/C in GLOB.combining_properties) + var/list/combo = GLOB.combining_properties[C] if(!combo.Find(property) || !combo.Find(P.name)) continue var/pieces = 0 @@ -372,11 +345,11 @@ LAZYREMOVE(properties, R) break //Handle properties that conflict - for(var/C in conflicting_properties) - if(property == C && P.name == conflicting_properties[C]) + for(var/C in GLOB.conflicting_properties) + if(property == C && P.name == GLOB.conflicting_properties[C]) match = P break - else if (property == conflicting_properties[C] && C == P.name) + else if (property == GLOB.conflicting_properties[C] && C == P.name) match = P break if(match) diff --git a/code/modules/reagents/chemical_research/Chemical-Research.dm b/code/modules/reagents/chemical_research/Chemical-Research.dm index 2050e7e8e607..a05bc132734d 100644 --- a/code/modules/reagents/chemical_research/Chemical-Research.dm +++ b/code/modules/reagents/chemical_research/Chemical-Research.dm @@ -87,8 +87,8 @@ GLOBAL_DATUM_INIT(chemical_data, /datum/chemical_data, new) if(P.category & PROPERTY_TYPE_UNADJUSTABLE || P.category & PROPERTY_TYPE_ANOMALOUS) continue property_names += P.name - for(var/name in research_property_data) - property_names -= name + for(var/datum/chem_property/property in research_property_data) + property_names -= property.name if(LAZYLEN(property_names)) has_new_properties = TRUE for(var/name in property_names) diff --git a/code/modules/reagents/chemistry_machinery/chem_simulator.dm b/code/modules/reagents/chemistry_machinery/chem_simulator.dm index 650b6cefbae9..13e051f5dc20 100644 --- a/code/modules/reagents/chemistry_machinery/chem_simulator.dm +++ b/code/modules/reagents/chemistry_machinery/chem_simulator.dm @@ -1,3 +1,4 @@ +//mode datums at the bottom. #define MODE_AMPLIFY 1 #define MODE_SUPPRESS 2 #define MODE_RELATE 3 @@ -40,7 +41,6 @@ var/ready = FALSE var/template_filter = PROPERTY_TYPE_ALL - var/complexity_editor = FALSE var/creation_template var/creation_complexity = list(CHEM_CLASS_COMMON, CHEM_CLASS_UNCOMMON, CHEM_CLASS_RARE) var/creation_name = "" @@ -62,29 +62,29 @@ ..() if(inoperable()) icon_state = "modifier_off" - SSnano.nanomanager.update_uis(src) // update all UIs attached to src /obj/structure/machinery/chem_simulator/attackby(obj/item/B, mob/living/user) if(!skillcheck(user, SKILL_RESEARCH, SKILL_RESEARCH_TRAINED)) to_chat(user, SPAN_WARNING("You have no idea how to use this.")) return if(istype(B, /obj/item/paper/research_notes)) - var/obj/item/paper/research_notes/N = B + var/obj/item/paper/research_notes/note = B if(!target || (mode == MODE_RELATE && !reference)) - B = N.convert_to_chem_report() + B = note.convert_to_chem_report() else to_chat(user, SPAN_WARNING("Chemical data already inserted.")) return if(istype(B, /obj/item/paper/research_report)) - if(!target) + var/obj/item/paper/research_report/note = B + if(!target && note.data) target = B ready = check_ready() - else if(mode == MODE_RELATE && !reference) - target_property = "" + else if(mode == MODE_RELATE && !reference && note.data) + target_property = null reference = B ready = check_ready() else - to_chat(user, SPAN_WARNING("Chemical data already inserted.")) + to_chat(user, SPAN_WARNING("Chemical data [note.data ? "is already inserted" : "is refused"]")) return else to_chat(user, SPAN_WARNING("[src] refuses [B].")) @@ -93,7 +93,6 @@ to_chat(user, SPAN_NOTICE("You insert [B] into [src].")) flick("[icon_state]_reading",src) update_costs() - SSnano.nanomanager.update_uis(src) // update all UIs attached to src /obj/structure/machinery/chem_simulator/attack_hand(mob/user as mob) if(inoperable()) @@ -101,256 +100,279 @@ if(!skillcheck(user, SKILL_RESEARCH, SKILL_RESEARCH_TRAINED)) to_chat(user, SPAN_WARNING("You have no idea how to use this.")) return - ui_interact(user) - -/obj/structure/machinery/chem_simulator/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) - var/list/data = list( - "rsc_credits" = GLOB.chemical_data.rsc_credits, - "target" = target, - "reference" = reference, - "mode" = mode, - "complexity_editor" = complexity_editor, - "property_costs" = property_costs, - "simulating" = simulating, - "status_bar" = status_bar, - "ready" = ready, - "od_lvl" = new_od_level, - "recipe_target" = recipe_target, - "recipe_targets" = list(), - "property_codings" = list() - ) - - if(simulating == SIMULATION_STAGE_FINAL) - for(var/reagent_id in recipe_targets) - var/datum/reagent/R = GLOB.chemical_reagents_list[reagent_id] - var/list/id_name[0] - id_name["[R.id]"] = R.name - data["recipe_targets"] += id_name + tgui_interact(user) - if(mode == MODE_CREATE) - data["creation_name"] = creation_name - data["creation_cost"] = creation_cost - data["complexity"] = complexity_to_string_list() - - //List of all available properties - data["property_data_list"] = list() - for(var/datum/chem_property/P in GLOB.chemical_data.research_property_data) - data["property_codings"][P.name] = P.code - if(template_filter && !HAS_FLAG(P.category, template_filter)) - continue - data["property_data_list"][P.name] = P.level - data["property_data_list"] = sortAssoc(data["property_data_list"]) - //List of enabled properties - data["target_property_list"] = list() - for(var/datum/chem_property/P in creation_template) - data["target_property_list"][P.name] = P.level - if(template_filter && !HAS_FLAG(P.category, template_filter)) - continue - //Override the editor level with the enabled property level - data["property_data_list"][P.name] = P.level - - data["template_filter"] = list( - "MED" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_MEDICINE), PROPERTY_TYPE_MEDICINE), - "TOX" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_TOXICANT), PROPERTY_TYPE_TOXICANT), - "STI" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_STIMULANT), PROPERTY_TYPE_STIMULANT), - "REA" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_REACTANT), PROPERTY_TYPE_REACTANT), - "IRR" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_IRRITANT), PROPERTY_TYPE_IRRITANT), - "MET" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_METABOLITE), PROPERTY_TYPE_METABOLITE) - ) - - else if(target && target.data && target.completed) - data["target_property_list"] = target.data.properties_to_assoc() - for(var/datum/chem_property/P in target.data.properties) - data["property_codings"][P.name] = P.code - - if(reference && reference.data && reference.completed) - data["reference_property_list"] = reference.data.properties_to_assoc() - for(var/datum/chem_property/P in reference.data.properties) - data["property_codings"][P.name] = P.code - - if(target_property) - data["target_property"] = target_property.name - data["target_info"] = target_property.description - data["target_categories"] = target_property.categories_to_string() - else - data["target_info"] = "" - - if(reference_property) - data["reference_property"] = reference_property.name - data["reference_info"] = reference_property.description - data["reference_categories"] = reference_property.categories_to_string() - else - data["reference_info"] = "" - - ui = SSnano.nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) +/obj/structure/machinery/chem_simulator/tgui_interact(mob/user, datum/tgui/ui) //death to the chem simulator! All Hail the new chem simulator! + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "chem_simulator.tmpl", "Synthesis Simulator", 800, 550) - ui.set_initial_data(data) + ui = new(user, src, "ChemSimulator", "Chemical Simulator") ui.open() -/obj/structure/machinery/chem_simulator/Topic(href, href_list) +/obj/structure/machinery/chem_simulator/ui_data(mob/user) . = ..() - if(.) - return - if(inoperable() || !ishuman(usr)) - return - var/mob/living/carbon/human/user = usr - if(user.stat || user.is_mob_restrained() || !in_range(src, user)) - return + var/list/data = list() + data["status"] = status_bar + ready = check_ready() + data["is_ready"] = ready + data["can_simulate"] = (ready && simulating == SIMULATION_STAGE_OFF) + data["can_eject_target"] = ((target ? TRUE : FALSE) && simulating == SIMULATION_STAGE_OFF) + data["can_eject_reference"] = ((reference ? TRUE : FALSE) && simulating == SIMULATION_STAGE_OFF) + data["is_picking_recipe"] = (simulating == SIMULATION_STAGE_FINAL && mode != MODE_CREATE) + data["lock_control"] = (simulating != SIMULATION_STAGE_OFF) + data["can_cancel_simulation"] = (simulating <= SIMULATION_STAGE_WAIT) + data["estimated_cost"] = (mode == MODE_CREATE ? creation_cost : (!target_property ? "NULL" : property_costs[target_property.name])) + calculate_new_od_level() + data["od_level"] = new_od_level + data["chemical_name"] = (mode == MODE_CREATE ? (creation_name == "" ? "NAME NOT SET" : creation_name) : (isnull(target) ? "CHEMICAL DATA NOT INSERTED" : target.data.name)) + data["reference_name"] = (isnull(reference) ? "CHEMICAL DATA NOT INSERTED" : reference.data.name) if(mode == MODE_CREATE && GLOB.chemical_data.has_new_properties) update_costs() - if(href_list["simulate"] && ready) - simulating = SIMULATION_STAGE_BEGIN - status_bar = "COMMENCING SIMULATION" - icon_state = "modifier_running" - recipe_targets = list() //reset - start_processing() - if(mode == MODE_CREATE) - msg_admin_niche("[key_name(user)] has created the chemical: [creation_name]") - else if(href_list["ejectT"]) - if(target) - if(!user.put_in_active_hand(target)) - target.forceMove(loc) - target = null - target_property = null - stop_processing() - simulating = SIMULATION_STAGE_OFF - flick("[icon_state]_printing",src) - else if(href_list["ejectR"]) - if(reference) - if(!user.put_in_active_hand(reference)) - reference.forceMove(loc) - reference = null - reference_property = null - stop_processing() - simulating = SIMULATION_STAGE_OFF - flick("[icon_state]_printing",src) - else if(href_list["set_mode"]) - if(mode == MODE_CREATE) //for when you set the mode away from MODE_CREATE - target_property = null - reference_property = null - complexity_editor = FALSE - switch(href_list["set_mode"]) - if("amp") - mode = MODE_AMPLIFY - if("sup") - mode = MODE_SUPPRESS - if("rel") - mode = MODE_RELATE - if("cre") - mode = MODE_CREATE - target_property = null - reference_property = null - calculate_new_od_level() - if(mode == MODE_CREATE) - calculate_creation_cost() - update_costs() - else if(href_list["set_target"]) - if(simulating) - return - if(mode == MODE_CREATE) - var/target_name = href_list["set_target"] - for(var/datum/chem_property/P in GLOB.chemical_data.research_property_data) - if(P.name == target_name) - if(target_property && target_property.name == target_name) - //Toggle the property - if(LAZYISIN(creation_template, target_property)) - target_property.level = 0 - LAZYREMOVE(creation_template, target_property) - else - target_property.level = 1 - LAZYADD(creation_template, target_property) - calculate_creation_cost() - else - target_property = P + if(simulating == SIMULATION_STAGE_FINAL) + for(var/reagent_id in recipe_targets) + var/datum/reagent/recipe_option = GLOB.chemical_reagents_list[reagent_id] + data["reagent_option_data"] += list(list( + "id" = recipe_option.id, + "name" = recipe_option.name, + )) + if(target && length(target?.data?.properties)) + for(var/datum/chem_property/target_property_data in target.data.properties) + var/is_locked = FALSE + var/conflicting_tooltip = null + if(!isnull(reference_property)) + if(LAZYACCESS(GLOB.conflicting_properties, reference_property.name) == target_property_data.name || LAZYACCESS(GLOB.conflicting_properties, target_property_data.name) == reference_property.name ) + is_locked = TRUE + conflicting_tooltip = "This property conflicts with the selected reference property!" + data["target_data"] += list(list( + "code" = target_property_data.code, + "level" = target_property_data.level, + "name" = target_property_data.name, + "desc" = target_property_data.description, + "cost" = property_costs[target_property_data.name], + "is_locked" = is_locked, + "tooltip" = conflicting_tooltip, + )) + else + data["target_data"] = null + + if(reference && length(reference?.data?.properties)) + for(var/datum/chem_property/reference_property_data in reference.data.properties) + var/is_locked = FALSE + var/conflicting_tooltip = null + if(!isnull(target_property)) + if(LAZYACCESS(GLOB.conflicting_properties, target_property.name) == reference_property_data.name || LAZYACCESS(GLOB.conflicting_properties, reference_property_data.name) == target_property.name ) + is_locked = TRUE + conflicting_tooltip = "This property conflicts with the selected target property!" + data["reference_data"] += list(list( + "code" = reference_property_data.code, + "level" = reference_property_data.level, + "name" = capitalize_first_letters(reference_property_data.name), + "desc" = reference_property_data.description, + "cost" = property_costs[reference_property_data.name], + "is_locked" = is_locked, + "tooltip" = conflicting_tooltip, + )) + else + data["reference_data"] = null + data["template_filters"] = list( + "MED" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_MEDICINE), PROPERTY_TYPE_MEDICINE), + "TOX" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_TOXICANT), PROPERTY_TYPE_TOXICANT), + "STI" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_STIMULANT), PROPERTY_TYPE_STIMULANT), + "REA" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_REACTANT), PROPERTY_TYPE_REACTANT), + "IRR" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_IRRITANT), PROPERTY_TYPE_IRRITANT), + "MET" = list(HAS_FLAG(template_filter, PROPERTY_TYPE_METABOLITE), PROPERTY_TYPE_METABOLITE) + ) + if(mode == MODE_CREATE) + for(var/datum/chem_property/known_properties in GLOB.chemical_data.research_property_data) + var/datum/chem_property/template_property + var/is_locked = FALSE + var/conflicting_tooltip = null + if(template_filter && !HAS_FLAG(known_properties.category, template_filter)) + continue + for(var/template in creation_template) + template_property = template + if(LAZYACCESS(GLOB.conflicting_properties, template_property.name) == known_properties.name || LAZYACCESS(GLOB.conflicting_properties, known_properties.name) == template_property.name) + is_locked = TRUE + conflicting_tooltip = "This property conflicts with [template_property.code]!" + if(template_property.code == known_properties.code) break - else - target_property = target.data.get_property(href_list["set_target"]) - calculate_new_od_level() - if(simulating) + template_property = null + + data["known_properties"] += list(list( + "code" = known_properties.code, + "level" = (isnull(template_property) ? 0 : template_property.level) , + "name" = capitalize_first_letters(known_properties.name), + "desc" = known_properties.description, + "is_enabled" = LAZYISIN(creation_template, known_properties), + "is_locked" = is_locked, + "conflicting_tooltip" = conflicting_tooltip, + )) + if(!length(data["known_properties"])) + data["known_properties"] = null + data["complexity_list"] += complexity_to_string_list() + + return data + +/obj/structure/machinery/chem_simulator/ui_static_data(mob/user) + . = ..() + var/list/static_data = list() + for(var/modes in subtypesof(/datum/chemical_simulator_modes)) + var/datum/chemical_simulator_modes/modes_datum = modes + static_data["mode_data"] += list(list( + "name" = modes_datum.name, + "desc" = modes_datum.desc, + "mode_id" = modes_datum.mode_id, + "icon_type" = modes_datum.icon_type + )) + static_data["credits"] = GLOB.chemical_data.rsc_credits + return static_data + +/obj/structure/machinery/chem_simulator/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + switch(action) + if("change_mode") + mode = params["mode_id"] + update_costs() + if("eject_target") + if(target) + if(!usr.put_in_active_hand(target)) + target.forceMove(loc) + target = null + target_property = null stop_processing() - icon_state = "modifier" simulating = SIMULATION_STAGE_OFF - else if(href_list["set_reference"]) - reference_property = reference.data.get_property(href_list["set_reference"]) - if(simulating) + flick("[icon_state]_printing",src) + if("eject_reference") + if(reference) + if(!usr.put_in_active_hand(reference)) + reference.forceMove(loc) + reference = null + reference_property = null + stop_processing() + flick("[icon_state]_printing",src) + if("select_target_property") + if(mode != MODE_CREATE) + if(!target) + return + for(var/datum/chem_property/target_prop in target.data.properties) + if(target_prop.code != params["property_code"]) + continue + target_property = target_prop + if(!target_property) + to_chat(usr, SPAN_WARNING("The [src] makes a suspicious wail.")) + return + if("select_reference_property") + if(!reference) + return + for(var/datum/chem_property/reference_prop in reference.data.properties) + if(reference_prop.code != params["property_code"]) + continue + reference_property = reference_prop + if(!reference_property) + to_chat(usr, SPAN_WARNING("The [src] makes a suspicious wail.")) + return + if("simulate") + if(!ready) + return + simulating = SIMULATION_STAGE_BEGIN + status_bar = "COMMENCING SIMULATION" + icon_state = "modifier_running" + recipe_targets = list() //reset + start_processing() + if(mode == MODE_CREATE) + msg_admin_niche("[key_name(usr)] has created the chemical: [creation_name]") + if("submit_recipe_pick") + if(recipe_target) + return + if(params["reagent_picked"] in recipe_targets) + recipe_target = params["reagent_picked"] + finalize_simulation(chem_cache) + recipe_target = null + if("cancel_simulation") stop_processing() icon_state = "modifier" simulating = SIMULATION_STAGE_OFF - update_costs() - else if(href_list["set_recipe_target"]) - recipe_target = href_list["set_recipe_target"] - else if(href_list["stop_simulation"]) - stop_processing() - icon_state = "modifier" - simulating = SIMULATION_STAGE_OFF - else if(href_list["finalize_simulation"] && recipe_target) - finalize_simulation(chem_cache) - //Template creation editor - else if(href_list["set_name"]) - var/newname = input("Set name for template (2-20 characters)","[src]") as text - newname = reject_bad_name(newname, TRUE, 20, FALSE) - if(isnull(newname)) - to_chat(user, "Bad name.") - else if(GLOB.chemical_reagents_list[newname]) - to_chat(user, "Name already taken.") - else - creation_name = newname - else if(href_list["set_level"] && target_property) - var/level_to_set = 1 - if(GLOB.chemical_data.clearance_level <= 2) - level_to_set = tgui_input_list(usr, "Set target level for [target_property.name]:","[src]", list(1,2,3,4)) - else if(GLOB.chemical_data.clearance_level <= 4) - level_to_set = tgui_input_list(usr, "Set target level for [target_property.name]:","[src]", list(1,2,3,4,5,6,7,8)) - else - level_to_set = tgui_input_list(usr, "Set target level for [target_property.name]:","[src]", list(1,2,3,4,5,6,7,8,9,10)) - if(!level_to_set) - return - - target_property.level = level_to_set - if(target_property.max_level && target_property.level > target_property.max_level) - target_property.level = target_property.max_level - to_chat(user, "Max level for [target_property.name] is [target_property.max_level].") - calculate_creation_cost() - else if(href_list["set_od"]) - var/od_to_set = tgui_input_list(usr, "Set new OD:", "[src]", list(5,10,15,20,25,30,35,40,45,50,55,60)) - if(!od_to_set) - return - new_od_level = od_to_set - creation_od_level = od_to_set - calculate_creation_cost() - else if(href_list["set_filter"]) - if(href_list["set_filter"] == "ALL") - template_filter = 0 - else - var/flag_value = text2num(href_list["config_value"]) + if("toggle_flag") + var/flag_value = params["flag_id"] if(template_filter & flag_value) template_filter &= ~flag_value else template_filter |= flag_value - else if(href_list["toggle_complexity_editor"]) - complexity_editor = !complexity_editor - else if(href_list["set_complexity"]) - var/slot = text2num(href_list["set_complexity"]) - var/new_rarity = tgui_input_list(usr, "Set chemical rarity for complexity slot [slot]:","[src]", list("BASIC (+7)","COMMON (+4)","UNCOMMON (1)","RARE (-5)")) - if(!new_rarity) + if("select_create_property") + if(mode == MODE_CREATE) + if(target_property?.code == params["property_code"]) + if(LAZYISIN(creation_template, target_property)) + target_property.level = 0 + LAZYREMOVE(creation_template, target_property) + else + target_property.level = 1 + LAZYADD(creation_template, target_property) + else + for(var/datum/chem_property/known_prop in GLOB.chemical_data.research_property_data) + if(known_prop.code != params["property_code"]) + continue + target_property = known_prop + if(!target_property) + to_chat(usr, SPAN_WARNING("The [src] makes a suspicious wail.")) + return + calculate_creation_cost() + if("select_overdose") + if(simulating == SIMULATION_STAGE_OFF && mode == MODE_CREATE) + var/od_to_set = tgui_input_list(usr, "Set new OD:", "[src]", list(5,10,15,20,25,30,35,40,45,50,55,60)) + if(!od_to_set || simulating != SIMULATION_STAGE_OFF) + return + creation_od_level = od_to_set + calculate_new_od_level() + calculate_creation_cost() + if("change_name") + if(simulating == SIMULATION_STAGE_OFF && mode == MODE_CREATE) + var/newname = input("Set name for template (2-20 characters)","[src]") as text + newname = reject_bad_name(newname, TRUE, 20, FALSE) + if(isnull(newname)) + to_chat(usr, SPAN_WARNING("This name is not permited.")) + else if(GLOB.chemical_reagents_list[newname]) + to_chat(usr, SPAN_WARNING("This name is already occupied")) + else + creation_name = newname + if("change_create_target_level") + var/level_to_set = 1 + if(GLOB.chemical_data.clearance_level <= 2) + level_to_set = tgui_input_list(usr, "Set target level for [target_property.name]:","[src]", list(1,2,3,4)) + else if(GLOB.chemical_data.clearance_level <= 4) + level_to_set = tgui_input_list(usr, "Set target level for [target_property.name]:","[src]", list(1,2,3,4,5,6,7,8)) + else + level_to_set = tgui_input_list(usr, "Set target level for [target_property.name]:","[src]", list(1,2,3,4,5,6,7,8,9,10)) + if(!level_to_set) + return + if(!LAZYISIN(creation_template, target_property)) + LAZYADD(creation_template, target_property) + target_property.level = level_to_set + if(target_property.max_level && target_property.level > target_property.max_level) + target_property.level = target_property.max_level + to_chat(usr, "Max level for [target_property.name] is [target_property.max_level].") + calculate_creation_cost() + if("change_complexity") + var/slot = params["complexity_slot"] + var/new_rarity = tgui_input_list(usr, "Set chemical rarity for complexity slot [slot]:", "[src]", list("BASIC (+7)", "COMMON (+4)", "UNCOMMON (1)", "RARE (-5)")) + if(!new_rarity || simulating != SIMULATION_STAGE_OFF) + return + switch(new_rarity) + if("BASIC (+7)") + creation_complexity[slot] = CHEM_CLASS_BASIC + if("COMMON (+4)") + creation_complexity[slot] = CHEM_CLASS_COMMON + if("UNCOMMON (1)") + creation_complexity[slot] = CHEM_CLASS_UNCOMMON + if("RARE (-5)") + creation_complexity[slot] = CHEM_CLASS_RARE + calculate_creation_cost() + if("keyboard_sound")//only exists to give sound + playsound(loc, pick('sound/machines/computer_typing1.ogg','sound/machines/computer_typing2.ogg','sound/machines/computer_typing3.ogg'), 5, 1) return - - switch(new_rarity) - if("BASIC (+7)") - creation_complexity[slot] = CHEM_CLASS_BASIC - if("COMMON (+4)") - creation_complexity[slot] = CHEM_CLASS_COMMON - if("UNCOMMON (1)") - creation_complexity[slot] = CHEM_CLASS_UNCOMMON - if("RARE (-5)") - creation_complexity[slot] = CHEM_CLASS_RARE - calculate_creation_cost() - ready = check_ready() playsound(loc, pick('sound/machines/computer_typing1.ogg','sound/machines/computer_typing2.ogg','sound/machines/computer_typing3.ogg'), 5, 1) - SSnano.nanomanager.update_uis(src) /obj/structure/machinery/chem_simulator/process() if(inoperable()) @@ -534,24 +556,34 @@ if(target_property.level >= GLOB.chemical_data.clearance_level*TECHTREE_LEVEL_MULTIPLIER + 2 && GLOB.chemical_data.clearance_level < 5) status_bar = "CLEARANCE INSUFFICIENT FOR AMPLIFICATION" return FALSE + else + status_bar = "TARGET NOT SELECTED" + return FALSE if(target && length(target.data.properties) < 2) status_bar = "TARGET COMPLEXITY IMPROPER FOR RELATION" return FALSE - if(reference && target) - if(!reference.completed) - status_bar = "INCOMPLETE DATA DETECTED IN REFERENCE" - return FALSE - if(reference_property) - if(target.data.get_property(reference_property.name)) - status_bar = "REFERENCE PROPERTY ALREADY IN TARGET" + if(mode == MODE_RELATE && isnull(reference)) + status_bar = "NO REFERENCE DATA DETECTED" + return FALSE + if(mode == MODE_RELATE) + if(reference && target) + if(!reference.completed) + status_bar = "INCOMPLETE DATA DETECTED IN REFERENCE" return FALSE - if(target_property) - if(target_property.level != reference_property.level) - status_bar = "REFERENCE AND TARGET PROPERTY MUST BE OF EQUAL LEVELS" - return FALSE - if(reference_property.category & PROPERTY_TYPE_UNADJUSTABLE) - status_bar = "REFERENCE PROPERTY CAN NOT BE SIMULATED" + if(reference_property) + if(target.data.get_property(reference_property.name)) + status_bar = "REFERENCE PROPERTY ALREADY IN TARGET" return FALSE + if(target_property) + if(target_property.level != reference_property.level) + status_bar = "REFERENCE AND TARGET PROPERTY MUST BE OF EQUAL LEVELS" + return FALSE + if(reference_property.category & PROPERTY_TYPE_UNADJUSTABLE) + status_bar = "REFERENCE PROPERTY CAN NOT BE SIMULATED" + return FALSE + else + status_bar = "REFERENCE PROPERTY NOT SELECTED" + return FALSE if(mode == MODE_CREATE) if(!LAZYLEN(creation_template)) status_bar = "TEMPLATE IS EMPTY" @@ -565,7 +597,8 @@ else if(!target) status_bar = "NO TARGET INSERTED" return FALSE - status_bar = "READY" + if(simulating == SIMULATION_STAGE_OFF) + status_bar = "READY" return TRUE /obj/structure/machinery/chem_simulator/proc/print(id, is_new) @@ -714,6 +747,36 @@ status_bar = "SIMULATION COMPLETE" print(C.id, TRUE) +/datum/chemical_simulator_modes + var/name + var/desc + var/mode_id + var/icon_type + +/datum/chemical_simulator_modes/create + name = "CREATE" + desc = "Create a new custom chemical from the known properties discovered earlier." + mode_id = MODE_CREATE + icon_type = "bolt" + +/datum/chemical_simulator_modes/supress + name = "SUPRESS" + desc = "Supress one level in the choosen property. This operation lowers the OD level." + mode_id = MODE_SUPPRESS + icon_type = "square-minus" + +/datum/chemical_simulator_modes/amplify + name = "AMPLIFY" + desc = "Amplify one level in the choosen property. This operation lowers the OD level." + mode_id = MODE_AMPLIFY + icon_type = "square-plus" + +/datum/chemical_simulator_modes/relate + name = "RELATE" + desc = "Use the reference chemical to replace one choosen property in the target chemical. The target and reference target property level must be equal, This operation lowers the OD level." + mode_id = MODE_RELATE + icon_type = "repeat" + #undef SIMULATION_FAILURE #undef SIMULATION_STAGE_OFF #undef SIMULATION_STAGE_FINAL diff --git a/code/modules/reagents/chemistry_properties/prop_negative.dm b/code/modules/reagents/chemistry_properties/prop_negative.dm index 783584102182..e7d40c3da31f 100644 --- a/code/modules/reagents/chemistry_properties/prop_negative.dm +++ b/code/modules/reagents/chemistry_properties/prop_negative.dm @@ -137,11 +137,9 @@ if(affecting) if(affecting.take_damage(4, 2)) H.UpdateDamageIcon() - if(prob(meltprob)) //Applies disfigurement + if(prob(meltprob)) if(H.pain.feels_pain) H.emote("scream") - H.status_flags |= DISFIGURED - H.name = H.get_visible_name() else M.take_limb_damage(min(6, volume)) return diff --git a/code/modules/reagents/chemistry_properties/prop_positive.dm b/code/modules/reagents/chemistry_properties/prop_positive.dm index 40867892afbd..051befa14fba 100644 --- a/code/modules/reagents/chemistry_properties/prop_positive.dm +++ b/code/modules/reagents/chemistry_properties/prop_positive.dm @@ -71,7 +71,7 @@ /datum/chem_property/positive/repairing name = PROPERTY_REPAIRING code = "REP" - description = "Repairs cybernetic organs by REDACTED." + description = "Repairs cybernetic organs by the use of REDACTED property of REDACTED element." rarity = PROPERTY_UNCOMMON category = PROPERTY_TYPE_MEDICINE value = 2 @@ -949,10 +949,6 @@ /datum/chem_property/positive/aiding/process(mob/living/M, potency = 1, delta_time) M.disabilities = 0 M.sdisabilities = 0 - M.status_flags &= ~DISFIGURED - if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.name = H.get_visible_name() /datum/chem_property/positive/aiding/process_overdose(mob/living/M, potency = 1, delta_time) M.confused = max(M.confused, 20 * potency) //Confusion and some toxins diff --git a/code/modules/shuttle/computer.dm b/code/modules/shuttle/computer.dm index 7608def18df1..0cbe3f7f476e 100644 --- a/code/modules/shuttle/computer.dm +++ b/code/modules/shuttle/computer.dm @@ -364,6 +364,8 @@ icon_state = "terminal" req_access = list() breakable = FALSE + unslashable = TRUE + unacidable = TRUE ///If true, the lifeboat is in the process of launching, and so the code will not allow another launch. var/launch_initiated = FALSE ///If true, the lifeboat is in the process of having the xeno override removed by the pilot. @@ -371,6 +373,9 @@ ///How long it takes to unlock the console var/remaining_time = 180 SECONDS +/obj/structure/machinery/computer/shuttle/lifeboat/ex_act(severity) + return + /obj/structure/machinery/computer/shuttle/lifeboat/attack_hand(mob/user) . = ..() var/obj/docking_port/mobile/crashable/lifeboat/lifeboat = SSshuttle.getShuttle(shuttleId) diff --git a/code/modules/shuttle/computers/dropship_computer.dm b/code/modules/shuttle/computers/dropship_computer.dm index 08a35b83071d..a28f65ce475d 100644 --- a/code/modules/shuttle/computers/dropship_computer.dm +++ b/code/modules/shuttle/computers/dropship_computer.dm @@ -314,7 +314,7 @@ var/original_evilution = hive.evolution_bonus hive.override_evilution(XENO_HIJACK_EVILUTION_BUFF, TRUE) if(hive.living_xeno_queen) - var/datum/action/xeno_action/onclick/grow_ovipositor/ovi_ability = get_xeno_action_by_type(hive.living_xeno_queen, /datum/action/xeno_action/onclick/grow_ovipositor) + var/datum/action/xeno_action/onclick/grow_ovipositor/ovi_ability = get_action(hive.living_xeno_queen, /datum/action/xeno_action/onclick/grow_ovipositor) ovi_ability.reduce_cooldown(ovi_ability.xeno_cooldown) addtimer(CALLBACK(hive, TYPE_PROC_REF(/datum/hive_status, override_evilution), original_evilution, FALSE), XENO_HIJACK_EVILUTION_TIME) diff --git a/code/modules/surgery/face.dm b/code/modules/surgery/face.dm deleted file mode 100644 index 7d13c0ed5675..000000000000 --- a/code/modules/surgery/face.dm +++ /dev/null @@ -1,174 +0,0 @@ -//Procedures in this file: Facial reconstruction surgery -////////////////////////////////////////////////////////////////// -// FACE SURGERY // -////////////////////////////////////////////////////////////////// - -/datum/surgery/face_fix - name = "Facial Reconstruction" - possible_locs = list("mouth") - invasiveness = list(SURGERY_DEPTH_SURFACE) - pain_reduction_required = PAIN_REDUCTION_HEAVY - required_surgery_skill = SKILL_SURGERY_TRAINED - steps = list( - /datum/surgery_step/facial_incision, - /datum/surgery_step/mend_vocals, - /datum/surgery_step/pull_skin, - /datum/surgery_step/cauterize/close_facial_incision, - ) - -/datum/surgery/face_fix/can_start(mob/user, mob/living/carbon/patient, obj/limb/L, obj/item/tool) - var/obj/limb/head/H = L - return H && H.disfigured - -//------------------------------------ - -/datum/surgery_step/facial_incision - name = "Make Facial Incision" - desc = "make facial incisions" - tools = SURGERY_TOOLS_INCISION - time = 4 SECONDS - -/datum/surgery_step/facial_incision/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_NOTICE("You start to cut open [target]'s face and neck with \the [tool]."), - SPAN_NOTICE("[user] starts to cut open your face and neck with \the [tool]."), - SPAN_NOTICE("[user] starts to cut open [target]'s face and neck with \the [tool].")) - - log_interact(user, target, "[key_name(user)] began to cut open [key_name(target)]'s face and neck with \the [tool].") - target.custom_pain("Your face is being cut apart!", 1) - -/datum/surgery_step/facial_incision/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_NOTICE("You finish opening incisions on [target]'s face and neck."), - SPAN_NOTICE("[user] finishes opening incisions on your face and neck."), - SPAN_NOTICE("[user] finishes opening incisions on [target]'s face and neck.")) - - target.incision_depths[target_zone] = SURGERY_DEPTH_SHALLOW - log_interact(user, target, "[key_name(user)] cut open [key_name(target)]'s face and neck with \the [tool].") - -/datum/surgery_step/facial_incision/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_DANGER("Your hand slips, slicing [target]'s throat wth \the [tool]!"), - SPAN_DANGER("[user]'s hand slips, slicing [target]'s throat wth \the [tool]!"), - SPAN_DANGER("[user]'s hand slips, slicing [target]'s throat wth \the [tool]!")) - - log_interact(user, target, "[key_name(user)] failed to cut open [key_name(target)]'s face and neck with \the [tool].") - - target.apply_damage(40, BRUTE, target_zone) - target.losebreath += 20 - user.add_blood(target.get_blood_color(), BLOOD_BODY|BLOOD_HANDS) - return FALSE - -//------------------------------------ - -/datum/surgery_step/mend_vocals - name = "Mend Vocal Cords" - desc = "mend the vocal cords" - tools = SURGERY_TOOLS_PINCH - time = 3 SECONDS - -/datum/surgery_step/mend_vocals/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_NOTICE("You start mending [target]'s vocal cords with \the [tool]."), - SPAN_NOTICE("[user] starts to mend your vocal cords with \the [tool]."), - SPAN_NOTICE("[user] starts to mend [target]'s vocal cords with \the [tool].")) - - log_interact(user, target, "[key_name(user)] began to mend [key_name(target)]'s vocal cords with \the [tool].") - target.custom_pain("The insides of your throat are being pinched and pulled at!", 1) - -/datum/surgery_step/mend_vocals/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_NOTICE("You mend [target]'s vocal cords."), - SPAN_NOTICE("[user] mends your vocal cords."), - SPAN_NOTICE("[user] mends [target]'s vocal cords.")) - - log_interact(user, target, "[key_name(user)] mended [key_name(target)]'s vocal cords with \the [tool].") - -/datum/surgery_step/mend_vocals/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_WARNING("Your hand slips, clamping [user]'s trachea shut for a moment with \the [tool]!"), - SPAN_DANGER("[user]'s hand slips, clamping your trachea shut for a moment with \the [tool]!"), - SPAN_WARNING("[user]'s hand slips, clamping [target]'s trachea shut for a moment with \the [tool]!")) - - log_interact(user, target, "[key_name(user)] failed to mend [key_name(target)]'s vocal cords with \the [tool].") - - target.losebreath += 10 - return FALSE - -//------------------------------------ - -/datum/surgery_step/pull_skin - name = "Reconstruct Facial Features" - desc = "reconstruct the face" - tools = SURGERY_TOOLS_PRY_DELICATE - time = 3 SECONDS - -/datum/surgery_step/pull_skin/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_NOTICE("You start pulling the skin on [target]'s face back into shape with \the [tool]."), - SPAN_NOTICE("[user] starts to pull the skin on your face back into shape with \the [tool]."), - SPAN_NOTICE("[user] starts to pull the skin on [target]'s face back into shape with \the [tool].")) - - log_interact(user, target, "[key_name(user)] began to pull the skin on [key_name(target)]'s face back in place with \the [tool].") - target.custom_pain("Your face hurts!", 1) - -/datum/surgery_step/pull_skin/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_NOTICE("You reconstruct [target]'s facial features."), - SPAN_NOTICE("[user] reconstructs your facial features."), - SPAN_NOTICE("[user] reconstructs [target]'s facial features.")) - - log_interact(user, target, "[key_name(user)] pulled the skin on [key_name(target)]'s face back in place with \the [tool].") - -/datum/surgery_step/pull_skin/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_WARNING("Your hand slips, tearing skin on [target]'s face with \the [tool]!"), - SPAN_WARNING("[user]'s hand slips, tearing skin on your face with \the [tool]!"), - SPAN_WARNING("[user]'s hand slips, tearing skin on [target]'s face with \the [tool]!")) - - log_interact(user, target, "[key_name(user)] failed to pull the skin on [key_name(target)]'s face back in place with \the [tool].") - - target.apply_damage(10, BRUTE, target_zone) - return FALSE - -//------------------------------------ - -/datum/surgery_step/cauterize/close_facial_incision - name = "Close Facial Incisions" - desc = "close the facial incisions" - time = 5 SECONDS - -/datum/surgery_step/cauterize/close_facial_incision/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_NOTICE("You begin to cauterize the incisions on [target]'s face and neck with \the [tool]."), - SPAN_NOTICE("[user] begins to cauterize the incisions on your face and neck with \the [tool]."), - SPAN_NOTICE("[user] begins to cauterize the incisions on [target]'s face and neck with \the [tool].")) - - target.custom_pain("Your face is being burned!", 1) - - log_interact(user, target, "[key_name(user)] began to cauterize [key_name(target)]'s face and neck with \the [tool].") - -/datum/surgery_step/cauterize/close_facial_incision/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_NOTICE("You cauterize the incisions on [target]'s face and neck."), - SPAN_NOTICE("[user] cauterizes the incisions on your face and neck."), - SPAN_NOTICE("[user] cauterizes the incision on [target]'s face and neck.")) - - log_interact(user, target, "[key_name(user)] cauterized [key_name(target)]'s face and neck with \the [tool], ending [surgery].") - - target.incision_depths[target_zone] = SURGERY_DEPTH_SURFACE - surgery.affected_limb.remove_all_bleeding(TRUE) - var/obj/limb/head/H = surgery.affected_limb - H.disfigured = FALSE - H.owner.name = H.owner.get_visible_name() - -/datum/surgery_step/cauterize/close_facial_incision/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.affected_message(target, - SPAN_WARNING("Your hand slips, leaving a small burn on [target]'s face!"), - SPAN_WARNING("[user]'s hand slips, leaving a small burn on your face!"), - SPAN_WARNING("[user]'s hand slips, leaving a small burn on [target]'s face!")) - - log_interact(user, target, "[key_name(user)] failed to cauterize [key_name(target)]'s face and neck with \the [tool].") - - target.apply_damage(5, BURN, target_zone) - return FALSE diff --git a/code/modules/surgery/surgery_toggle.dm b/code/modules/surgery/surgery_toggle.dm index b9ca3ca93311..973d1c5b682f 100644 --- a/code/modules/surgery/surgery_toggle.dm +++ b/code/modules/surgery/surgery_toggle.dm @@ -18,6 +18,7 @@ // Called when the action is clicked on. /datum/action/surgery_toggle/action_activate() + . = ..() if(owner.mob_flags & SURGERY_MODE_ON) button.icon_state = "template" owner.mob_flags &= ~SURGERY_MODE_ON diff --git a/code/modules/vehicles/hardpoints/hardpoint_ammo/cupola_ammo.dm b/code/modules/vehicles/hardpoints/hardpoint_ammo/cupola_ammo.dm index cadb760bd644..7eecc7d04511 100644 --- a/code/modules/vehicles/hardpoints/hardpoint_ammo/cupola_ammo.dm +++ b/code/modules/vehicles/hardpoints/hardpoint_ammo/cupola_ammo.dm @@ -5,7 +5,7 @@ icon = 'icons/obj/items/weapons/guns/ammo_by_faction/uscm.dmi' icon_state = "cupola_1" w_class = SIZE_LARGE - default_ammo = /datum/ammo/bullet/smartgun + default_ammo = /datum/ammo/bullet/machinegun max_rounds = 500 gun_type = /obj/item/hardpoint/secondary/m56cupola diff --git a/code/modules/vehicles/hardpoints/hardpoint_ammo/primary_flamer_ammo.dm b/code/modules/vehicles/hardpoints/hardpoint_ammo/primary_flamer_ammo.dm index def6016f0759..a164b38383b8 100644 --- a/code/modules/vehicles/hardpoints/hardpoint_ammo/primary_flamer_ammo.dm +++ b/code/modules/vehicles/hardpoints/hardpoint_ammo/primary_flamer_ammo.dm @@ -1,7 +1,7 @@ /obj/item/ammo_magazine/hardpoint/primary_flamer name = "DRG-N Offensive Flamer Unit Fuel Tank" desc = "A primary armament flamethrower magazine." - caliber = "Napalm X" //correlates to flamer mags + caliber = "High-Combustion Napalm" //correlates to flamer mags icon_state = "drgn_flametank" w_class = SIZE_LARGE max_rounds = 60 diff --git a/code/modules/vehicles/hardpoints/primary/flamer.dm b/code/modules/vehicles/hardpoints/primary/flamer.dm index fce6e7f6a410..60a7979cd5fb 100644 --- a/code/modules/vehicles/hardpoints/primary/flamer.dm +++ b/code/modules/vehicles/hardpoints/primary/flamer.dm @@ -1,6 +1,6 @@ /obj/item/hardpoint/primary/flamer name = "\improper DRG-N Offensive Flamer Unit" - desc = "A primary weapon for the tank that spews fire everywhere." + desc = "A primary weapon for the tank that spews out high-combustion napalm in a wide radius. The fuel burns intensely and quickly, which allows for it to be used offensively by armoured vehicles." icon_state = "drgn_flamer" disp_icon = "tank" diff --git a/code/modules/vehicles/hardpoints/secondary/cupola.dm b/code/modules/vehicles/hardpoints/secondary/cupola.dm index a4b40c7dd3a1..70b9f9a4889f 100644 --- a/code/modules/vehicles/hardpoints/secondary/cupola.dm +++ b/code/modules/vehicles/hardpoints/secondary/cupola.dm @@ -28,9 +28,3 @@ burst_amount = 3 burst_delay = 0.3 SECONDS extra_delay = 0.6 SECONDS - -/obj/item/hardpoint/secondary/m56cupola/set_bullet_traits() - ..() - LAZYADD(traits_to_give, list( - BULLET_TRAIT_ENTRY(/datum/element/bullet_trait_iff) - )) diff --git a/colonialmarines.dme b/colonialmarines.dme index 9bfccac6a56e..54760dde8594 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -311,6 +311,7 @@ #include "code\controllers\subsystem\tracking.dm" #include "code\controllers\subsystem\vote.dm" #include "code\controllers\subsystem\weather.dm" +#include "code\controllers\subsystem\who.dm" #include "code\controllers\subsystem\x_evolution.dm" #include "code\controllers\subsystem\xeno.dm" #include "code\controllers\subsystem\init\landmarks.dm" @@ -698,6 +699,7 @@ #include "code\datums\tutorial\ss13\basic_ss13.dm" #include "code\datums\tutorial\ss13\intents.dm" #include "code\datums\tutorial\xenomorph\_xenomorph.dm" +#include "code\datums\tutorial\xenomorph\abomination.dm" #include "code\datums\tutorial\xenomorph\xenomorph_basic.dm" #include "code\datums\weather\weather_event.dm" #include "code\datums\weather\weather_map_holder.dm" @@ -1137,11 +1139,7 @@ #include "code\game\objects\items\devices\pinpointer.dm" #include "code\game\objects\items\devices\pipe_painter.dm" #include "code\game\objects\items\devices\portable_vendor.dm" -#include "code\game\objects\items\devices\RCD.dm" -#include "code\game\objects\items\devices\RSF.dm" -#include "code\game\objects\items\devices\RSP.dm" #include "code\game\objects\items\devices\scanners.dm" -#include "code\game\objects\items\devices\suit_cooling.dm" #include "code\game\objects\items\devices\taperecorder.dm" #include "code\game\objects\items\devices\teleportation.dm" #include "code\game\objects\items\devices\transfer_valve.dm" @@ -1250,7 +1248,6 @@ #include "code\game\objects\items\storage\toolbox.dm" #include "code\game\objects\items\storage\toolkit.dm" #include "code\game\objects\items\storage\wallets.dm" -#include "code\game\objects\items\tanks\jetpack.dm" #include "code\game\objects\items\tanks\tank_types.dm" #include "code\game\objects\items\tanks\tanks.dm" #include "code\game\objects\items\tools\cleaning_tools.dm" @@ -1314,6 +1311,7 @@ #include "code\game\objects\structures\prop_mech.dm" #include "code\game\objects\structures\props.dm" #include "code\game\objects\structures\reagent_dispensers.dm" +#include "code\game\objects\structures\roof.dm" #include "code\game\objects\structures\safe.dm" #include "code\game\objects\structures\shower.dm" #include "code\game\objects\structures\signs.dm" @@ -1346,7 +1344,6 @@ #include "code\game\objects\structures\crates_lockers\closets\gimmick.dm" #include "code\game\objects\structures\crates_lockers\closets\job_closets.dm" #include "code\game\objects\structures\crates_lockers\closets\l3closet.dm" -#include "code\game\objects\structures\crates_lockers\closets\malfunction.dm" #include "code\game\objects\structures\crates_lockers\closets\utility_closets.dm" #include "code\game\objects\structures\crates_lockers\closets\wall_locker.dm" #include "code\game\objects\structures\crates_lockers\closets\wardrobe.dm" @@ -1410,7 +1407,6 @@ #include "code\game\verbs\ooc.dm" #include "code\game\verbs\preferences.dm" #include "code\game\verbs\records.dm" -#include "code\game\verbs\who.dm" #include "code\modules\trigger.dm" #include "code\modules\admin\admin.dm" #include "code\modules\admin\admin_ranks.dm" @@ -1740,7 +1736,6 @@ #include "code\modules\economy\cash.dm" #include "code\modules\economy\economy_misc.dm" #include "code\modules\economy\EFTPOS.dm" -#include "code\modules\economy\TradeDestinations.dm" #include "code\modules\emoji\emoji_parse.dm" #include "code\modules\escape_menu\admin_buttons.dm" #include "code\modules\escape_menu\details.dm" @@ -2334,7 +2329,6 @@ #include "code\modules\surgery\brainrepair.dm" #include "code\modules\surgery\chestburster.dm" #include "code\modules\surgery\eye.dm" -#include "code\modules\surgery\face.dm" #include "code\modules\surgery\generic.dm" #include "code\modules\surgery\headreattach.dm" #include "code\modules\surgery\implant.dm" diff --git a/html/changelogs/AutoChangeLog-pr-6543.yml b/html/changelogs/AutoChangeLog-pr-6543.yml deleted file mode 100644 index 87919d002c94..000000000000 --- a/html/changelogs/AutoChangeLog-pr-6543.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: "Blundir" -delete-after: True -changes: - - rscadd: "jtac and Intel kits to ASRS store" - - rscadd: "Intel kit to IO points vendor" - - balance: "intel kit now has large doc pouch instead of small" - - balance: "jtac kit now has radiopack" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-6544.yml b/html/changelogs/AutoChangeLog-pr-6544.yml deleted file mode 100644 index cd3c72c43076..000000000000 --- a/html/changelogs/AutoChangeLog-pr-6544.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "iloveloopers" -delete-after: True -changes: - - bugfix: "Demolitions scanner now properly works for incinerator tanks." - - spellcheck: "Fixed some capitalization with custom incinerator tanks." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-6549.yml b/html/changelogs/AutoChangeLog-pr-6549.yml deleted file mode 100644 index 5770d46d171e..000000000000 --- a/html/changelogs/AutoChangeLog-pr-6549.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Diegoflores31" -delete-after: True -changes: - - imageadd: "changes xeno intent icon for a cooler one." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-6550.yml b/html/changelogs/AutoChangeLog-pr-6550.yml deleted file mode 100644 index c6d18b244fe0..000000000000 --- a/html/changelogs/AutoChangeLog-pr-6550.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Unknownity" -delete-after: True -changes: - - bugfix: "Burrowers now see themselves as partly transparent when burrowed." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-6570.yml b/html/changelogs/AutoChangeLog-pr-6570.yml deleted file mode 100644 index 087e269ba78a..000000000000 --- a/html/changelogs/AutoChangeLog-pr-6570.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Git-Nivrak" -delete-after: True -changes: - - balance: "Hivelords now have meson vision" - - rscadd: "Added a toggle for meson vision for hivelord and burrower" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-6655.yml b/html/changelogs/AutoChangeLog-pr-6655.yml deleted file mode 100644 index 755b58900c16..000000000000 --- a/html/changelogs/AutoChangeLog-pr-6655.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "blackdragonTOW" -delete-after: True -changes: - - soundadd: "Power Loader sounds have been normalized to -6db" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-6656.yml b/html/changelogs/AutoChangeLog-pr-6656.yml deleted file mode 100644 index 398d11cadcc4..000000000000 --- a/html/changelogs/AutoChangeLog-pr-6656.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "Drathek" -delete-after: True -changes: - - maptweak: "Removed var edits from open turfs to fix ScrapeAway resetting the turf (e.g. xenos building resin walls) on basically all maps" - - maptweak: "Fixed bad dir var edits on various map" - - maptweak: "Fixed stacked structures on various maps" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-6665.yml b/html/changelogs/AutoChangeLog-pr-6665.yml deleted file mode 100644 index dba836f4df3c..000000000000 --- a/html/changelogs/AutoChangeLog-pr-6665.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Doubleumc" -delete-after: True -changes: - - imageadd: "adds CMP tracker sprites for all HUD options" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-6670.yml b/html/changelogs/AutoChangeLog-pr-6670.yml deleted file mode 100644 index 936ea1fa4bdd..000000000000 --- a/html/changelogs/AutoChangeLog-pr-6670.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Steelpoint" -delete-after: True -changes: - - rscadd: "VAISO Covert Operatives will now spawn with a Night Vision Optic in their helmet." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-6722.yml b/html/changelogs/AutoChangeLog-pr-6722.yml new file mode 100644 index 000000000000..418f5ba27cbd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-6722.yml @@ -0,0 +1,4 @@ +author: "cuberound" +delete-after: True +changes: + - rscdel: "removes /obj/item/device/suit_cooling_unit and get_pressure_weakness()" \ No newline at end of file diff --git a/html/changelogs/archive/2024-07.yml b/html/changelogs/archive/2024-07.yml index ae4029da063d..242f50f1e7d3 100644 --- a/html/changelogs/archive/2024-07.yml +++ b/html/changelogs/archive/2024-07.yml @@ -92,3 +92,136 @@ hislittlecuzingames: - rscadd: Multiple tools, and welding visor to SO Locker - qol: Adds free bayonet to Staff Officer Locker +2024-07-11: + Blundir: + - rscadd: jtac and Intel kits to ASRS store + - rscadd: Intel kit to IO points vendor + - balance: intel kit now has large doc pouch instead of small + - balance: jtac kit now has radiopack + Diegoflores31: + - imageadd: changes xeno intent icon for a cooler one. + Doubleumc: + - imageadd: adds CMP tracker sprites for all HUD options + Drathek: + - maptweak: Removed var edits from open turfs to fix ScrapeAway resetting the turf + (e.g. xenos building resin walls) on basically all maps + - maptweak: Fixed bad dir var edits on various map + - maptweak: Fixed stacked structures on various maps + Git-Nivrak: + - balance: Hivelords now have meson vision + - rscadd: Added a toggle for meson vision for hivelord and burrower + Steelpoint: + - rscadd: VAISO Covert Operatives will now spawn with a Night Vision Optic in their + helmet. + Unknownity: + - bugfix: Burrowers now see themselves as partly transparent when burrowed. + blackdragonTOW: + - soundadd: Power Loader sounds have been normalized to -6db + iloveloopers: + - bugfix: Demolitions scanner now properly works for incinerator tanks. + - spellcheck: Fixed some capitalization with custom incinerator tanks. +2024-07-12: + Kivts: + - ui: The Company spent some money to upgrade the chemical simulator to work on + the TGUI, Including a few prepaid features. +2024-07-14: + kiVts: + - bugfix: Denied request on req is working again +2024-07-15: + cuberound: + - rscadd: roof structures added, can be also used for lattices and billboards, go + transparent when you are near them +2024-07-16: + Git-Nivrak: + - rscdel: Mortar shells no longer blow up their payload, instead they will create + a small fixed explosion. + Nomoresolvalou: + - rscadd: Added neckties and stethoscope to the synthetic snowflake vendor + Steelpoint: + - balance: The XM88 now deals higher damage per-bullet at the cost of a slightly + lower rate of fire and accuracy. This is identical to as if it had a barrel + charger attached to it. + - balance: Per the above, the barrel charger is no longer compatible with the XM88. +2024-07-17: + AndroBetel: + - rscadd: MP5 has 10% chance to spawn with M203 attached. + VileBeggar: + - rscadd: The CIC armoury now contains a plantable flag of the United Americas. + Zonespace27: + - rscadd: Added a tutorial for xenomorph Abominations. You must complete the tutorial + before being able to roll for Abomination. + harryob: + - bugfix: queens can remote build again + ihatethisengine: + - balance: being mid-paradrop won't trigger traps, fire and stray bullets before + you land. + realforest2001: + - bugfix: Fixes riflemen spec_kits not being usable by riflemen. +2024-07-18: + cuberound: + - rscdel: Removed Rapid-Service-Fabricator, rapid construction device and Rapid-Seed-Producer + (old ss13 junk) +2024-07-19: + Drathek: + - bugfix: Fixed light blue scrubs having no cost in snowflake vendor. + SpypigDev: + - bugfix: SO Armory vendors no longer infinitely supply knives + TotalEpicness5, Triiodine, monkeyfist, Blundir: + - rscadd: Adds the G2 electroshock grenade. This grenade does not stun nor deal + serious damage to xenos, but it stuns via electric shock. It can create EMP-like + effects when faced with electronic devices like sentries, synths, Area Power + Controllers, etc. It's damage is reduced by energy armor. + - bugfix: take_overall_armoured_damage now can actually deal burn damage + - balance: Marine armor has a small bit of energy armor added back. Heavy armor + has slightly more protection than medium/light. + - bugfix: Mines now check for explosive antigrief checks + VileBeggar: + - balance: The DRG-N Offensive Flamer Unit now fires a 3-tile wide glob of high-combustion + napalm. + Zonespace, Vile Beggar: + - rscadd: Handheld planted flags are now indestructible and do a small amount of + damage on hit. + - bugfix: Plantable flags can no longer be duplicated. + - rscdel: Planting a UA flag no longer forces anyone but the planter to warcry. + cuberound: + - bugfix: having left hand broken and not splinted has the same effect on wheelchair + movement speed as right hand + - bugfix: corrects holoround highligh alpha value + - rscdel: Removed malfanction closet + kiVts: + - bugfix: Surgery sound and alike is fixed + realforest2001: + - rscadd: The Combat Correspondant's civilian equipment is now in it's own category + to make it easier to tell why you can't click it as the military version. +2024-07-20: + Doubleumc: + - rscdel: Removed facial disfigurement + - code_imp: Fixed and refactored probability weighting for pick_weight + - bugfix: no longer stab with utensil when trying to feed while target full + Drathek: + - admin: Added causes for explosion starts to attack logs + Steelpoint: + - rscadd: The Heavy Pulse Rifle (M41AE2) will now start with a pre-attached bipod. + To better inform players of its unique auto-fire function. + Zonespace27: + - bugfix: Fixed a large amount of objects activating erroneous functionality (like + an armor light) when using action buttons tied to that object. + - bugfix: Fixed a potential softlock in the abomination tutorial. + cuberound: + - rscdel: removes trade destinations (they were never used) + - balance: m56 cupola uses m56d ammo rather then standard sg ammo +2024-07-22: + BlackCrystalic: + - bugfix: Queen maturity timer + Blackcrystalic: + - qol: port who/staffwho to TGUI + ThePiachu: + - refactor: Made XM88 box code more uniform with other handful boxes. + zzzmike: + - bugfix: lifeboat launch console is no longer slashable / acidable +2024-07-23: + cuberound: + - code_imp: cleans up water particle code +2024-07-24: + Doubleumc: + - bugfix: sounds & motion detectors should be more reliable diff --git a/icons/effects/sebb.dmi b/icons/effects/sebb.dmi new file mode 100644 index 000000000000..288a1023ce3d Binary files /dev/null and b/icons/effects/sebb.dmi differ diff --git a/icons/mob/humans/onmob/items_lefthand_0.dmi b/icons/mob/humans/onmob/items_lefthand_0.dmi index 7d887799815b..a4396aeb93de 100644 Binary files a/icons/mob/humans/onmob/items_lefthand_0.dmi and b/icons/mob/humans/onmob/items_lefthand_0.dmi differ diff --git a/icons/mob/humans/onmob/items_lefthand_64.dmi b/icons/mob/humans/onmob/items_lefthand_64.dmi index 057d7f1cad66..d005d8c5f049 100644 Binary files a/icons/mob/humans/onmob/items_lefthand_64.dmi and b/icons/mob/humans/onmob/items_lefthand_64.dmi differ diff --git a/icons/mob/humans/onmob/items_righthand_0.dmi b/icons/mob/humans/onmob/items_righthand_0.dmi index 184946a13f0b..582262e88289 100644 Binary files a/icons/mob/humans/onmob/items_righthand_0.dmi and b/icons/mob/humans/onmob/items_righthand_0.dmi differ diff --git a/icons/mob/humans/onmob/items_righthand_64.dmi b/icons/mob/humans/onmob/items_righthand_64.dmi index 599ef5935f2e..72335e39bfff 100644 Binary files a/icons/mob/humans/onmob/items_righthand_64.dmi and b/icons/mob/humans/onmob/items_righthand_64.dmi differ diff --git a/icons/obj/items/weapons/grenade.dmi b/icons/obj/items/weapons/grenade.dmi index 7ee5af737066..ca8aaf9afcd6 100644 Binary files a/icons/obj/items/weapons/grenade.dmi and b/icons/obj/items/weapons/grenade.dmi differ diff --git a/icons/obj/structures/plantable_flag.dmi b/icons/obj/structures/plantable_flag.dmi new file mode 100644 index 000000000000..c92311529be3 Binary files /dev/null and b/icons/obj/structures/plantable_flag.dmi differ diff --git a/maps/map_files/CORSAT/Corsat.dmm b/maps/map_files/CORSAT/Corsat.dmm index ea56dacf0fa3..f335e4c41e8b 100644 --- a/maps/map_files/CORSAT/Corsat.dmm +++ b/maps/map_files/CORSAT/Corsat.dmm @@ -24911,7 +24911,6 @@ /area/corsat/sigma/south/complex) "bTM" = ( /obj/structure/surface/table/reinforced, -/obj/item/device/suit_cooling_unit, /turf/open/floor/corsat/retrosquareslight, /area/corsat/sigma/south/complex) "bTN" = ( @@ -35676,7 +35675,6 @@ /area/corsat/omega/complex) "lHI" = ( /obj/structure/surface/table/reinforced, -/obj/item/ammo_rcd, /turf/open/floor/corsat/retrosquareslight, /area/corsat/sigma/south/complex) "lHK" = ( diff --git a/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm b/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm index f66743b6388e..954a9fdbe40a 100644 --- a/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm +++ b/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm @@ -25377,7 +25377,6 @@ /turf/open/floor/prison/sterile_white/southwest, /area/fiorina/station/medbay) "tpE" = ( -/obj/item/tank/jetpack/carbondioxide, /obj/structure/surface/rack, /turf/open/floor/prison/floor_plate, /area/fiorina/tumor/servers) diff --git a/maps/map_files/Ice_Colony_v2/Ice_Colony_v2.dmm b/maps/map_files/Ice_Colony_v2/Ice_Colony_v2.dmm index 80342068f6e6..af8650e3bdb2 100644 --- a/maps/map_files/Ice_Colony_v2/Ice_Colony_v2.dmm +++ b/maps/map_files/Ice_Colony_v2/Ice_Colony_v2.dmm @@ -10137,10 +10137,6 @@ /area/ice_colony/surface/storage_unit/research) "aKo" = ( /obj/structure/surface/rack, -/obj/item/ammo_rcd, -/obj/item/ammo_rcd, -/obj/item/ammo_rcd, -/obj/item/ammo_rcd, /turf/open/floor/vault2/west, /area/ice_colony/surface/storage_unit/research) "aKp" = ( diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm index 9617bfaccb6c..b4a195ae5969 100644 --- a/maps/map_files/USS_Almayer/USS_Almayer.dmm +++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm @@ -2665,6 +2665,7 @@ /obj/item/device/radio/marine, /obj/item/device/radio/marine, /obj/item/folded_tent/cmd, +/obj/item/flag/plantable/ua, /turf/open/floor/almayer/redfull, /area/almayer/command/cic) "asR" = ( diff --git a/nano/templates/chem_simulator.tmpl b/nano/templates/chem_simulator.tmpl deleted file mode 100644 index 47057f13bf85..000000000000 --- a/nano/templates/chem_simulator.tmpl +++ /dev/null @@ -1,366 +0,0 @@ - -
-
- STATUS: {{:data.status_bar}} -
- RESEARCH CREDITS: {{:data.rsc_credits}} -
- {{if data.mode == 4 }} - CREATION NAME: {{:data.creation_name}}
- CREATION COST: {{:data.creation_cost}}
- ESTIMATED OVERDOSE LVL: {{:data.od_lvl}} UNITS - {{else}} - {{if data.target }} - TARGET DATA: {{:data.target}} - {{else}} - TARGET DATA: NOT FOUND - {{/if}} -
- {{if data.reference }} - REFERENCE DATA: {{:data.reference}} - {{else}} - REFERENCE DATA: NOT FOUND - {{/if}} -
- ESTIMATED OVERDOSE LVL: {{:data.od_lvl}} UNITS - {{/if}} -
- {{if data.simulating }} - - {{else}} - - {{/if}} - -
-
-
- {{if data.mode != 4 }} -
- {{if data.target_property}} -

{{:data.property_codings[data.target_property]}} - {{:data.target_property}}

-

- {{:data.target_info}} -
Type: {{:data.target_categories}} -
Research Cost: {{:data.property_costs[data.target_property]}} -

- {{/if}} -
-
-

Target Properties

- {{if data.target}} - {{if data.target_property_list }} -
- {{props data.target_property_list :level:property}} - {{:helper.link('' + data.property_codings[property] + ' Level ' + level + '', null, {'set_target' : property}, (data.target_property == property) ? 'selected' : null, 'propbutton')}} - {{/props}} -
- {{else}} - PROPERTIES CAN NOT BE SIMULATED - {{/if}} - {{/if}} -
- {{else}} -
-
- {{if data.complexity_editor }} - {{:helper.link(data.complexity[0], 'gear', {'set_complexity' : 1}, null, 'menubutton templateButton')}} - {{:helper.link(data.complexity[1], 'gear', {'set_complexity' : 2}, null, 'menubutton templateButton')}} - {{:helper.link(data.complexity[2], 'gear', {'set_complexity' : 3}, null, 'menubutton templateButton')}} - {{else}} - {{:helper.link('SET LVL', 'gear', {'set_level' : 1}, (data.target_property && data.property_data_list[data.target_property] >= 1) ? null : 'disabled', 'menubutton templateButton')}} - {{:helper.link('SET NAME', 'gear', {'set_name' : 1}, null, 'templateButton')}} - {{:helper.link('SET OD', 'gear', {'set_od' : 1}, null, 'templateButton')}} - {{props data.template_filter :setting:configuration}} - {{if setting[0] == 1 }} - {{:helper.link(configuration, null, {'set_filter' : configuration, 'config_value' : setting[1]}, null, 'modebutton templateButton enabled')}} - {{else}} - {{:helper.link(configuration, null, {'set_filter' : configuration, 'config_value' : setting[1]}, null, 'modebutton templateButton')}} - {{/if}} - {{/props}} - {{/if}} -
-
- {{props data.property_data_list :level:property}} - {{if data.target_property == property}} - {{if level > 0 }} - {{:helper.link(data.property_codings[property] + ' ' + level, null, {'set_target' : property}, null, 'propbutton templateProp targetedEnabled')}} - {{else}} - {{:helper.link(data.property_codings[property] + ' ' + level, null, {'set_target' : property}, null, 'propbutton templateProp targetedDisabled')}} - {{/if}} - {{else}} - {{if level > 0 }} - {{:helper.link(data.property_codings[property] + ' ' + level, null, {'set_target' : property}, null, 'propbutton templateProp')}} - {{else}} - {{:helper.link(data.property_codings[property] + ' ' + level, null, {'set_target' : property}, null, 'propbutton templateProp disabled')}} - {{/if}} - {{/if}} - {{/props}} -
-
- {{/if}} -
-
- {{if data.mode == 3 }} -
- {{if data.reference_property }} -

{{:data.property_codings[data.reference_property]}} - {{:data.reference_property}}

-

- {{:data.reference_info}} -
Type: {{:data.reference_categories}} -

- {{/if}} -
-
-

Reference Properties

- {{if data.reference}} - {{if data.reference_property_list }} -
- {{props data.reference_property_list :level:property}} - {{:helper.link('' + data.property_codings[property] + ' Level ' + level + '', null, {'set_reference' : property}, (data.reference_property == property) ? 'selected' : null, 'propbutton')}} - {{/props}} -
- {{else}} - PROPERTIES CAN NOT BE SIMULATED - {{/if}} - {{/if}} -
- {{else}} - {{if data.mode == 4 }} -
- {{if data.target_property}} -

{{:data.property_codings[data.target_property]}} - {{:data.target_property}}

-

- {{:data.target_info}} -
Type: {{:data.target_categories}} -
Value per level: {{:data.property_costs[data.target_property]}} -

- {{/if}} -
- {{/if}} - {{/if}} -
-
diff --git a/sound/effects/.wav b/sound/effects/.wav new file mode 100644 index 000000000000..a5aa273379f6 Binary files /dev/null and b/sound/effects/.wav differ diff --git a/sound/effects/flag_lowering.ogg b/sound/effects/flag_lowering.ogg new file mode 100644 index 000000000000..d514e097913d Binary files /dev/null and b/sound/effects/flag_lowering.ogg differ diff --git a/sound/effects/flag_raised.ogg b/sound/effects/flag_raised.ogg new file mode 100644 index 000000000000..5da7eca55acb Binary files /dev/null and b/sound/effects/flag_raised.ogg differ diff --git a/sound/effects/flag_raising.ogg b/sound/effects/flag_raising.ogg new file mode 100644 index 000000000000..cc2770f2ecb8 Binary files /dev/null and b/sound/effects/flag_raising.ogg differ diff --git a/sound/effects/flag_warcry_ua.ogg b/sound/effects/flag_warcry_ua.ogg new file mode 100644 index 000000000000..eb0ddecc66eb Binary files /dev/null and b/sound/effects/flag_warcry_ua.ogg differ diff --git a/sound/effects/flag_warcry_ua_extra.ogg b/sound/effects/flag_warcry_ua_extra.ogg new file mode 100644 index 000000000000..c723cca44620 Binary files /dev/null and b/sound/effects/flag_warcry_ua_extra.ogg differ diff --git a/sound/effects/sebb.ogg b/sound/effects/sebb.ogg new file mode 100644 index 000000000000..5fd1f5b396d9 Binary files /dev/null and b/sound/effects/sebb.ogg differ diff --git a/sound/effects/sebb_beep.ogg b/sound/effects/sebb_beep.ogg new file mode 100644 index 000000000000..16c9347d0be2 Binary files /dev/null and b/sound/effects/sebb_beep.ogg differ diff --git a/sound/effects/sebb_explode.ogg b/sound/effects/sebb_explode.ogg new file mode 100644 index 000000000000..999385d9f068 Binary files /dev/null and b/sound/effects/sebb_explode.ogg differ diff --git a/tgui/packages/tgui/interfaces/ChemSimulator.jsx b/tgui/packages/tgui/interfaces/ChemSimulator.jsx new file mode 100644 index 000000000000..4243386e14c3 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ChemSimulator.jsx @@ -0,0 +1,629 @@ +import { map } from 'common/collections'; + +import { useBackend, useSharedState } from '../backend'; +import { + Box, + Button, + Divider, + Flex, + NoticeBox, + ProgressBar, + Section, + Stack, +} from '../components'; +import { Window } from '../layouts'; + +export const InfoPanel = () => { + const { data } = useBackend(); + const { + credits, + status, + od_level, + chemical_name, + estimated_cost, + reference_name, + } = data; + return ( +
+ + + +

RESEARCH CREDITS: {credits}

+
+
+ + STATUS: {status} + + + ESTIMATED SIMULATING COST: {estimated_cost} + + + TARGET NAME: {chemical_name} + + + REFERENCE NAME: {reference_name} + + + OVERDOSE LEVEL AFTER SIMULATION: {od_level} + +
+
+ ); +}; + +export const Controls = (props) => { + const { act, data } = useBackend(); + const { + selectedMode, + setSelectedMode, + complexityMenu, + setComplexityMenu, + setSelectedReferenceProperty, + setSelectedTargetProperty, + } = props; + const { + mode_data, + can_simulate, + can_eject_target, + can_eject_reference, + can_cancel_simulation, + lock_control, + } = data; + return ( + + + + + {can_cancel_simulation ? ( + + ) : ( + + )} + + + + + + + + + + + + + + + {mode_data.map((mode_data, id) => ( + + + + ))} + + + + ); +}; + +export const RecipeOptions = () => { + const { act, data } = useBackend(); + const [selectedRecipe, setSelectedRecipe] = useSharedState('recipe', null); + const { reagent_option_data } = data; + return ( + + + + {map(reagent_option_data, (recipe, id) => ( + + ))} + + + ); +}; + +export const ModeChange = (props) => { + const { act, data } = useBackend(); + const { target_data, lock_control } = data; + const { selectedTargetProperty, setSelectedTargetProperty } = props; + return ( + (target_data && ( + + + + Target Data + + + + {map(target_data, (property) => ( + + ))} + + + + + + {map( + target_data, + (property) => + property.code === selectedTargetProperty && ( + + +
{property.desc}
+
+ + Price of the operation : {property.cost} + +
+ ), + )} +
+
+ )) || ( + + No data inserted! + + ) + ); +}; + +export const ModeRelate = (props) => { + const { act, data } = useBackend(); + const { target_data, reference_data, lock_control } = data; + const { + setSelectedTargetProperty, + setSelectedReferenceProperty, + selectedReferenceProperty, + selectedTargetProperty, + } = props; + return ( + (target_data && reference_data && ( + + + + Target Data + + + + {map(target_data, (property) => ( + + ))} + + + + + + + Reference Data + + + + {map(reference_data, (property) => ( + + ))} + + + + + + {map( + target_data, + (property) => + property.code === selectedTargetProperty && ( + + +
{property.desc}
+
+ + Price of the operation : {property.cost} + +
+ ), + )} +
+
+ )) || ( + + No data inserted! + + ) + ); +}; + +export const ModeCreate = (props) => { + const { act, data } = useBackend(); + const { complexityMenu } = props; + const { known_properties } = data; + const [selectedProperty, setSelectedProperty] = useSharedState(false); + return ( + + + + + + + {map(known_properties, (property) => ( + + + + ))} + + + + {map( + known_properties, + (property) => + property.code === selectedProperty && ( +
+

{property.desc}

+
+ ), + )} +
+
+ ); +}; + +export const CreateControl = (props) => { + const { act, data } = useBackend(); + const { template_filters, lock_control, complexity_list } = data; + const { complexityMenu } = props; + return !complexityMenu ? ( + + + + + + + + + + + {map(template_filters, (flag, name) => ( + + + + ))} + + ) : ( + + {map(complexity_list, (rarity, id) => ( + + + + ))} + + ); +}; + +export const ChemSimulator = () => { + const { data } = useBackend(); + const { is_picking_recipe } = data; + const [selectedMode, setSelectedMode] = useSharedState('modes'); + const [complexityMenu, setComplexityMenu] = useSharedState( + 'complexity_flip', + false, + ); + const [selectedTargetProperty, setSelectedTargetProperty] = useSharedState( + 'target', + false, + ); + const [selectedReferenceProperty, setSelectedReferenceProperty] = + useSharedState('reference_relate', false); + return ( + + + + + + + + {(!is_picking_recipe && ( + + )) || } + + + + {selectedMode === 1 && ( + + )} + {selectedMode === 2 && ( + + )} + {selectedMode === 3 && ( + + )} + {selectedMode === 4 && } + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/StaffWho.jsx b/tgui/packages/tgui/interfaces/StaffWho.jsx new file mode 100644 index 000000000000..1ce71c9b5001 --- /dev/null +++ b/tgui/packages/tgui/interfaces/StaffWho.jsx @@ -0,0 +1,78 @@ +import { useBackend } from '../backend'; +import { Button, Collapsible, Stack } from '../components'; +import { Window } from '../layouts'; + +export const StaffWho = (props, context) => { + const { data } = useBackend(context); + const { admin, administrators } = data; + + return ( + + + {administrators !== undefined ? ( + + + {administrators.map((x, index) => ( + + {x.admins.map((x, index) => ( + + ))} + + ))} + + + ) : null} + + + ); +}; + +const StaffWhoCollapsible = (props, context) => { + const { title, color, children } = props; + return ( + + {children} + + ); +}; + +const GetAdminInfo = (props, context) => { + const { admin, content, color, text } = props; + return admin ? ( + + ) : ( + + ); +}; diff --git a/tgui/packages/tgui/interfaces/TutorialMenu.tsx b/tgui/packages/tgui/interfaces/TutorialMenu.tsx index 14abfa957b1c..c47db9fd746d 100644 --- a/tgui/packages/tgui/interfaces/TutorialMenu.tsx +++ b/tgui/packages/tgui/interfaces/TutorialMenu.tsx @@ -60,25 +60,30 @@ export const TutorialMenu = (props) => { {tutorial_categories.map( (tutorial_category) => tutorial_category.name === categoryIndex && - tutorial_category.tutorials.map((tutorial) => ( -
- -
- )), + + + )), )} diff --git a/tgui/packages/tgui/interfaces/Who.jsx b/tgui/packages/tgui/interfaces/Who.jsx new file mode 100644 index 000000000000..dccf3d1e39f0 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Who.jsx @@ -0,0 +1,189 @@ +import { useBackend, useLocalState } from '../backend'; +import { + Box, + Button, + Collapsible, + Icon, + Input, + Section, + Stack, +} from '../components'; +import { Window } from '../layouts'; + +export const Who = (props, context) => { + const { act, data } = useBackend(context); + const { + admin, + all_clients, + total_players = [], + additional_info = [], + factions = [], + xenomorphs = [], + } = data; + + const [searchQuery, setSearchQuery] = useLocalState('searchQuery', ''); + + const searchPlayers = () => + total_players.filter((player) => isMatch(player, searchQuery)); + + const filteredTotalPlayers = searchPlayers(); + + return ( + + + + +
+ + + + + + + act('get_player_panel', { + ckey: searchPlayers()?.[0].ckey, + }) + } + onInput={(e) => setSearchQuery(e.target.value)} + placeholder="Search..." + value={searchQuery} + /> + + +
+
+ +
+ + {filteredTotalPlayers.length ? ( + + {filteredTotalPlayers.map((x) => ( + + ))} + + ) : null} + +
+ {admin !== 0 ? ( +
+ + + {additional_info.length + ? additional_info.map((x, index) => ( + + )) + : null} + {factions.length + ? factions.map((x, index) => ( + + )) + : null} + {xenomorphs.length + ? xenomorphs.map((x, index) => ( + + )) + : null} + + +
+ ) : null} +
+
+
+
+ ); +}; + +const WhoCollapsible = (props, context) => { + const { title, color, children } = props; + return ( + + {children} + + ); +}; + +const GetAddInfo = (props, context) => { + const { act } = useBackend(context); + const { content, color, text } = props; + + return ( + + ); +}; + +const GetPlayerInfo = (props, context) => { + const { act } = useBackend(context); + const { + admin, + player: { ckey, ckey_color, color, text }, + } = props; + return admin !== 0 ? ( + + ) : ( + + ); +}; + +const isMatch = (player, searchQuery) => { + if (!searchQuery) { + return true; + } + + return ( + player.ckey.toLowerCase().includes(searchQuery?.toLowerCase()) || false + ); +}; diff --git a/tgui/packages/tgui/styles/themes/weyland.scss b/tgui/packages/tgui/styles/themes/weyland.scss index 665a975e933d..bf2cbbd29cc6 100644 --- a/tgui/packages/tgui/styles/themes/weyland.scss +++ b/tgui/packages/tgui/styles/themes/weyland.scss @@ -28,7 +28,7 @@ $weyland: #af7f38; '../components/Button.scss', $with: ( 'color-default': $weyland, - 'color-selected': #9d0808, + 'color-selected': #e4c69a, 'color-caution': #be6209, 'color-danger': #9a9d00, 'color-transparent-text': color.scale($weyland, $lightness: 30%) @@ -47,6 +47,10 @@ $weyland: #af7f38; '../layouts/TitleBar.scss', $with: ('background-color': color.scale(#252832, $lightness: -25%)) ); + @include meta.load-css( + '../components/Divider.scss', + $with: ('color': rgba(28, 30, 32, 0.932), 'thickness': base.em(4px)) + ); .Button { font-family: consolas; @@ -59,7 +63,7 @@ $weyland: #af7f38; background-color: #252832; background-image: url('../../assets/bg-weyland.png'); background-position: top; - background-size: contain; + background-size: auto; background-repeat: repeat no-repeat; }