diff --git a/modular_zzz/code/datums/actions/items/toggles.dm b/modular_zzz/code/datums/actions/items/toggles.dm
new file mode 100644
index 0000000000000..e677a61ca2c1d
--- /dev/null
+++ b/modular_zzz/code/datums/actions/items/toggles.dm
@@ -0,0 +1,29 @@
+/datum/action/item_action/no_drop_toggle
+ name = "No Drop"
+ desc = "Предмет не выпадет из рук!"
+ button_icon = 'icons/obj/weapons/hand.dmi'
+ button_icon_state = "disintegrate"
+
+/datum/action/item_action/no_drop_toggle/do_effect(trigger_flags)
+ . = ..()
+ if(!. || !isitem(target) || !ismob(usr))
+ return FALSE
+ var/obj/item/I = target
+ var/mob/M = usr
+ if(!M.is_holding(I))
+ return FALSE
+ if(HAS_TRAIT_FROM(I, TRAIT_NODROP, REF(src)))
+ REMOVE_TRAIT(I, TRAIT_NODROP, REF(src))
+ to_chat(M, "Ты расжимаешь хватку.")
+ else
+ ADD_TRAIT(I, TRAIT_NODROP, REF(src))
+ to_chat(M, "Ты цепляешься к предмету смертной хваткой!")
+ M.playsound_local(M, 'sound/items/equip/glove_equip.ogg', 100, FALSE)
+ build_all_button_icons()
+
+/datum/action/item_action/no_drop_toggle/apply_button_background(atom/movable/screen/movable/action_button/current_button, force)
+ if(!isnull(target) && HAS_TRAIT_FROM(target, TRAIT_NODROP, REF(src)))
+ background_icon_state = "bg_default_on"
+ else
+ background_icon_state = "bg_default"
+ . = ..()
diff --git a/modular_zzz/code/modules/antagonists/hatred/ak_hatred.dmi b/modular_zzz/code/modules/antagonists/hatred/ak_hatred.dmi
new file mode 100644
index 0000000000000..10959b63ed928
Binary files /dev/null and b/modular_zzz/code/modules/antagonists/hatred/ak_hatred.dmi differ
diff --git a/modular_zzz/code/modules/antagonists/hatred/ak_hatred_lefthand.dmi b/modular_zzz/code/modules/antagonists/hatred/ak_hatred_lefthand.dmi
new file mode 100644
index 0000000000000..c2ccf94bb25cf
Binary files /dev/null and b/modular_zzz/code/modules/antagonists/hatred/ak_hatred_lefthand.dmi differ
diff --git a/modular_zzz/code/modules/antagonists/hatred/ak_hatred_righthand.dmi b/modular_zzz/code/modules/antagonists/hatred/ak_hatred_righthand.dmi
new file mode 100644
index 0000000000000..0751bab79413e
Binary files /dev/null and b/modular_zzz/code/modules/antagonists/hatred/ak_hatred_righthand.dmi differ
diff --git a/modular_zzz/code/modules/antagonists/hatred/hatred.dm b/modular_zzz/code/modules/antagonists/hatred/hatred.dm
index f0593eac3a383..a398ed956358a 100644
--- a/modular_zzz/code/modules/antagonists/hatred/hatred.dm
+++ b/modular_zzz/code/modules/antagonists/hatred/hatred.dm
@@ -1,28 +1,10 @@
/**
* Данный антаг был вдоховлен игрою "Hatred" (2015).
*
- * Краткое пояснение концепта антага и игромеханических решений:
- * Концепт: мажорный мидраунд антаг для хард динамика с целью моментального массового ПВП пиздореза. Почти как Lone Operative, но этот не должен
- * просто закончить раунд, убив капитана. Минимум манча и времени на разогрев. Только при существенном онлайне и с достаточным количеством живых офицеров СБ.
- * Хил от убийства других игроков: как и в оригинальной игре персонаж восстанавливает здоровье от кинематографичных убийств (glory kills) и это является
- * единственным способом востановить здоровье. Я полагаю и в сске оно будет выглядеть уместно и вполне сбалансированно. Игроку для восстановления
- * здоровья необходимо заставить живую цель не двигаться вплоть до ~10 секунд и убить её выстрелом вплотную для восстановления здоровья. Тем самым мы снижаем
- * градус ахуевания антага и заставляем его делать передышики и играть аккуратнее, ведь он один, всегда уязвим и не может прятаться в космосе или вне станции,
- * как делает абсолютное большинство антагов.
- * Оружие с бесконечными патронами: в оригинальной игре по локации разбросана куча других оружий, а также оружие щедро падает с бесконечных волн
- * полицейских. Но в сске у нас ограниченное количество СБ, поэтому рано или поздно антаг пойдет манчить себе оружие. Этот антаг создан для пиздореза,
- * а не получасового манча оружейки, поэтому я хочу свести к минимуму любой существенный манч.
- * "Прикрученное намертво" снаряжение: всё минимально необходимое снаряжение намертво прикручено к персонажу. Оно хорошо сбалансированно
- * для ведения продолжительных пвп битв, но не является читами и накладывает массу ограничений, поэтому при возможности игрок скинул бы свое снаряжение и
- * взял бы что-то более мощное, убийственное или полезное, например МОДсьюты или хардсьюты ЕРТшников, но я ему не позволю, ибо как сказано в предыдущем
- * пункте: это антаг не для манча, а для моментального пиздореза.
- *
* Если будет востребованно, то я возможно сделаю:
* - Антаг худ (квадратик над персонажем с иконкой роли)
- * - Счетчик убийств и вывод его в итоги раунда (здесь мне нужна помощь, я не знаю, как считать сочные фраги).
- * - минимум убийств для получения гринтекста.
- * - события после определенного кол-ва убийств (если перебил пол станции)..
- * - Больше QOL фич, если у меня или других игроков будут хорошие и выполнимые идеи.
+ * - минимум убийств для получения гринтекста.
+ * - события после определенного кол-ва убийств
*/
//////////////////////////////////////////////
@@ -37,10 +19,10 @@
roundend_category = "Mass Shooter"
pref_flag = ROLE_MASS_SHOOTER
antag_moodlet = /datum/mood_event/focused
- suicide_cry = "I REGRET NOTHING."
show_to_ghosts = TRUE
show_in_antagpanel = FALSE // only for ghosts
antag_ticket_multiplier = 1
+ ui_name = "AntagInfoHatred"
var/list/allowed_z_levels = list()
/**
* Level of available gear is determined by a number of alive security officers and other conditions.
@@ -50,12 +32,12 @@
*/
var/gear_level = 1
// var/list/low_guns = list("Pistol", "Double-barreled shotgun") // NOT IMPLEMENTED YET!
- var/list/classic_guns = list("AK12", "Riot Shotgun", "Pistols")
+ var/list/classic_guns = list("AK12", "Combat Shotgun", "Pistols")
// there won't be special level 2 guns, because I don't want antag to have cheat guns. Level 2 gear is always better stats/traits for level 1 gear.
var/list/high_gear = list(/*"Belt of Hatred", */"More armor", "Faster executions")
var/chosen_gun = null
var/chosen_high_gear = null
- var/next_speech_time = 0
+ COOLDOWN_DECLARE(killing_speech_cd)
var/list/killing_speech = list( 'modular_zzz/code/modules/antagonists/hatred/killing_speech/hatred_speech_1.ogg',
'modular_zzz/code/modules/antagonists/hatred/killing_speech/hatred_speech_2.ogg',
'modular_zzz/code/modules/antagonists/hatred/killing_speech/hatred_speech_3.ogg',
@@ -72,7 +54,7 @@
'modular_zzz/code/modules/antagonists/hatred/killing_speech/hatred_speech_14.ogg'
)
var/list/allowed_guns = list( /obj/item/gun/ballistic/automatic/ar/ak12/hatred,
- /obj/item/gun/ballistic/shotgun/riot/hatred,
+ /obj/item/gun/ballistic/shotgun/automatic/combat/hatred,
/obj/item/gun/ballistic/automatic/pistol/m1911/hatred,
/obj/item/gun/ballistic/shotgun/doublebarrel/hatred_sawn_off
)
@@ -83,26 +65,55 @@
/datum/antagonist/hatred/get_preview_icon()
return finish_preview_icon(icon('modular_zzz/code/modules/antagonists/hatred/hatred_icon.dmi', "human"))
+/datum/antagonist/hatred/forge_objectives()
+ var/datum/objective/O = new /datum/objective/genocide()
+ O.owner = owner
+ objectives += O
+ O = new /datum/objective/martyr()
+ O.owner = owner
+ objectives += O
+
+/datum/objective/genocide
+ name = "Genocide of civilians"
+ explanation_text = "Убей столько народу, сколько успеешь за свою короткую оставшуюся жизнь. Не щади никого. Кровь слабых питает тебя."
+ martyr_compatible = TRUE
+ completed = TRUE // i have no idea how to count your personal kills.
+ var/glory_kills = 0
+
+/datum/antagonist/hatred/roundend_report()
+ . = ..()
+ var/datum/objective/genocide/objective = locate() in objectives
+ if(istype(objective))
+ . += "
[objective.glory_kills] ничтожных существ(а) было брутально и безжалостно добито массшутером."
+
/datum/antagonist/hatred/greet()
var/greet_text
greet_text += "Ты - [span_red(span_bold("Безымянный Массшутер"))]. Твое имя совершенно неважно. Твое прошлое даже если и было, оно было незавидным.
"
greet_text += "Ты испытываешь непреодолимую ненависть, отвращение и презрение ко всем окружающим.
"
greet_text += "У тебя лишь две цели: убивать и умереть славной смертью.
"
greet_text += "Твое проклятое снаряжение неразлучно с тобою и подстегивает тебя продолжать соврешать геноцид беззащитных гражданских.
"
- greet_text += "Твоё [span_red("Оружие Ненависти")] и неутолимая жажда убивать вознаграждают тебя, ибо завершающий выстрел в упор в голову (рот) исцеляет твои раны, нож добивает быстрее и надежнее. [span_red("Обычная медицина бессильна")].
"
+ greet_text += "Твоё [span_red("Оружие Ненависти")] и неутолимая жажда убивать вознаграждают тебя, ибо завершающий выстрел в упор в голову (рот) исцеляет твои раны, нож добивает быстрее и надежнее.
"
+ greet_text += span_red("Обычная медицина бессильна, а чужое оружие бесполезно для тебя.")
if(chosen_gun == "Pistols")
- greet_text += "[span_red("Кобура Ненависти")] всегда готова предоставить тебе особое парное оружие (стрелять с двух рук - в харме). После использования можешь просто выбросить их, ибо их цель была выполнена.
"
+ greet_text += "[span_red("Кобура Ненависти")] всегда готова предоставить тебе особое парное оружие. [span_red("Стрелять с двух рук - в Харме")]. После использования можешь просто выбросить их, ибо их цель была выполнена.
"
else
- greet_text += "[span_red("Cумка для патронов")] сама пополняет пустые магазины/картриджи/клипсы. Никогда не выбрасывай их!
"
- if(chosen_gun == "Riot Shotgun")
- greet_text += "В твоей кобуре спрятан [span_red("запасной дробовик")], чтобы у тебя всегда под рукой был План Б.
"
- // if(chosen_high_gear == "Belt of Hatred")
+ greet_text += "[span_red("Cумка для патронов")] сама пополняет пустые магазины/картриджи/клипсы для твоего оружия. Никогда не выбрасывай их!
"
+ // if(chosen_gun == "Combat Shotgun")
+ // greet_text += "Ты захватил с собой [span_red("запасной дробовик")], чтобы у тебя всегда под рукой был План Б.
"
if(!isnull(chosen_high_gear))
greet_text += "[span_red("Пояс с гранатами")] пожирает сердца твоих жертв после их добивания и вознаграждает тебя новой взрывоопасной аммуницией.
"
greet_text += "[span_red(span_bold("Убивай и будь убит!"))] Ибо никто сегодня не защищен от твоей Ненависти.
"
to_chat(owner.current, greet_text)
+ antag_memory = greet_text
owner.announce_objectives()
+/datum/antagonist/hatred/ui_static_data(mob/user)
+ . = ..()
+ if(!islist(.))
+ return
+ .["pistols"] = (chosen_gun == "Pistols")
+ .["belt"] = !isnull(chosen_high_gear)
+
/datum/antagonist/hatred/on_gain()
var/mob/living/carbon/human/H = owner.current
if(!istype(H))
@@ -110,16 +121,24 @@
make_authentic_body()
evaluate_security()
forge_objectives()
- H.Immobilize(INFINITY, TRUE) // we don't want the player to walk around in temorary debug room during equipment selection.
- // H.Paralyze(INFINITY, TRUE)
- // H.SetParalyzed(0, TRUE)
+ RegisterSignal(H, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(prevent_spawnloc_movement))
+ RegisterSignal(H, COMSIG_MOB_EQUIPPED_ITEM, PROC_REF(check_equipped_item)) // any knife we pick might be our deadliest weapon
H.equipOutfit(/datum/outfit/hatred)
. = ..()
- H.add_movespeed_mod_immunities("hatred", /datum/movespeed_modifier/damage_slowdown) // I want him to be a bit slower, but indomitable by mere pain.
H.add_movespeed_modifier(/datum/movespeed_modifier/hatred)
- // H.add_movespeed_mod_immunities("hatred", /datum/movespeed_modifier/sanity) // this doesn't work due to subtypes
// Unpredictable mood changes makes it diffcult to balance antag's speed.
+ H.add_movespeed_mod_immunities("hatred", /datum/movespeed_modifier/damage_slowdown) // I want him to be a bit slower, but indomitable by mere pain.
+ H.add_movespeed_mod_immunities("hatred", MOVESPEED_ID_SANITY)
+ // just to be sure
+ for(var/ms in typesof(/datum/movespeed_modifier/sanity))
+ H.add_movespeed_mod_immunities("hatred", ms)
+ owner.current.add_personality(/datum/personality/introvert)
+ owner.current.add_personality(/datum/personality/callous)
H.mob_mood?.mood_modifier -= 1 //Basically nothing can change your mood
+ // сверхскорость и неуловимость страшнее сверхброни и бесконечных патронов
+ for(var/datum/movespeed_modifier/ms in typesof(/datum/movespeed_modifier/reagent))
+ if(ms.multiplicative_slowdown < 0)
+ H.add_movespeed_mod_immunities("hatred", ms)
// SPECIAL TRAITS
ADD_TRAIT(H, TRAIT_SLEEPIMMUNE, "hatred") // I challenge you to a glorious fight!
ADD_TRAIT(H, TRAIT_VIRUS_RESISTANCE, "hatred")
@@ -131,6 +150,9 @@
ADD_TRAIT(H, TRAIT_NODISMEMBER, "hatred") // if a player loses his arm, he won't be able to shoot nor drop his gun. it would be unplayable.
ADD_TRAIT(H, TRAIT_UNCONVERTABLE, "hatred")
// ADD_TRAIT(H, TRAIT_NOSOFTCRIT, "hatred")
+ ADD_TRAIT(H, TRAIT_NOLIMBDISABLE, "hatred")
+ for(var/obj/item/bodypart/bp as anything in H.bodyparts)
+ bp.can_be_disabled = FALSE
// GENERAL QUIRKS
H.add_quirk(/datum/quirk/night_vision, announce = FALSE) // ADD_TRAIT(H, TRAIT_NIGHT_VISION, "hatred")
H.add_quirk(/datum/quirk/throwingarm, announce = FALSE) // ADD_TRAIT(H, TRAIT_THROWINGARM, "hatred")
@@ -141,7 +163,8 @@
ADD_TRAIT(H, TRAIT_EVIL, "hatred") // H.add_quirk(/datum/quirk/evil, announce = FALSE) // no unwanted post_add() text
tgui_alert(H, "У тебя есть последняя минута, чтобы собраться с мыслями. Ознакомься с инструкциями в чате. Закрой это окошко когда будешь готов...", "Ты готов убивать?", list("Я готов убивать."), timeout = 1 MINUTES, autofocus = FALSE)
// WE ARE READY.
- H.SetImmobilized(0, TRUE)
+ UnregisterSignal(H, COMSIG_MOVABLE_PRE_MOVE)
+ RegisterSignal(H, COMSIG_LIVING_DEATH, PROC_REF(on_hatred_death))
H.fully_heal() // in case of some accidents in spawn room during preparation
H.mob_mood?.set_sanity(initial(H.mob_mood?.sanity), override = TRUE)
appear_on_station()
@@ -150,15 +173,47 @@
allowed_z_levels += SSmapping.levels_by_trait(ZTRAIT_STATION)
RegisterSignal(H, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(check_hatred_off_station)) // almost like anchor implant, but doesn't hurt
RegisterSignals(H, COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES, PROC_REF(on_try_healing)) // for AdjustXXXLoss()
- RegisterSignal(H, COMSIG_MOB_EQUIPPED_ITEM, PROC_REF(check_knife)) // any knife we pick might be our deadliest weapon
RegisterSignal(H, COMSIG_MOB_TRYING_TO_FIRE_GUN, PROC_REF(check_used_gun))
playsound(H, pick('modular_zzz/code/modules/antagonists/hatred/hatred_begin_1.ogg', \
'modular_zzz/code/modules/antagonists/hatred/hatred_begin_2.ogg', \
- 'modular_zzz/code/modules/antagonists/hatred/hatred_begin_3.ogg'), vol = 50, vary = FALSE, ignore_walls = FALSE)
+ 'modular_zzz/code/modules/antagonists/hatred/hatred_begin_3.ogg'), vol = 100, vary = FALSE, ignore_walls = FALSE)
addtimer(CALLBACK(src, PROC_REF(alarm_station)), 5 SECONDS, TIMER_DELETE_ME) // Think FAST.
+/datum/antagonist/hatred/on_removal()
+ var/mob/living/L = owner.current
+ UnregisterSignal(L, COMSIG_MOVABLE_Z_CHANGED)
+ UnregisterSignal(L, COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES)
+ UnregisterSignal(L, COMSIG_MOB_EQUIPPED_ITEM)
+ UnregisterSignal(L, COMSIG_MOB_TRYING_TO_FIRE_GUN)
+ UnregisterSignal(L, COMSIG_LIVING_DEATH)
+ . = ..()
+ if(!QDELETED(L) && istype(L))
+ ADD_TRAIT(L, TRAIT_PREVENT_IMPLANT_AUTO_EXPLOSION, "hatred") // no boom on admin remove
+ to_chat(L, span_userdanger("As Hatred leaves your mind, it consumes you completely..."))
+ L.dust(force = TRUE) // from ghosts we come, to ghosts we leave.
+
+/// Железно запрещаем перемещение по стартовой локации ерроров
+/datum/antagonist/hatred/proc/prevent_spawnloc_movement()
+ SIGNAL_HANDLER
+ return COMPONENT_MOVABLE_BLOCK_PRE_MOVE
+
+/datum/antagonist/hatred/proc/on_hatred_death()
+ SIGNAL_HANDLER
+ switch(chosen_gun)
+ if("Pistols")
+ var/obj/item/clothing/suit/jacket/leather_trenchcoat/hatred/I = new (get_turf(owner.current))
+ I.desc = "The blood stained shabby leather overcoat with decent armor paddings and special lightweight kevlar."
+ addtimer(CALLBACK(I, TYPE_PROC_REF(/obj/item/clothing, repair)), 3 SECONDS, TIMER_DELETE_ME)
+ else
+ // предотвращаем уничтожение уникального оружия на спине
+ var/mob/living/L = owner.current
+ if(istype(L))
+ var/obj/item/I = L.get_item_by_slot(ITEM_SLOT_SUITSTORE)
+ if(istype(I))
+ I.forceMove(L.drop_location())
+
/datum/movespeed_modifier/hatred
- multiplicative_slowdown = 0.6
+ multiplicative_slowdown = 0.5
/datum/antagonist/hatred/proc/evaluate_security()
var/gear_points = length(SSjob.get_living_sec())
@@ -172,13 +227,10 @@
gear_points++
if(length(active_ais(check_mind = TRUE, skip_syndicate = TRUE))) // вертолеты
gear_points++
- switch(gear_points)
- // if(-INFINITY to 4)
- // gear_level = 0
- if(-INFINITY to 5) // 5
- gear_level = 1
- if(7 to INFINITY) // 7+
- gear_level = 2
+ if(gear_points < 7)
+ gear_level = 1 // 5-6
+ else
+ gear_level = 2 // 7+
/datum/antagonist/hatred/proc/make_authentic_body()
var/mob/living/carbon/human/H = owner.current
@@ -208,20 +260,6 @@
H.update_body(TRUE)
H.update_hair()
-/datum/antagonist/hatred/forge_objectives()
- var/datum/objective/O = new /datum/objective/genocide()
- O.owner = owner
- objectives += O
- O = new /datum/objective/martyr()
- O.owner = owner
- objectives += O
-
-/datum/objective/genocide
- name = "Genocide of civilians"
- explanation_text = "Убей столько народу, сколько успеешь за свою короткую оставшуюся жизнь. Не щади никого. Кровь слабых питает тебя."
- martyr_compatible = TRUE
- completed = TRUE // i have no idea how to count your personal kills.
-
/datum/antagonist/hatred/proc/appear_on_station()
var/list/possible_spawns = list()
possible_spawns += get_safe_random_station_turf(typesof(/area/station/command/gateway)) // 1/7 is ~15%
@@ -247,7 +285,7 @@
return NONE
/datum/antagonist/hatred/proc/alarm_station() // major antag is currently commencing genocide, so we must let everyone know.
- if(istype(src) && owner?.current)
+ if(istype(src) && owner?.current && owner?.current.stat != DEAD)
var/chosen_sound = pick('modular_zzz/code/modules/antagonists/hatred/hatred_spawned_1.ogg','modular_zzz/code/modules/antagonists/hatred/hatred_spawned_2.ogg')
priority_announce("На ваш объект ворвался особо опасный вооруженный преступник с целью массового убийства гражданских лиц. \
Нейтрализуйте угрозу любыми доступными средствами. \
@@ -256,11 +294,12 @@
"ALERT: MASS SHOOTER!", chosen_sound, has_important_message = TRUE)
/// we check if we picked up a knife in our hand. if so, we listen to it when it strikes its target.
-/datum/antagonist/hatred/proc/check_knife(mob/source, obj/item/I, slot)
+/datum/antagonist/hatred/proc/check_equipped_item(mob/source, obj/item/I, slot)
SIGNAL_HANDLER
- if(istype(I, /obj/item/knife) && slot == ITEM_SLOT_HANDS && ishuman(source))
- RegisterSignal(I, COMSIG_ITEM_ATTACK, PROC_REF(knife_check_glory))
- RegisterSignal(I, COMSIG_ITEM_DROPPED, PROC_REF(remove_knife_check_glory))
+ if(ishuman(source) && slot == ITEM_SLOT_HANDS)
+ if(istype(I, /obj/item/knife))
+ RegisterSignal(I, COMSIG_ITEM_DROPPED, PROC_REF(remove_knife_check_glory))
+ RegisterSignal(I, COMSIG_ITEM_ATTACK, PROC_REF(knife_check_glory))
/// once we don't hold a knife, we don't listen to it when it strikes.
/datum/antagonist/hatred/proc/remove_knife_check_glory(obj/item/knife/K, mob/user)
@@ -269,7 +308,7 @@
UnregisterSignal(K, COMSIG_ITEM_DROPPED)
/// if we strike a target and it meets certain criteria - we handle it in a special way.
-/datum/antagonist/hatred/proc/knife_check_glory(obj/item/knife/K, mob/living/target_mob, mob/user, list/modifiers, list/attack_modifiers)
+/datum/antagonist/hatred/proc/knife_check_glory(obj/item/knife/knife, mob/living/target_mob, mob/user, list/modifiers, list/attack_modifiers)
SIGNAL_HANDLER
if(ishuman(target_mob) && ishuman(user) && target_mob != user)
if(length(attack_modifiers) && attack_modifiers[FORCE_OVERRIDE] == 200) // no need to check. the lethal strike is about to be blown.
@@ -278,33 +317,37 @@
var/mob/living/carbon/human/killer = user
// the target is dead and we want its heart for the Belt of Hatred.
if(target.stat == DEAD && killer.zone_selected == BODY_ZONE_CHEST && target.get_bodypart(BODY_ZONE_CHEST))
- var/datum/wound/loss/dismembering = new
- dismembering.apply_dismember(target.get_bodypart(BODY_ZONE_CHEST), outright = TRUE)
+ var/obj/item/organ/heart/h = locate() in target.get_bodypart(BODY_ZONE_CHEST)
+ if(istype(h) && h.drop_when_organ_spilling)
+ h.Remove(target)
+ user.visible_message(span_bold(span_danger("[user] безжалостно вырывает сердце из груди [target]!")))
+ if(!killer.put_in_inactive_hand(h))
+ h.forceMove(get_turf(target))
// the target is almost dead and we want to glory kill it with a knife.
else if(!(target.stat in list(CONSCIOUS)) && killer.zone_selected == BODY_ZONE_PRECISE_MOUTH && !isdullahan(target) && target.get_bodypart(BODY_ZONE_HEAD))
- target.visible_message(span_warning("[killer] brings [K] to [target]'s throat, ready to slit it open..."), \
- span_userdanger("[killer] brings [K] to your throat, ready to slit it open..."))
+ target.visible_message(span_warning("[killer] подносит [knife] к горлу [target], готовый перерезать его..."), \
+ span_userdanger("[killer] подносит [knife] к твоему горлу, готовый перерезать его..."))
// it's a signal handler so we don't sleep
- INVOKE_ASYNC(src, PROC_REF(knife_glory_kill), target, K, killer, modifiers, attack_modifiers)
+ INVOKE_ASYNC(src, PROC_REF(knife_glory_kill), knife, target, killer, modifiers, attack_modifiers)
return COMPONENT_CANCEL_ATTACK_CHAIN
/// target is in crit and about to be executed.
-/datum/antagonist/hatred/proc/knife_glory_kill(mob/living/carbon/human/target, obj/item/knife/knife, mob/living/carbon/human/killer, list/modifiers, list/attack_modifiers)
+/datum/antagonist/hatred/proc/knife_glory_kill(obj/item/knife/knife, mob/living/carbon/human/target, mob/living/carbon/human/killer, list/modifiers, list/attack_modifiers)
var/is_glory = TRUE
// already dead bodies or npcs don't count
// if((!target.client && ((world.time - target.lastclienttime) > 10 SECONDS)) || (target.stat == DEAD && ((world.time - target.timeofdeath) > 3 SECONDS)))
if(!target.client || target.stat == DEAD)
is_glory = FALSE
- else if(next_speech_time <= world.time)
- playsound(owner.current, pick(killing_speech), vol = 50, vary = FALSE, ignore_walls = FALSE)
- next_speech_time = world.time + 10 SECONDS
- var/time_to_kill = chosen_high_gear == "Faster executions" ? 4 SECONDS : 6 SECONDS
+ else if(COOLDOWN_FINISHED(src, killing_speech_cd))
+ playsound(owner.current, pick(killing_speech), vol = 100, vary = FALSE, ignore_walls = FALSE)
+ COOLDOWN_START(src, killing_speech_cd, 10 SECONDS)
+ var/time_to_kill = chosen_high_gear == "Faster executions" ? 5 SECONDS : 7 SECONDS
if(do_after(killer, time_to_kill, target))
- target.visible_message(span_warning("[killer] slits [target]'s throat!"), span_userdanger("[killer] slits your throat!"))
+ target.visible_message(span_warning("[killer] перерезает горло [target]!"), span_userdanger("[killer] перерезает твое горло!"))
SET_ATTACK_FORCE(attack_modifiers, 200)
// knife.attack(target, killer, modifiers, attack_modifiers)
knife.melee_attack_chain(killer, target, modifiers, attack_modifiers)
- while(target.stat != DEAD && target.IsReachableBy(killer, knife))
+ while(!QDELETED(target) && target.stat != DEAD && target.IsReachableBy(killer, knife))
if(!do_after(killer, 0.5 SECONDS, target))
break
if(!knife.melee_attack_chain(killer, target, modifiers, attack_modifiers))
@@ -312,7 +355,7 @@
if(is_glory)
addtimer(CALLBACK(knife, TYPE_PROC_REF(/obj/item/knife, check_glory_kill), killer, target), 1 SECONDS, TIMER_DELETE_ME)
else
- target.visible_message(span_notice("[killer] stopped his knife."), span_notice("[killer] stopped his knife!"))
+ killer.visible_message(span_notice("[killer] остановил свой нож."))
/datum/antagonist/hatred/proc/check_used_gun(mob/living/carbon/human/H, obj/item/gun/G, target, flag, params)
SIGNAL_HANDLER
@@ -322,18 +365,6 @@
to_chat(H, span_userdanger("You have no need for this. You have your own killing machines."))
return COMPONENT_CANCEL_GUN_FIRE
-/datum/antagonist/hatred/on_removal()
- var/mob/living/L = owner.current
- UnregisterSignal(L, COMSIG_MOVABLE_Z_CHANGED)
- UnregisterSignal(L, COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES)
- UnregisterSignal(L, COMSIG_MOB_EQUIPPED_ITEM)
- UnregisterSignal(L, COMSIG_MOB_TRYING_TO_FIRE_GUN)
- . = ..()
- if(!QDELETED(L) && istype(L))
- ADD_TRAIT(L, TRAIT_PREVENT_IMPLANT_AUTO_EXPLOSION, "hatred") // no boom on admin remove
- to_chat(L, span_userdanger("As Hatred leaves your mind, it consumes you completely..."))
- L.dust(force = TRUE) // from ghosts we come, to ghosts we leave.
-
/obj/item/gun/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params, bypass_timer, time_to_kill = 12 SECONDS)
var/datum/antagonist/hatred/Ha = user.mind.has_antag_datum(/datum/antagonist/hatred)
if(!Ha || !ishuman(target))
@@ -345,24 +376,26 @@
// if((!target.client && ((world.time - target.lastclienttime) > 10 SECONDS)) || (target.stat == DEAD && ((world.time - target.timeofdeath) > 3 SECONDS)))
if(!target.client || target.stat == DEAD)
is_glory = FALSE
- else if(Ha.next_speech_time <= world.time)
- playsound(user, pick(Ha.killing_speech), vol = 50, vary = FALSE, ignore_walls = FALSE)
- Ha.next_speech_time = world.time + 10 SECONDS
- var/new_ttk = Ha.chosen_high_gear == "Faster executions" ? 6 SECONDS : 8 SECONDS
+ else if(COOLDOWN_FINISHED(Ha, killing_speech_cd))
+ playsound(user, pick(Ha.killing_speech), vol = 100, vary = FALSE, ignore_walls = FALSE)
+ COOLDOWN_START(Ha, killing_speech_cd, 10 SECONDS)
+ var/new_ttk = Ha.chosen_high_gear == "Faster executions" ? 8 SECONDS : 10 SECONDS
. = ..(user, target, params, bypass_timer, time_to_kill = new_ttk)
if(!. || user == target || !is_glory)
return
addtimer(CALLBACK(src, PROC_REF(check_glory_kill), user, target), 1 SECONDS, TIMER_DELETE_ME) // wait for boolet to do its job
/obj/item/proc/check_glory_kill(mob/living/carbon/human/user, mob/living/carbon/human/target)
- if((QDELETED(target) || target?.stat == DEAD) && !QDELETED(user) && (user?.stat in list(CONSCIOUS, SOFT_CRIT)))
+ if((QDELETED(target) || target?.stat == DEAD) && !QDELETED(user) && user?.stat != DEAD)
user.fully_heal() // the only way of healing
// user.do_adrenaline(150, TRUE, 0, 0, TRUE, list(/datum/reagent/medicine/inaprovaline = 10, /datum/reagent/medicine/synaptizine = 15, /datum/reagent/medicine/regen_jelly = 20, /datum/reagent/medicine/stimulants = 20), "You feel a sudden surge of energy!")
- user.visible_message("As victim's blood splashes onto [src], it starts glowing menacingly and its wielder seemingly regaining his strength and vitality.")
- to_chat(user, span_notice("The blood of the weak gives you an inhuman relief and strength to continue the massacre."))
+ user.visible_message("Кровь жертвы окрапляет [user], даруя ему нечеловеческое облегчение и силу продолжать бойню.")
+ var/datum/antagonist/hatred/Ha = user.mind?.has_antag_datum(/datum/antagonist/hatred)
+ var/datum/objective/genocide/objective = locate() in Ha?.objectives
+ objective?.glory_kills++
var/obj/item/storage/belt/military/assault/hatred/B = user.get_item_by_slot(ITEM_SLOT_BELT)
if(istype(B))
- to_chat(user, span_notice("[B.name] hungrily growls in anticipation of the coming sacrifice."))
+ to_chat(user, span_notice("[B.name] жадно урчит в предвкушении скорого жертвоприношения."))
B.glory_points++
//////////////////////////////////////////////
@@ -375,8 +408,14 @@
// we don't have ak47. what a disappointment. wake me up when we have one.
/obj/item/gun/ballistic/automatic/ar/ak12/hatred
- name = "\proper AK-12 rifle of Hatred"
- desc = "The scratches on this rifle say: \"The Genocide Machine\"."
+ name = "\improper AK-12 rifle of Hatred"
+ desc = "Wooden stock modified rifle. The scratches on this rifle say: \"The Genocide Machine\"."
+ // Аутентичного ак47 я не дождусь.
+ icon = 'modular_zzz/code/modules/antagonists/hatred/ak_hatred.dmi'
+ icon_state = "ak47"
+ inhand_icon_state = "ak47"
+ lefthand_file = 'modular_zzz/code/modules/antagonists/hatred/ak_hatred_lefthand.dmi'
+ righthand_file = 'modular_zzz/code/modules/antagonists/hatred/ak_hatred_righthand.dmi'
resistance_flags = FIRE_PROOF | ACID_PROOF
max_integrity = 400 // will be damaged during antag's death implant detonation
burst_fire_selection = FALSE
@@ -384,78 +423,98 @@
burst_size = 1
burst_delay = 2
weapon_weight = WEAPON_HEAVY
+ w_class = WEIGHT_CLASS_BULKY
// 100% = 35
// 90% = 32
// 85% = 30
// 80% = 28
projectile_damage_multiplier = 0.8
- var/mob/living/carbon/human/original_owner = null
- var/is_trophy = FALSE
+
+// /obj/item/gun/ballistic/automatic/ar/ak12/hatred/attack_hand(mob/user, list/modifiers)
+// . = ..()
/obj/item/gun/ballistic/automatic/ar/ak12/hatred/Initialize(mapload)
. = ..()
+ add_item_action(/datum/action/item_action/no_drop_toggle)
AddComponent(/datum/component/automatic_fire, 0.2 SECONDS)
-/obj/item/gun/ballistic/automatic/ar/ak12/hatred/examine(mob/user)
+/obj/item/gun/ballistic/automatic/ar/ak12/hatred/update_icon_state()
. = ..()
- if(HAS_TRAIT(src, TRAIT_NODROP))
- . += span_danger("You cannot make your fingers drop this weapon of Doom.")
+ if(magazine)
+ icon_state = "ak47"
+ else
+ icon_state = "ak47_e"
-/obj/item/gun/ballistic/automatic/ar/ak12/hatred/equipped(mob/living/user, slot)
+/obj/item/gun/ballistic/automatic/ar/ak12/hatred/ui_action_click(mob/user, actiontype)
+ if(istype(actiontype, /datum/action/item_action/no_drop_toggle))
+ return
. = ..()
- if(!is_trophy)
- if(isnull(original_owner))
- original_owner = user
- RegisterSignal(original_owner, COMSIG_LIVING_DEATH, PROC_REF(on_hatred_death))
- if(original_owner == user)
- ADD_TRAIT(src, TRAIT_NODROP, "hatred")
-/obj/item/gun/ballistic/automatic/ar/ak12/hatred/proc/on_hatred_death()
- SIGNAL_HANDLER
- desc = "The blood stained scratches on this rifle say: \"The Genocide Machine\"."
- is_trophy = TRUE
- REMOVE_TRAIT(src, TRAIT_NODROP, "hatred")
+/obj/item/gun/ballistic/automatic/ar/ak12/hatred/give_gun_safeties()
+ return
-/obj/item/gun/ballistic/automatic/ar/ak12/hatred/dropped(mob/user, silent)
+/obj/item/gun/ballistic/automatic/ar/ak12/hatred/dropped(mob/user, silent) // lost arm or something else
. = ..()
- if(!is_trophy)
- if(user == original_owner) // lost arm or something else
- REMOVE_TRAIT(src, TRAIT_NODROP, "hatred")
+ REMOVE_TRAIT(src, TRAIT_NODROP, null)
/// THE SHOTGUN OF HATRED ///
-/obj/item/gun/ballistic/shotgun/riot/hatred
- name = "\proper Riot Shotgun of Hatred"
+/obj/item/gun/ballistic/shotgun/automatic/combat/hatred
+ name = "\improper Combat Shotgun of Hatred"
desc = "The scratches on this shotgun say: \"The Bringer of Doom\"."
- accepted_magazine_type = /obj/item/ammo_box/magazine/internal/shot/hatred
+ icon = 'icons/obj/weapons/guns/ballistic.dmi'
+ lefthand_file = 'icons/mob/inhands/weapons/64x_guns_left.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/64x_guns_right.dmi'
+ inhand_x_dimension = 64
+ inhand_y_dimension = 64
+ icon_state = "cshotgun"
+ inhand_icon_state = "shotgun_combat"
+ accepted_magazine_type = /obj/item/ammo_box/magazine/internal/shot/com/hatred
resistance_flags = FIRE_PROOF | ACID_PROOF
max_integrity = 400 // will be damaged during antag's death implant detonation
box_reload_penalty = FALSE
- fire_delay = 4
- rack_delay = 4
- var/mob/living/carbon/human/original_owner = null
+ // fire_delay = 4
+ // rack_delay = 4
+ unique_reskin = null
var/quick_empty_flag = FALSE // is user quick emptying it right now
- var/is_trophy = FALSE
-/obj/item/ammo_box/magazine/internal/shot/hatred
- ammo_type = /obj/item/ammo_box/advanced/s12gauge
+/obj/item/ammo_box/magazine/internal/shot/com/hatred
+ ammo_type = /obj/item/ammo_casing/shotgun/buckshot
max_ammo = 6 // there are 7 shells in default ammo boxes, so shotgun has perfect 6+1 slots.
-/obj/item/gun/ballistic/shotgun/riot/hatred/give_manufacturer_examine()
+/obj/item/gun/ballistic/shotgun/automatic/combat/hatred/Initialize(mapload)
+ . = ..()
+ add_item_action(/datum/action/item_action/no_drop_toggle)
+
+/obj/item/gun/ballistic/shotgun/automatic/combat/hatred/examine(mob/user)
+ . = ..()
+ . += span_notice("[span_bold("Ctrl-Shift-Click")] - быстрая разрядка.")
+
+/obj/item/gun/ballistic/shotgun/automatic/combat/hatred/ui_action_click(mob/user, actiontype)
+ if(istype(actiontype, /datum/action/item_action/no_drop_toggle))
+ return
+ . = ..()
+
+/obj/item/gun/ballistic/shotgun/automatic/combat/hatred/give_manufacturer_examine()
return // no more "Nanotrasen Armories"
-/obj/item/gun/ballistic/shotgun/riot/hatred/examine(mob/user)
+/obj/item/gun/ballistic/shotgun/automatic/combat/hatred/give_gun_safeties()
+ return
+
+/obj/item/gun/ballistic/shotgun/automatic/combat/hatred/dropped(mob/user, silent) // lost arm, etc...
. = ..()
- . += span_notice("[span_bold("Ctrl-Shift-Click")] to quickly empty [src].")
- if(HAS_TRAIT(src, TRAIT_NODROP))
- . += span_danger("You cannot make your fingers drop this weapon of Doom.")
+ REMOVE_TRAIT(src, TRAIT_NODROP, null)
+
+/obj/item/gun/ballistic/shotgun/automatic/combat/hatred/attack_self(mob/living/user)
+ if(!quick_empty_flag)
+ . = ..()
// говно с оффов не обрабатывает обновление счетчика патронов при перезарядке
-/obj/item/gun/ballistic/shotgun/riot/hatred/load_gun(obj/item/ammo, mob/living/user)
+/obj/item/gun/ballistic/shotgun/automatic/combat/hatred/load_gun(obj/item/ammo, mob/living/user)
. = ..()
SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD)
-/obj/item/gun/ballistic/shotgun/riot/hatred/click_ctrl_shift(mob/user)
+/obj/item/gun/ballistic/shotgun/automatic/combat/hatred/click_ctrl_shift(mob/user)
if(!quick_empty_flag)
quick_empty_flag = TRUE
rack()
@@ -464,27 +523,6 @@
rack()
quick_empty_flag = FALSE
-/obj/item/gun/ballistic/shotgun/riot/hatred/equipped(mob/living/user, slot)
- . = ..()
- if(!is_trophy)
- if(isnull(original_owner))
- original_owner = user
- RegisterSignal(original_owner, COMSIG_LIVING_DEATH, PROC_REF(on_hatred_death))
- if(original_owner == user)
- ADD_TRAIT(src, TRAIT_NODROP, "hatred")
-
-/obj/item/gun/ballistic/shotgun/riot/hatred/proc/on_hatred_death()
- SIGNAL_HANDLER
- desc = "The blood stained scratches on this shotgun say: \"The Bringer of Doom\"."
- is_trophy = TRUE
- REMOVE_TRAIT(src, TRAIT_NODROP, "hatred")
-
-/obj/item/gun/ballistic/shotgun/riot/hatred/dropped(mob/user, silent)
- . = ..()
- if(!is_trophy)
- if(user == original_owner) // lost arm or something else
- REMOVE_TRAIT(src, TRAIT_NODROP, "hatred")
-
/// THE PLAN B ///
/obj/item/gun/ballistic/shotgun/doublebarrel/hatred_sawn_off
@@ -543,6 +581,9 @@
// MAGAZINE_TYPE_ARMORPIERCE
// ammo_type = /obj/item/ammo_casing/c45/ap
+/obj/item/gun/ballistic/automatic/pistol/m1911/hatred/give_gun_safeties()
+ return
+
/obj/item/gun/ballistic/automatic/pistol/m1911/hatred/equipped(mob/user, slot, initial)
. = ..()
if(isnull(original_owner) && ishuman(loc) && slot == ITEM_SLOT_HANDS)
@@ -568,18 +609,29 @@
return
postfire_empty_checks(.)
-/obj/item/gun/ballistic/automatic/pistol/m1911/hatred/postfire_empty_checks(last_shot_succeeded)
+/obj/item/gun/ballistic/automatic/pistol/m1911/hatred/shoot_with_empty_chamber(mob/living/user)
. = ..()
- if(bolt_locked && ishuman(loc))
+ if(ishuman(loc))
var/mob/living/carbon/human/H = loc
H.dropItemToGround(src, force = TRUE, silent = FALSE)
- H.visible_message("[H] nonchalantly drops his empty pistol on the ground as soon as he makes a last shot.")
+ H.visible_message("[H] с безразличием бросает на землю пустой пистолет.")
+ var/obj/item/gun/ballistic/automatic/pistol/m1911/hatred/second = user.get_inactive_held_item()
+ if(istype(second, type))
+ if(!second.can_shoot() || !second.chambered || !second.chambered.loaded_projectile)
+ addtimer(CALLBACK(second, TYPE_PROC_REF(/obj/item/gun, shoot_with_empty_chamber), user), 2)
+
+// /obj/item/gun/ballistic/automatic/pistol/m1911/hatred/postfire_empty_checks(last_shot_succeeded)
+// . = ..()
+// if(bolt_locked && ishuman(loc))
+// var/mob/living/carbon/human/H = loc
+// H.dropItemToGround(src, force = TRUE, silent = FALSE)
+// H.visible_message("[H] nonchalantly drops his empty pistol on the ground as soon as he makes a last shot.")
/// THE HOLSTER OF HATRED ///
/obj/item/storage/belt/holster/hatred
name = "\proper Holster of Hatred"
- desc = "The cursed holster is always ready to supply you with new tools of Genocide."
+ desc = "Кобура Ненависти воплощает смертоностные, но недолговечные пистолеты."
resistance_flags = FIRE_PROOF | ACID_PROOF
/obj/item/storage/belt/holster/hatred/Initialize(mapload)
@@ -600,7 +652,6 @@
/obj/item/storage/belt/holster/hatred/dropped(mob/user, silent)
. = ..()
if(!QDELETED(src))
- // REMOVE_TRAIT(src, TRAIT_NODROP, "hatred")
visible_message("[src] рассыпается в прах на ваших глазах...")
qdel(src)
@@ -615,7 +666,7 @@
/obj/item/storage/pouch/ammo/hatred
name = "\proper Ammo pouch of Hatred"
- desc = "The cursed pouch with infinite bullets encourage you to relentlessly continue your atrocities against humanity. What a miracle and delight for your Genocide Machines."
+ desc = "Проклятый Подсумок Ненависти пополняет твои пустые магазины для твоих Машин Геноцида, подстегивая тебя продолжать бесчеловечную бойню."
unique_reskin = null
resistance_flags = FIRE_PROOF | ACID_PROOF
// uses_advanced_reskins = FALSE
@@ -632,9 +683,8 @@
/obj/item/storage/pouch/ammo/hatred/examine(mob/user)
. = ..()
- . += "If you place an empty magazine/clip into this phenomenal pouch next time you check it will be filled with bullets."
- . += span_notice("Click [span_bold("RMB")] to open.")
- . += span_notice("Once you lose this item it will turn into dust.")
+ . += "Положи пустой магазин/картридж/клипсу в этот проклятый подсумок и он наполнится патронами."
+ . += span_notice("[span_bold("Alt-Click / ПКМ")] - открыть.")
/obj/item/storage/pouch/ammo/hatred/Entered(atom/movable/AM, atom/oldLoc)
. = ..()
@@ -658,15 +708,14 @@
/obj/item/storage/belt/military/assault/hatred
name = "\proper Belt of Hatred"
- desc = "The cursed belt eagerly devours hearts of your victims and supplies you with new deadly explosives."
+ desc = "Проклятый Пояс Ненависти жадно поглощает сердца твоих жертв и вознаграждает тебя смертоностной аммуницией."
resistance_flags = FIRE_PROOF | ACID_PROOF
var/glory_points = 0
/obj/item/storage/belt/military/assault/hatred/examine(mob/user)
. = ..()
- . += "If you place a heart into this phenomenal belt next time you check there will be no heart but a deadly explosive."
- . += span_notice("[src] is ready to accept [span_bold("[glory_points]")] hearts. Get more Glory Kills to make it accept more.")
- . += span_notice("Once you lose this item it will turn into dust.")
+ . += "Положи сердце в этот проклятый пояс и оно обратится во взрывчатку."
+ . += span_notice("[src] готов принять [span_bold("[glory_points]")] сердец. Брутально добей больше ничтожеств, чтобы насытить пояс.")
/obj/item/storage/belt/military/assault/hatred/Entered(atom/movable/AM, atom/oldLoc)
. = ..()
@@ -705,56 +754,34 @@
cold_protection = CHEST|GROIN|ARMS|LEGS
heat_protection = CHEST|GROIN|ARMS|LEGS
max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
- var/is_trophy = FALSE
/obj/item/clothing/suit/jacket/leather_trenchcoat/hatred/Initialize(mapload)
. = ..()
- allowed += list(/obj/item/storage/belt/holster)
+ allowed += list(/obj/item/storage/belt/holster, /obj/item/gun)
// clueless armor stats.
/datum/armor/hatred
- melee = 40
- bullet = 40
- laser = 40
- energy = 40
- bomb = 40
- bio = 40
- fire = 70
- acid = 70
- wound = WOUND_ARMOR_STANDARD
+ melee = 40
+ bullet = 40
+ laser = 40
+ energy = 40
+ bomb = 40
+ bio = 40
+ fire = 70
+ acid = 70
+ wound = WOUND_ARMOR_STANDARD
// level 2 gear upgrade. +10
/datum/armor/hatred_more
- melee = 50
- bullet = 50
- laser = 50
- energy = 50
- bomb = 50
- bio = 50
- fire = 80
- acid = 80
- wound = WOUND_ARMOR_HIGH
-
-/obj/item/clothing/suit/jacket/leather_trenchcoat/hatred/equipped(mob/user, slot)
- . = ..()
- if(slot == ITEM_SLOT_OCLOTHING && !is_trophy)
- ADD_TRAIT(src, TRAIT_NODROP, "hatred")
- var/datum/antagonist/hatred/Ha = user.mind?.has_antag_datum(/datum/antagonist/hatred)
- if(Ha?.chosen_gun == "Pistols")
- RegisterSignal(user, COMSIG_LIVING_DEATH, PROC_REF(on_hatred_death))
-
-/obj/item/clothing/suit/jacket/leather_trenchcoat/hatred/proc/on_hatred_death()
- SIGNAL_HANDLER
- var/obj/item/clothing/suit/jacket/leather_trenchcoat/hatred/I = new type(get_turf(src))
- I.desc = "The blood stained shabby leather overcoat with decent armor paddings and special lightweight kevlar."
- I.max_integrity = 400
- I.update_integrity(I.max_integrity) // will be damaged during antag's death implant detonation
- I.is_trophy = TRUE
-
-/obj/item/clothing/suit/jacket/leather_trenchcoat/hatred/dropped(mob/user)
- . = ..()
- if(!QDELETED(src) && !is_trophy)
- REMOVE_TRAIT(src, TRAIT_NODROP, "hatred")
+ melee = 50
+ bullet = 50
+ laser = 50
+ energy = 50
+ bomb = 50
+ bio = 50
+ fire = 80
+ acid = 80
+ wound = WOUND_ARMOR_HIGH
/obj/item/clothing/head/invisihat/hatred
name = "\proper Veil of Hatred"
@@ -783,7 +810,6 @@
gloves = /obj/item/clothing/gloves/tackler/combat/insulated
shoes = /obj/item/clothing/shoes/jackboots/knee // /obj/item/clothing/shoes/combat
id = /obj/item/card/id/away/old
- l_pocket = /obj/item/storage/pouch/ammo/hatred
// suit_store = /obj/item/flashlight/seclite // the light doesn't work after spawn for some reason
belt = /obj/item/storage/belt/military/assault
back = /obj/item/storage/backpack/satchel/fireproof // /obj/item/storage/backpack/duffelbag/syndie/nri/captain
@@ -804,32 +830,26 @@
var/available_sets = Ha.classic_guns
SEND_SOUND(H, 'sound/announcer/notice/notice2.ogg')
Ha.chosen_gun = tgui_input_list(H, "Выбери стартовое оружие и сделай это БЫСТРО!", "Выбери оружие геноцида", available_sets, available_sets[1], 10 SECONDS)
+ if(!Ha.chosen_gun)
+ Ha.chosen_gun = available_sets[1]
switch(Ha.chosen_gun)
- if(null)
- Ha.chosen_gun = "AK12"
- r_hand = /obj/item/gun/ballistic/automatic/ar/ak12/hatred
if("AK12")
- r_hand = /obj/item/gun/ballistic/automatic/ar/ak12/hatred
- if("Riot Shotgun")
- r_hand = /obj/item/gun/ballistic/shotgun/riot/hatred
- suit_store = /obj/item/storage/belt/holster/hatred_sawn_off
+ suit_store = /obj/item/gun/ballistic/automatic/ar/ak12/hatred
+ l_pocket = /obj/item/storage/pouch/ammo/hatred
+ if("Combat Shotgun")
+ suit_store = /obj/item/gun/ballistic/shotgun/automatic/combat/hatred
+ // suit_store = /obj/item/storage/belt/holster/hatred_sawn_off
+ l_pocket = /obj/item/storage/pouch/ammo/hatred
if("Pistols")
suit_store = /obj/item/storage/belt/holster/hatred
- l_pocket = null
ADD_TRAIT(H, TRAIT_DOUBLE_TAP, "hatred")
- if(Ha.gear_level == 2)
+ if(Ha.gear_level >= 2)
// if(Ha.chosen_gun == "Pistols")
// Ha.high_gear += "Shoot faster"
belt = /obj/item/storage/belt/military/assault/hatred
Ha.chosen_high_gear = tgui_input_list(H, "Выбери дополнительную экипировку и сделай это БЫСТРО!", "Выбери оружие геноцида", Ha.high_gear, Ha.high_gear[1], 10 SECONDS)
- switch(Ha.chosen_high_gear)
- if(null)
- Ha.chosen_high_gear = "More armor"
- // belt = /obj/item/storage/belt/military/assault/hatred
- // if("Belt of Hatred")
- // belt = /obj/item/storage/belt/military/assault/hatred
- // if("Shoot faster")
- // ADD_TRAIT(H, TRAIT_DOUBLE_TAP, "hatred")
+ if(!Ha.chosen_high_gear)
+ Ha.chosen_high_gear = Ha.high_gear[1]
/datum/outfit/hatred/post_equip(mob/living/carbon/human/H, visualsOnly, client/preference_source)
// var/obj/item/implant/explosive/E = new
@@ -840,7 +860,10 @@
U.unique_reskin = null
ADD_TRAIT(U, TRAIT_NODROP, "hatred")
- var/obj/item/clothing/I = H.get_item_by_slot(ITEM_SLOT_FEET)
+ var/obj/item/I = H.get_item_by_slot(ITEM_SLOT_OCLOTHING)
+ ADD_TRAIT(I, TRAIT_NODROP, "hatred")
+
+ I = H.get_item_by_slot(ITEM_SLOT_FEET)
I.resistance_flags = FIRE_PROOF
I = H.get_item_by_slot(ITEM_SLOT_EYES)
@@ -849,6 +872,9 @@
I = H.get_item_by_slot(ITEM_SLOT_GLOVES)
I.resistance_flags = FIRE_PROOF
+ I = H.get_item_by_slot(ITEM_SLOT_BACK)
+ I.resistance_flags = FIRE_PROOF
+
var/obj/item/card/id/advanced/A = H.get_item_by_slot(ITEM_SLOT_ID)
A.name = "Mangled ID Card"
A.desc = "Deep cuts and scratches made its inscriptions and pics unreadable."
@@ -861,27 +887,29 @@
mol.reagents.add_reagent(/datum/reagent/consumable/ethanol/vodka, 100)
new /obj/item/lighter/skull(B)
- var/obj/item/storage/pouch/ammo/hatred/P = H.get_item_by_slot(ITEM_SLOT_LPOCKET)
var/datum/antagonist/hatred/Ha = H.mind?.has_antag_datum(/datum/antagonist/hatred)
if(!Ha)
return
switch(Ha.chosen_gun)
if("AK12")
+ var/obj/item/storage/pouch/ammo/hatred/P = H.get_item_by_slot(ITEM_SLOT_LPOCKET)
P.atom_storage.set_holdable(list(/obj/item/ammo_box/magazine/ak12), list(), list(/obj/item/ammo_box/magazine/ak12))
+ P.atom_storage.max_slots = 3
new /obj/item/ammo_box/magazine/ak12(P)
new /obj/item/ammo_box/magazine/ak12(P)
- if("Riot Shotgun")
+ if("Combat Shotgun")
+ var/obj/item/storage/pouch/ammo/hatred/P = H.get_item_by_slot(ITEM_SLOT_LPOCKET)
P.atom_storage.set_holdable(list(/obj/item/ammo_box/advanced/s12gauge), list(), list(/obj/item/ammo_box/advanced/s12gauge))
- P.atom_storage.max_slots = 10
- new /obj/item/ammo_box/advanced/s12gauge/laser(P)
+ P.atom_storage.max_slots = 5
+ new /obj/item/ammo_box/advanced/s12gauge/buckshot(P)
new /obj/item/ammo_box/advanced/s12gauge(P)
- // new /obj/item/ammo_box/magazine/m12g/slug(P)
- // new /obj/item/ammo_box/advanced/s12gauge/incendiary(P)
- new /obj/item/ammo_box/advanced/s12gauge/flechette(P)
- // new /obj/item/ammo_box/advanced/s12gauge/express(P)
- new /obj/item/ammo_box/advanced/s12gauge/dragonsbreath(P)
+ new /obj/item/ammo_box/advanced/s12gauge/incendiary(P)
new /obj/item/ammo_box/advanced/s12gauge/frangible(P)
+ new /obj/item/ammo_box/advanced/s12gauge/flechette(P)
+ // new /obj/item/ammo_box/advanced/s12gauge/dragonsbreath(P)
// new /obj/item/ammo_box/advanced/s12gauge/breaching(P)
+ // new /obj/item/ammo_box/advanced/s12gauge/express(P)
+ // new /obj/item/ammo_box/advanced/s12gauge/laser(P)
if("Pistols")
I = H.get_item_by_slot(ITEM_SLOT_OCLOTHING)
I.resistance_flags = FIRE_PROOF | ACID_PROOF // to prevent the holster of Hatred to be dropped and lost forever.
@@ -911,12 +939,13 @@
DYNAMIC_TIER_LOW = 0,
DYNAMIC_TIER_LOWMEDIUM = 0,
DYNAMIC_TIER_MEDIUMHIGH = 0,
- DYNAMIC_TIER_HIGH = 9, // будет 7 или 8, так как этот антаг имеет высокие требования к количеству живых офицеров и в нагруженные динамики это требование будет невыполено. на время бета теста выставлено 9.
+ DYNAMIC_TIER_HIGH = 9, // этот антаг имеет высокие требования к количеству живых офицеров и в нагруженные динамики это требование зачастую будет невыполено.
)
min_pop = 30
max_antag_cap = 1
repeatable = FALSE // one man is enough to shake this station.
signup_atom_appearance = /obj/item/gun/ballistic/automatic/ar/ak12
+ // minimum_required_age = 14
/datum/dynamic_ruleset/midround/from_ghosts/hatred/can_be_selected()
. = ..()
@@ -936,7 +965,7 @@
/datum/dynamic_ruleset/midround/from_ghosts/hatred/assign_role(datum/mind/candidate)
// var/turf/entry_spawn_loc
// /area/awaymission/errorroom
- var/mob/living/carbon/human/body = new (GET_ERROR_ROOM) // what a fine empty room. why don't we borrow it for a couple of seconds during preparation.
+ var/mob/living/carbon/human/body = new (get_turf(GET_ERROR_ROOM)) // what a fine empty room. why don't we borrow it for a couple of seconds during preparation.
// body.move_to_error_room()
candidate.transfer_to(body, force_key_move = TRUE)
body.dna.remove_all_mutations()
@@ -993,7 +1022,7 @@
var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_MASS_SHOOTER, role = ROLE_MASS_SHOOTER, alert_pic = /obj/item/gun/ballistic/automatic/ar/ak12, role_name_text = "Mass Shooter", amount_to_pick = 1)
if(isnull(chosen_one))
return NOT_ENOUGH_PLAYERS
- var/mob/living/carbon/human/body = new (entry_spawn_loc)
+ var/mob/living/carbon/human/body = new (get_turf(entry_spawn_loc))
// body.move_to_error_room()
// body.PossessByPlayer(chosen_one.key)
var/datum/mind/Mind = new /datum/mind(chosen_one.key)
diff --git a/tgstation.dme b/tgstation.dme
index 21eed82b84955..1d2068be8cbe3 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -10736,6 +10736,7 @@
#include "modular_zzz\code\controllers\subsystem\vote.dm"
#include "modular_zzz\code\datums\sprite_accessories.dm"
#include "modular_zzz\code\datums\world_topic.dm"
+#include "modular_zzz\code\datums\actions\items\toggles.dm"
#include "modular_zzz\code\datums\components\jukebox.dm"
#include "modular_zzz\code\datums\quirks\negative_quirks\allergic.dm"
#include "modular_zzz\code\datums\quirks\negative_quirks\blood_deficiency.dm"
diff --git a/tgui/packages/tgui/interfaces/AntagInfoHatred.tsx b/tgui/packages/tgui/interfaces/AntagInfoHatred.tsx
new file mode 100644
index 0000000000000..55e5cce2362ad
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/AntagInfoHatred.tsx
@@ -0,0 +1,82 @@
+import { Section, Stack } from 'tgui-core/components';
+
+import { useBackend } from '../backend';
+import { Window } from '../layouts';
+import { Rules } from './AntagInfoRules'; // BUBBER EDIT ADDITION
+import { type Objective, ObjectivePrintout } from './common/Objectives';
+
+type Info = {
+ antag_name: string;
+ objectives: Objective[];
+ pistols: boolean;
+ belt: boolean;
+};
+
+// SKYRAT EDIT increase height from 250 to 500
+export const AntagInfoHatred = (props) => {
+ const { data } = useBackend();
+ const { antag_name, objectives } = data;
+ return (
+
+
+
+
+
+ You are the {antag_name}!
+
+ {/* SKYRAT EDIT ADDITION START */}
+
+
+
+ {/* SKYRAT EDIT ADDITION END */}
+
+
+
+
+
+ Ты - Безымянный Массшутер. Твое имя совершенно неважно. Твое прошлое даже если и было, оно было незавидным.
+
Ты испытываешь непреодолимую ненависть, отвращение и презрение ко всем окружающим.
+
У тебя лишь две цели: убивать и умереть славной смертью.
+
Твое проклятое снаряжение неразлучно с тобою и подстегивает тебя продолжать соврешать геноцид беззащитных гражданских.
+
Твоё Оружие Ненависти и неутолимая жажда убивать вознаграждают тебя, ибо завершающий выстрел в упор в голову (рот) исцеляет твои раны, нож добивает быстрее и надежнее.
+
Обычная медицина бессильна, а чужое оружие бесполезно для тебя.
+
+
+
Убивай и будь убит! Ибо никто сегодня не защищен от твоей Ненависти.
+
+
+
+
+
+
+ );
+};
+
+const PistolsInfo = (props) => {
+ const { data } = useBackend();
+ const { pistols } = data;
+ if (pistols) {
+ return (
+
+ Кобура Ненависти всегда готова предоставить тебе особое парное оружие. Стрелять с двух рук - в Харме. После использования можешь просто выбросить их, ибо их цель была выполнена.
+
+ );
+ }
+ return (
+
+ Cумка для патронов сама пополняет пустые магазины/картриджи/клипсы для твоего оружия. Никогда не выбрасывай их!
+
+ )
+};
+
+const BeltInfo = (props) => {
+ const { data } = useBackend();
+ const { belt } = data;
+ if (belt) {
+ return (
+
+ Пояс с гранатами пожирает сердца твоих жертв после их добивания и вознаграждает тебя новой взрывоопасной аммуницией.
+
+ );
+ }
+};