Skip to content

Commit f822b20

Browse files
authored
Vampire Expansion Pack 2 (#1212)
* neckbitenstuff * fix gamemode 4 real
1 parent 5a37f13 commit f822b20

File tree

10 files changed

+82
-26
lines changed

10 files changed

+82
-26
lines changed

code/__DEFINES/maps.dm

-6
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,6 @@ require only minor tweaks.
6767
#define ZTRAIT_ICE_RUINS_UNDERGROUND "Ice Ruins Underground"
6868
#define ZTRAIT_ISOLATED_RUINS "Isolated Ruins" //Placing ruins on z levels with this trait will use turf reservation instead of usual placement.
6969

70-
// boolean - Is this Z-level used to house shuttles during transport
71-
#define ZTRAIT_TRANSIT "Transit"
72-
7370
// boolean - weather types that occur on the level
7471
#define ZTRAIT_SNOWSTORM "Weather_Snowstorm"
7572
#define ZTRAIT_VOIDSTORM "Weather_Voidstorm"
@@ -117,9 +114,6 @@ require only minor tweaks.
117114
///Z level traits for Secret Away Missions
118115
#define ZTRAITS_AWAY_SECRET list(ZTRAIT_AWAY = TRUE, ZTRAIT_SECRET = TRUE, ZTRAIT_NOPHASE = TRUE)
119116

120-
///Z level traits for the transit z level
121-
#define ZTRAITS_TRANSIT list(ZTRAIT_RESERVED = TRUE, ZTRAIT_TRANSIT = TRUE)
122-
123117
#define DL_NAME "name"
124118
#define DL_TRAITS "traits"
125119
#define DECLARE_LEVEL(NAME, TRAITS) list(DL_NAME = NAME, DL_TRAITS = TRAITS)

code/game/gamemodes/blood_plague_outbreak.dm

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@
1111
if(.)
1212
return
1313

14-
var/list/transit_levels = SSmapping.levels_by_trait(ZTRAIT_TRANSIT)
14+
if(EMERGENCY_AT_LEAST_DOCKED || SSshuttle.emergency?.mode == SHUTTLE_CALL)
15+
return TRUE
16+
1517
// If there's no non-vampires left alive, end the round.
1618
// If this becomes too common, something is wrong, this is NOT a conversion antagonist.
1719
for(var/mob/living/carbon/human in GLOB.human_list)
1820
if(!human.ckey)
1921
continue
2022

2123
var/turf/pos = get_turf(human)
22-
if(isnull(pos) || !(is_station_level(pos.z) || (pos.z in transit_levels)))
24+
if(isnull(pos) || !(is_station_level(pos.z) || isshuttleturf(pos)))
2325
continue
2426

2527
if(IS_VAMPIRE(human))

code/modules/antagonists/vampire/vampire.dm

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
var/list/current_states = list()
1717
var/list/state_datums
1818

19-
/// Weakref to the last mob drained of blood.
20-
var/datum/weakref/last_victim_ref
19+
/// Weakrefs to mobs drained of blood.
20+
var/list/datum/weakref/past_victim_refs = list()
2121

2222
var/list/innate_actions = list(
2323
/datum/action/cooldown/blood_sense,

code/modules/antagonists/vampire/vampire_actions/blood_track.dm

+21-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
return
2020

2121
var/datum/antagonist/vampire/vamp_datum = owner.mind.has_antag_datum(/datum/antagonist/vampire)
22-
return !!vamp_datum.last_victim_ref
22+
return !!length(vamp_datum.past_victim_refs)
2323

2424
/datum/action/cooldown/blood_track/Activate(atom/target)
2525
var/mob/living/carbon/human/human_owner = owner
@@ -32,10 +32,28 @@
3232
to_chat(owner, span_notice("You are unable to catch a scent here."))
3333
return
3434

35+
var/datum/antagonist/vampire/vamp_datum = owner.mind.has_antag_datum(/datum/antagonist/vampire)
36+
37+
var/list/options = list()
38+
for(var/datum/weakref/weakref as anything in vamp_datum.past_victim_refs)
39+
var/mob/living/carbon/human/H = weakref.resolve()
40+
if(!ishuman(H))
41+
vamp_datum.past_victim_refs -= weakref
42+
continue
43+
44+
options[H.real_name] = weakref
45+
46+
var/victim_name = tgui_input_list(owner, "Select a target", "Blood hunt", options, options[1], 1 MINUTE)
47+
if(isnull(victim_name) || isnull(owner))
48+
return
49+
50+
var/datum/weakref/victim_ref = options[victim_name]
51+
var/mob/living/carbon/human/victim = victim_ref.resolve()
52+
if(!ishuman(victim))
53+
return
54+
3555
. = ..()
3656

37-
var/datum/antagonist/vampire/vamp_datum = owner.mind.has_antag_datum(/datum/antagonist/vampire)
38-
var/mob/living/carbon/human/victim = vamp_datum.last_victim_ref.resolve()
3957
var/turf/victim_turf = get_turf(victim)
4058
var/turf/owner_turf = get_turf(owner)
4159

code/modules/antagonists/vampire/vampire_actions/neck_bite.dm

+27-10
Original file line numberDiff line numberDiff line change
@@ -38,31 +38,39 @@
3838
var/mob/living/carbon/human/user = target
3939
var/mob/living/carbon/human/victim = select_target()
4040

41-
user.visible_message(span_danger("[user] bites down on [victim]'s neck!"), vision_distance = COMBAT_MESSAGE_RANGE)
42-
41+
var/datum/antagonist/vampire/vamp_datum = user.mind.has_antag_datum(/datum/antagonist/vampire)
4342
var/datum/callback/checks_callback = CALLBACK(src, PROC_REF(can_bite), user, victim)
44-
if(!do_after(user, victim, 3 SECONDS, DO_IGNORE_HELD_ITEM|DO_IGNORE_SLOWDOWNS|DO_PUBLIC, extra_checks = checks_callback, display = image('goon/icons/actions.dmi', "bite")))
45-
return FALSE
43+
44+
if(vamp_datum.thirst_stage != THIRST_STAGE_BLOODLUST)
45+
if(!do_after(user, victim, 3 SECONDS, DO_IGNORE_HELD_ITEM|DO_IGNORE_SLOWDOWNS|DO_PUBLIC, extra_checks = checks_callback, display = image('goon/icons/actions.dmi', "bite")))
46+
return FALSE
4647

4748
. = ..()
4849

4950
spawn(-1)
51+
user.visible_message(span_danger("<b>[user]</b> bites down on <b>[victim]</b>'s neck."), vision_distance = COMBAT_MESSAGE_RANGE)
52+
5053
ADD_TRAIT(user, TRAIT_MUTE, ref(src))
54+
ADD_TRAIT(victim, TRAIT_MUTE, ref(src))
55+
var/obj/item/bodypart/head/head = victim.get_bodypart(BODY_ZONE_HEAD)
56+
head.create_wound_easy(/datum/wound/neck_bite, 10)
57+
5158
var/image/succ_image = image('goon/icons/actions.dmi', "blood")
5259
while(TRUE)
5360
if(!can_bite(user, victim))
5461
break
5562

5663
if(!do_after(user, victim, 1 SECOND, DO_IGNORE_HELD_ITEM|DO_IGNORE_SLOWDOWNS|DO_PUBLIC, extra_checks = checks_callback, display = succ_image))
57-
user.visible_message(span_notice("[user] removes [p_their()] teeth from [victim]'s neck."))
64+
user.visible_message(span_notice("<b>[user]</b> removes [p_their()] teeth from </b>[victim]</b>'s neck."))
5865
break
5966

6067
siphon_blood(user, victim)
6168

69+
REMOVE_TRAIT(victim, TRAIT_MUTE, ref(src))
6270
REMOVE_TRAIT(user, TRAIT_MUTE, ref(src))
6371

6472
/datum/action/cooldown/neck_bite/proc/siphon_blood(mob/living/carbon/human/user, mob/living/carbon/human/victim)
65-
user.visible_message(span_danger("[user] siphons blood from [victim]'s neck!"), vision_distance = COMBAT_MESSAGE_RANGE, ignored_mobs = victim)
73+
user.visible_message(span_danger("<b>[user]</b> siphons blood from <b>[victim]</b>'s neck."), vision_distance = COMBAT_MESSAGE_RANGE, ignored_mobs = victim)
6674
if(victim.stat == CONSCIOUS)
6775
to_chat(victim, span_danger("You can feel blood draining from your neck."))
6876

@@ -74,13 +82,18 @@
7482
victim.adjustBloodVolume(-VAMPIRE_BLOOD_DRAIN_RATE)
7583
user.adjustBloodVolumeUpTo(VAMPIRE_BLOOD_DRAIN_RATE, BLOOD_VOLUME_NORMAL + 100)
7684

85+
if(user.nutrition < NUTRITION_LEVEL_FULL)
86+
user.set_nutrition(min(user.nutrition + 10, NUTRITION_LEVEL_FULL))
87+
user.satiety = min(user.satiety + 20, MAX_SATIETY)
88+
89+
user.heal_overall_damage(2.5, 2.5, BODYTYPE_ORGANIC)
90+
7791
var/datum/antagonist/vampire/vamp_datum = user.mind.has_antag_datum(/datum/antagonist/vampire)
7892
vamp_datum.thirst_level.remove_points(VAMPIRE_BLOOD_DRAIN_RATE * VAMPIRE_BLOOD_THIRST_EXCHANGE_COEFF)
7993
vamp_datum.update_thirst_stage()
8094

81-
var/had_victim = vamp_datum.last_victim_ref
82-
vamp_datum.last_victim_ref = WEAKREF(victim)
83-
if(!had_victim)
95+
if(!(WEAKREF(victim) in vamp_datum.past_victim_refs))
96+
vamp_datum.past_victim_refs += WEAKREF(victim)
8497
var/datum/action/cooldown/blood_track/track = locate() in owner.actions
8598
if(track)
8699
track.build_all_button_icons(UPDATE_BUTTON_STATUS)
@@ -140,14 +153,18 @@
140153
*error_string_ptr = "You aren't holding anyone."
141154
return null
142155

156+
var/datum/antagonist/vampire/vamp_datum = user.mind.has_antag_datum(/datum/antagonist/vampire)
157+
158+
var/needed_grab = vamp_datum.thirst_stage == THIRST_STAGE_BLOODLUST ? GRAB_AGGRESSIVE : GRAB_NECK
159+
143160
for(var/obj/item/hand_item/grab/grab in user.active_grabs)
144161
var/mob/living/carbon/human/potential_victim = grab.affecting
145162
if(!ishuman(potential_victim) || ismonkey(potential_victim))
146163
if(ismob(potential_victim) && error_string_ptr)
147164
*error_string_ptr = "You cannot feast on [potential_victim]."
148165
continue
149166

150-
if((grab.current_grab.damage_stage < GRAB_NECK))
167+
if((grab.current_grab.damage_stage < needed_grab))
151168
if(error_string_ptr)
152169
*error_string_ptr = "You need a stronger grip on [potential_victim]."
153170
continue

code/modules/mob/living/carbon/human/human.dm

+2-2
Original file line numberDiff line numberDiff line change
@@ -1224,8 +1224,8 @@
12241224
)
12251225
else
12261226
visible_message(
1227-
span_warning("The [W.desc] on [src]'s [W.parent.plaintext_zone] widens with a nasty ripping noise."),
1228-
span_warning("The [W.desc] on your [W.parent.plaintext_zone] widens with a nasty ripping noise."),
1227+
span_warning("The [W.desc] on [src]'s [W.wound_location()] widens with a nasty ripping noise."),
1228+
span_warning("The [W.desc] on your [W.wound_location()] widens with a nasty ripping noise."),
12291229
span_hear("You hear a nasty ripping noise, as if flesh is being torn apart."),
12301230
COMBAT_MESSAGE_RANGE,
12311231
)

code/modules/shuttle/emergency.dm

+1-1
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@
502502
for(var/obj/docking_port/mobile/M in SSshuttle.mobile_docking_ports)
503503
M.post_emergency_launch()
504504
if(prob(10))
505-
SSuniverse.SetUniversalState(/datum/universal_state/resonance_jump, list(ZTRAIT_TRANSIT))
505+
SSuniverse.SetUniversalState(/datum/universal_state/resonance_jump, list(ZTRAIT_RESERVED))
506506
setTimer(SSshuttle.emergency_escape_time * engine_coeff)
507507
priority_announce("The Icarus has entered the resonance gate and is enroute to it's destination. Estimate [timeLeft(600)] minutes until the shuttle docks at Sector Control.", "LRSV Icarus Announcement")
508508
INVOKE_ASYNC(SSticker, TYPE_PROC_REF(/datum/controller/subsystem/ticker, poll_hearts))

code/modules/surgery/bodyparts/wounds/_wounds.dm

+3
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,9 @@
279279

280280
return this_wound_desc
281281

282+
/// Returns the location of the wound for descriptions.
283+
/datum/wound/proc/wound_location()
284+
return parent.plaintext_zone
282285

283286
/datum/wound/proc/item_gone(datum/source)
284287
SIGNAL_HANDLER
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/// Used by the Neck Bite ability.
2+
/datum/wound/neck_bite
3+
pain_factor = 0
4+
bleed_threshold = 0
5+
wound_type = WOUND_PIERCE
6+
7+
autoheal_cutoff = 10
8+
max_bleeding_stage = 1
9+
stages = list(
10+
"afflicted bite" = 5,
11+
"fading bite mark" = 0,
12+
)
13+
14+
/datum/wound/neck_bite/can_worsen(damage_type, damage)
15+
return FALSE
16+
17+
/datum/wound/neck_bite/can_merge(datum/wound/other)
18+
return FALSE
19+
20+
/datum/wound/neck_bite/wound_location()
21+
return "neck"

daedalus.dme

+1
Original file line numberDiff line numberDiff line change
@@ -4466,6 +4466,7 @@
44664466
#include "code\modules\surgery\bodyparts\wounds\create_wound.dm"
44674467
#include "code\modules\surgery\bodyparts\wounds\cuts.dm"
44684468
#include "code\modules\surgery\bodyparts\wounds\lost_limb.dm"
4469+
#include "code\modules\surgery\bodyparts\wounds\neck_bite.dm"
44694470
#include "code\modules\surgery\bodyparts\wounds\punctures.dm"
44704471
#include "code\modules\surgery\machines\bodyscanner.dm"
44714472
#include "code\modules\surgery\machines\bodyscanner_display.dm"

0 commit comments

Comments
 (0)