diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index c443a49ba1..60fa224ef8 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -318,7 +318,7 @@
var/obj/item/card/id/ID = A
if(ID.registered_name == oldname)
ID.registered_name = newname
- ID.name = "[newname]'s ID Card ([ID.assignment])"
+ ID.name = "[newname]'s [ID.card_name] ([ID.assignment])"
if(!search_pda) break
search_id = 0
return 1
diff --git a/code/datums/ammo/bullet/pistol.dm b/code/datums/ammo/bullet/pistol.dm
index 8edb66857d..488b4e22c8 100644
--- a/code/datums/ammo/bullet/pistol.dm
+++ b/code/datums/ammo/bullet/pistol.dm
@@ -182,9 +182,10 @@
accuracy = HIT_ACCURACY_TIER_2
damage = 50
- penetration = ARMOR_PENETRATION_TIER_4
- shrapnel_chance = SHRAPNEL_CHANCE_TIER_2
- damage_falloff = DAMAGE_FALLOFF_TIER_3 //"VP78 - the only pistol viable as a primary."-Vampmare, probably.
+ penetration = ARMOR_PENETRATION_TIER_2
+ shrapnel_chance = SHRAPNEL_CHANCE_TIER_1
+ effective_range_max = 3 //hopefully this fixes the damage woes.
+ damage_falloff = DAMAGE_FALLOFF_TIER_6
/datum/ammo/bullet/pistol/squash/toxin
name = "toxic squash-head pistol bullet"
diff --git a/code/game/jobs/job/marine/squads.dm b/code/game/jobs/job/marine/squads.dm
index 028dd70ec1..27fb293daa 100644
--- a/code/game/jobs/job/marine/squads.dm
+++ b/code/game/jobs/job/marine/squads.dm
@@ -360,7 +360,7 @@
continue
marine_card.assignment = "[new_name] [marine.job]"
- marine_card.name = "[marine_card.registered_name]'s ID Card ([marine_card.assignment])"
+ marine_card.name = "[marine_card.registered_name]'s [marine_card.card_name] ([marine_card.assignment])"
/datum/squad/proc/setup_supply_drop_list()
SIGNAL_HANDLER
@@ -607,7 +607,7 @@
if(paygrade)
C.paygrade = paygrade
- C.name = "[C.registered_name]'s ID Card ([C.assignment])"
+ C.name = "[C.registered_name]'s [C.card_name] ([C.assignment])"
var/obj/item/device/radio/headset/almayer/marine/headset = locate() in list(M.wear_l_ear, M.wear_r_ear)
if(headset && radio_freq)
@@ -629,7 +629,7 @@
C.access -= src.access
C.assignment = M.assigned_equipment_preset.assignment
- C.name = "[C.registered_name]'s ID Card ([C.assignment])"
+ C.name = "[C.registered_name]'s [C.card_name] ([C.assignment])"
forget_marine_in_squad(M)
diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm
index b6ce8b11ca..2b6ae446d8 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -92,6 +92,8 @@
var/modification_log = list()
+ var/card_name = "ID Card"
+
/obj/item/card/id/Initialize(mapload, ...)
. = ..()
@@ -132,7 +134,7 @@
/obj/item/card/id/proc/set_assignment(new_assignment)
assignment = new_assignment
- name = "[registered_name]'s ID Card ([assignment])"
+ name = "[registered_name]'s [card_name] ([assignment])"
/obj/item/card/id/GetAccess()
return access
@@ -279,7 +281,7 @@
else
registered_name = "Agent Card"
assignment = "Agent"
- name = "[registered_name]'s ID Card ([assignment])"
+ name = "[registered_name]'s [card_name] ([assignment])"
/obj/item/card/id/syndicate/afterattack(obj/item/O as obj, mob/user as mob, proximity)
if(!proximity) return
@@ -304,7 +306,7 @@
src.registered_name = ""
return
src.assignment = u
- src.name = "[src.registered_name]'s ID Card ([src.assignment])"
+ src.name = "[src.registered_name]'s [card_name] ([src.assignment])"
to_chat(user, SPAN_NOTICE(" You successfully forge the ID card."))
registered_user = user
else if(!registered_user || registered_user == user)
@@ -324,7 +326,7 @@
alert("Invalid assignment.")
return
src.assignment = u
- src.name = "[src.registered_name]'s ID Card ([src.assignment])"
+ src.name = "[src.registered_name]'s [card_name] ([src.assignment])"
to_chat(user, SPAN_NOTICE(" You successfully forge the ID card."))
return
if("Show")
@@ -387,6 +389,7 @@
item_state = "dogtag"
pinned_on_uniform = FALSE
var/dogtag_taken = FALSE
+ card_name = "dog tags"
/obj/item/card/id/dogtag/get_examine_text(mob/user)
diff --git a/code/modules/admin/game_master/game_master.dm b/code/modules/admin/game_master/game_master.dm
index c6ad9063c7..947c49aeb5 100644
--- a/code/modules/admin/game_master/game_master.dm
+++ b/code/modules/admin/game_master/game_master.dm
@@ -58,6 +58,7 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100)
var/list/submenu_types = list(
/obj/structure/pipes/vents = /datum/game_master_submenu/ambush/vents,
/obj/structure/tunnel = /datum/game_master_submenu/ambush/tunnels,
+ /mob/living/carbon/human = /datum/game_master_submenu/infest,
)
/// List of current submenus
diff --git a/code/modules/admin/game_master/game_master_submenu/infest.dm b/code/modules/admin/game_master/game_master_submenu/infest.dm
new file mode 100644
index 0000000000..4d64e66e0b
--- /dev/null
+++ b/code/modules/admin/game_master/game_master_submenu/infest.dm
@@ -0,0 +1,97 @@
+#define DEFAULT_SPAWN_HIVE_STRING XENO_HIVE_NORMAL
+
+/datum/game_master_submenu/infest
+ tgui_menu_name = "GameMasterSubmenuInfest"
+ tgui_menu_title = "Infest Control"
+
+ /// Current selected hive for the embryo
+ var/selected_hive = DEFAULT_SPAWN_HIVE_STRING
+
+ /// Target growth stage for the embryo
+ var/embryo_stage = 0
+
+/datum/game_master_submenu/infest/ui_data(mob/user)
+ . = ..()
+
+ var/list/data = list()
+
+ data["selected_hive"] = selected_hive
+ data["embryo_stage"] = embryo_stage
+
+ return data
+
+/datum/game_master_submenu/infest/ui_static_data(mob/user)
+ . = ..()
+
+ var/list/data = list()
+
+ data["selectable_hives"] = ALL_XENO_HIVES
+
+ return data
+
+/datum/game_master_submenu/infest/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+
+ switch(action)
+ if("set_selected_hive")
+ selected_hive = params["new_hive"]
+ return TRUE
+
+ if("set_embryo_stage")
+ embryo_stage = params["stage"]
+ return TRUE
+
+ if("infest")
+ setup_embryo()
+ return TRUE
+
+ if("clear_infest")
+ remove_embryo()
+ return TRUE
+
+ if("burst")
+ force_burst()
+ return TRUE
+
+/datum/game_master_submenu/infest/proc/setup_embryo()
+ var/obj/item/alien_embryo/infesting_embryo
+ for(var/obj/item/alien_embryo/embryo in referenced_atom) //if this hive's embryo already exists, convert to larva and use it
+ if(embryo.hivenumber == selected_hive)
+ infesting_embryo = embryo
+ else
+ qdel(embryo)
+
+ if(!infesting_embryo) //else, make a new one
+ infesting_embryo = new /obj/item/alien_embryo(referenced_atom)
+ infesting_embryo.hivenumber = selected_hive
+
+ var/mob/living/carbon/human/infested_host = referenced_atom
+ infested_host.species?.larva_impregnated(infesting_embryo) //Yautja handling
+
+ infesting_embryo.stage = embryo_stage
+
+/datum/game_master_submenu/infest/proc/remove_embryo()
+ for(var/obj/item/alien_embryo/embryo in referenced_atom)
+ qdel(embryo)
+
+/datum/game_master_submenu/infest/proc/force_burst()
+ var/mob/living/carbon/xenomorph/larva/infesting_larva = locate() in referenced_atom //if a larva already exists, use it
+ if(infesting_larva)
+ infesting_larva.chest_burst(referenced_atom)
+ return
+
+ for(var/obj/item/alien_embryo/embryo in referenced_atom) //else if this hive's embryo already exists, convert to larva and use it
+ if(embryo.hivenumber == selected_hive)
+ embryo.become_larva()
+ infesting_larva = locate() in referenced_atom
+ break
+ if(infesting_larva)
+ infesting_larva.chest_burst(referenced_atom)
+ return
+
+ infesting_larva = new /mob/living/carbon/xenomorph/larva(referenced_atom, null, selected_hive) //else, make a new larva
+ var/mob/living/carbon/human/infested_host = referenced_atom
+ infesting_larva.ckey = infested_host.ckey
+ infesting_larva.chest_burst(referenced_atom)
+
+#undef DEFAULT_SPAWN_HIVE_STRING
diff --git a/code/modules/admin/verbs/select_equipment.dm b/code/modules/admin/verbs/select_equipment.dm
index b684fc0d6f..83a9cb1a06 100644
--- a/code/modules/admin/verbs/select_equipment.dm
+++ b/code/modules/admin/verbs/select_equipment.dm
@@ -22,7 +22,7 @@
I.access = J.get_access()
I.rank = J.title
I.assignment = J.disp_title
- I.name = "[I.registered_name]'s ID Card ([I.assignment])"
+ I.name = "[I.registered_name]'s [I.card_name] ([I.assignment])"
I.paygrade = J.get_paygrade()
if(H.w_uniform)
var/obj/item/clothing/C = H.w_uniform
@@ -81,7 +81,7 @@
I.rank = IDtitle
I.assignment = IDtitle
- I.name = "[I.registered_name]'s ID Card ([I.assignment])"
+ I.name = "[I.registered_name]'s [I.card_name] ([I.assignment])"
var/new_faction = tgui_input_list(usr, "Select faction.", "Faction Choice", FACTION_LIST_HUMANOID)
if(!new_faction)
diff --git a/code/modules/cm_marines/marines_consoles.dm b/code/modules/cm_marines/marines_consoles.dm
index 734972ac7b..14911faf85 100644
--- a/code/modules/cm_marines/marines_consoles.dm
+++ b/code/modules/cm_marines/marines_consoles.dm
@@ -137,7 +137,7 @@
if(target_id_card)
if(target_id_card.registered_name != origin_name || target_id_card.assignment != origin_assignment)
GLOB.data_core.manifest_modify(target_id_card.registered_name, target_id_card.registered_ref, target_id_card.assignment, target_id_card.rank)
- target_id_card.name = text("[target_id_card.registered_name]'s ID Card ([target_id_card.assignment])")
+ target_id_card.name = text("[target_id_card.registered_name]'s [target_id_card.card_name] ([target_id_card.assignment])")
if(target_id_card.registered_name != origin_name)
log_idmod(target_id_card, " [key_name_admin(usr)] changed the registered name of the ID to '[target_id_card.registered_name]'. ")
if(target_id_card.assignment != origin_assignment)
@@ -451,7 +451,7 @@
usr.put_in_hands(target_id_card)
if(operable()) // Powered. Make comp proceed ejection
GLOB.data_core.manifest_modify(target_id_card.registered_name, target_id_card.registered_ref, target_id_card.assignment, target_id_card.rank)
- target_id_card.name = text("[target_id_card.registered_name]'s ID Card ([target_id_card.assignment])")
+ target_id_card.name = text("[target_id_card.registered_name]'s [target_id_card.card_name] ([target_id_card.assignment])")
visible_message("[SPAN_BOLD("[src]")] states, \"CARD EJECT: Data imprinted. Updating database... Success.\"")
else
to_chat(usr, "You remove \the [target_id_card] from \the [src].")
diff --git a/code/modules/gear_presets/_select_equipment.dm b/code/modules/gear_presets/_select_equipment.dm
index ce47c0ffec..6aefa9a673 100644
--- a/code/modules/gear_presets/_select_equipment.dm
+++ b/code/modules/gear_presets/_select_equipment.dm
@@ -111,7 +111,7 @@
if(!idtype)
return
var/obj/item/card/id/ID = new idtype()
- ID.name = "[new_human.real_name]'s ID Card"
+ ID.name = "[new_human.real_name]'s [ID.card_name]"
if(assignment)
ID.name += " ([assignment])"
ID.access = access.Copy(1, 0)
diff --git a/code/modules/projectiles/guns/pistols.dm b/code/modules/projectiles/guns/pistols.dm
index c17ca5bca7..aeffb19b9e 100644
--- a/code/modules/projectiles/guns/pistols.dm
+++ b/code/modules/projectiles/guns/pistols.dm
@@ -677,7 +677,7 @@
damage_mult = BASE_BULLET_DAMAGE_MULT + BULLET_DAMAGE_MULT_TIER_4
//-------------------------------------------------------
-//VP78 - the only pistol viable as a primary.
+//VP78 - High power pistol?
/obj/item/weapon/gun/pistol/vp78
name = "\improper VP78 pistol"
@@ -717,14 +717,14 @@
/obj/item/weapon/gun/pistol/vp78/set_gun_config_values()
..()
- set_fire_delay(FIRE_DELAY_TIER_4)
+ set_fire_delay(FIRE_DELAY_TIER_6)
set_burst_amount(BURST_AMOUNT_TIER_3)
set_burst_delay(FIRE_DELAY_TIER_11)
- accuracy_mult = BASE_ACCURACY_MULT
+ accuracy_mult = BASE_ACCURACY_MULT + HIT_ACCURACY_MULT_TIER_6
accuracy_mult_unwielded = BASE_ACCURACY_MULT
- scatter = SCATTER_AMOUNT_TIER_6
- burst_scatter_mult = SCATTER_AMOUNT_TIER_6
- scatter_unwielded = SCATTER_AMOUNT_TIER_6
+ scatter = SCATTER_AMOUNT_TIER_9
+ burst_scatter_mult = SCATTER_AMOUNT_TIER_7
+ scatter_unwielded = SCATTER_AMOUNT_TIER_5
damage_mult = BASE_BULLET_DAMAGE_MULT
recoil = RECOIL_AMOUNT_TIER_5
recoil_unwielded = RECOIL_AMOUNT_TIER_4
diff --git a/code/modules/projectiles/guns/smartgun.dm b/code/modules/projectiles/guns/smartgun.dm
index 7b444de0db..0b0ae120cd 100644
--- a/code/modules/projectiles/guns/smartgun.dm
+++ b/code/modules/projectiles/guns/smartgun.dm
@@ -316,14 +316,15 @@
return FALSE
var/mob/living/carbon/human/H = user
if(!skillcheckexplicit(user, SKILL_SPEC_WEAPONS, SKILL_SPEC_SMARTGUN) && !skillcheckexplicit(user, SKILL_SPEC_WEAPONS, SKILL_SPEC_ALL))
- to_chat(H, SPAN_WARNING("You don't seem to know how to use \the [src]..."))
+ balloon_alert(user, "insufficient skills")
return FALSE
if(requires_harness)
if(!H.wear_suit || !(H.wear_suit.flags_inventory & SMARTGUN_HARNESS))
- to_chat(H, SPAN_WARNING("You need a harness suit to be able to fire [src]..."))
+ balloon_alert(user, "harness required")
return FALSE
if(cover_open)
to_chat(H, SPAN_WARNING("You can't fire \the [src] with the feed cover open! (alt-click to close)"))
+ balloon_alert(user, "cannot fire; feed cover open")
return FALSE
/obj/item/weapon/gun/smartgun/unique_action(mob/user)
@@ -337,6 +338,7 @@
return
secondary_toggled = !secondary_toggled
to_chat(user, "[icon2html(src, usr)] You changed \the [src]'s ammo preparation procedures. You now fire [secondary_toggled ? "armor shredding rounds" : "highly precise rounds"].")
+ balloon_alert(user, "firing [secondary_toggled ? "armor shredding" : "highly precise"]")
playsound(loc,'sound/machines/click.ogg', 25, 1)
ammo = secondary_toggled ? ammo_secondary : ammo_primary
var/datum/action/item_action/smartgun/toggle_ammo_type/TAT = locate(/datum/action/item_action/smartgun/toggle_ammo_type) in actions
@@ -388,7 +390,7 @@
return FALSE
return TRUE
if(!battery || battery.power_cell.charge == 0)
- to_chat(usr, SPAN_WARNING("[src] emits a low power warning and immediately shuts down!"))
+ balloon_alert(usr, "low power")
return FALSE
return FALSE
diff --git a/colonialmarines.dme b/colonialmarines.dme
index 50b122a0a2..9872ffc48e 100644
--- a/colonialmarines.dme
+++ b/colonialmarines.dme
@@ -1393,6 +1393,7 @@
#include "code\modules\admin\game_master\extra_buttons\toggle_join_xeno.dm"
#include "code\modules\admin\game_master\extra_buttons\toggle_vehicle_blockers.dm"
#include "code\modules\admin\game_master\game_master_submenu\ambush.dm"
+#include "code\modules\admin\game_master\game_master_submenu\infest.dm"
#include "code\modules\admin\game_master\game_master_submenu\tunnels.dm"
#include "code\modules\admin\game_master\game_master_submenu\vents.dm"
#include "code\modules\admin\medal_panel\medals_panel.dm"
diff --git a/tgui/packages/tgui/interfaces/GameMasterSubmenuInfest.js b/tgui/packages/tgui/interfaces/GameMasterSubmenuInfest.js
new file mode 100644
index 0000000000..05514969d2
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/GameMasterSubmenuInfest.js
@@ -0,0 +1,85 @@
+import { useBackend } from '../backend';
+import { Stack, Dropdown, Button, Section, Slider } from '../components';
+import { Window } from '../layouts';
+
+export const GameMasterSubmenuInfest = (props, context) => {
+ const { data, act } = useBackend(context);
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+export const GameMasterSubmenuInfestInfestingPanel = (props, context) => {
+ const { data, act } = useBackend(context);
+
+ return (
+
+
+
+
+
+ {
+ act('set_selected_hive', { new_hive });
+ }}
+ />
+
+
+
+ Embryo Stage
+
+ {
+ act('set_embryo_stage', { stage });
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};