Skip to content

Commit

Permalink
Antagonist: Sanguine Plague Victim (#1136)
Browse files Browse the repository at this point in the history
* base

* chompy

* blood plague

* blood plague + config addition

* message admins when kicking an afk player

* improvements

* over designed but great

* state stuffs and fixes

* vampire moodlets

* glare

* desperate feed

* name tweaks

* blood track icon

* unused file

* blood effects

* fix master merge

* finish up
  • Loading branch information
Kapu1178 authored Feb 1, 2025
1 parent ec81597 commit 52f564c
Show file tree
Hide file tree
Showing 58 changed files with 1,169 additions and 253 deletions.
3 changes: 3 additions & 0 deletions code/__DEFINES/antagonists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ GLOBAL_LIST_INIT(ai_employers, list(
/// Checks if the given mob is a traitor
#define IS_TRAITOR(mob) (mob?.mind?.has_antag_datum(/datum/antagonist/traitor))

/// Checks if the given mob is a vampire
#define IS_VAMPIRE(mob) (mob?.mind?.has_antag_datum(/datum/antagonist/vampire))

/// The dimensions of the antagonist preview icon. Will be scaled to this size.
#define ANTAGONIST_PREVIEW_ICON_SIZE 96

Expand Down
7 changes: 7 additions & 0 deletions code/__DEFINES/dcs/flags.dm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
#define COMPONENT_DUPE_ALLOWED 1
/// new component is deleted
#define COMPONENT_DUPE_UNIQUE 2
/**
* Component uses source tracking to manage adding and removal logic.
* Add a source/spawn to/the component by using AddComponentFrom(source, component_type, args...)
* Removing the last source will automatically remove the component from the parent.
* Arguments will be passed to on_source_add(source, args...); ensure that Initialize and on_source_add have the same signature.
*/
#define COMPONENT_DUPE_SOURCES 3
/// old component is given the initialization args of the new
#define COMPONENT_DUPE_UNIQUE_PASSARGS 4
/// each component of the same type is consulted as to whether the duplicate should be allowed
Expand Down
4 changes: 4 additions & 0 deletions code/__DEFINES/dcs/helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
/// A wrapper for _AddComponent that allows us to pretend we're using normal named arguments
#define AddComponent(arguments...) _AddComponent(list(##arguments))

/// A wrapper for _AddComonent that passes in a source.
/// Necessary if dupe_mode is set to COMPONENT_DUPE_SOURCES.
#define AddComponentFrom(source, arguments...) _AddComponent(list(##arguments), source)

/// A wrapper for _LoadComponent that allows us to pretend we're using normal named arguments
#define LoadComponent(arguments...) _LoadComponent(list(##arguments))
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
#define COMSIG_LIVING_TRY_GRAB "living_try_pull"
#define COMSIG_LIVING_CANCEL_GRAB (1 << 0)

///called on /living when it downgrades a grab
#define COMSIG_LIVING_GRAB_DOWNGRADE "living_grab_downgrade"
///called on /living when it upgrades a grab
#define COMSIG_LIVING_GRAB_UPGRADE "living_grab_upgrade"

/// Called from /mob/living/PushAM -- Called when this mob is about to push a movable, but before it moves
/// (aotm/movable/being_pushed)
#define COMSIG_LIVING_PUSHING_MOVABLE "living_pushing_movable"
Expand Down
1 change: 0 additions & 1 deletion code/__DEFINES/is_helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define isskeleton(A) (is_species(A, /datum/species/skeleton))
#define ismoth(A) (is_species(A, /datum/species/moth))
#define isethereal(A) (is_species(A, /datum/species/ethereal))
#define isvampire(A) (is_species(A,/datum/species/vampire))
#define isdullahan(A) (is_species(A, /datum/species/dullahan))
#define ismonkey(A) (is_species(A, /datum/species/monkey))
#define isandroid(A) (is_species(A, /datum/species/android))
Expand Down
1 change: 0 additions & 1 deletion code/__DEFINES/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@
#define SPECIES_SKELETON "skeleton"
#define SPECIES_SNAIL "snail"
#define SPECIES_TESHARI "teshari"
#define SPECIES_VAMPIRE "vampire"
#define SPECIES_VOX "vox"
#define SPECIES_ZOMBIE "zombie"
#define SPECIES_ZOMBIE_INFECTIOUS "memezombie"
Expand Down
3 changes: 2 additions & 1 deletion code/__DEFINES/role_preferences.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
#define ROLE_CHANGELING "Changeling"
#define ROLE_CULTIST "Cultist"
#define ROLE_FAMILIES "Gangster"
#define ROLE_FLOCK "Flock"
#define ROLE_HERETIC "Heretic"
#define ROLE_MALF "Malf AI"
#define ROLE_OPERATIVE "Operative"
#define ROLE_THIEF "Thief"
#define ROLE_TRAITOR "Traitor"
#define ROLE_VAMPIRE "Vampire"
#define ROLE_WIZARD "Wizard"
#define ROLE_FLOCK "Flock"

// Midround roles
#define ROLE_ABDUCTOR "Abductor"
Expand Down
3 changes: 3 additions & 0 deletions code/__DEFINES/status_effects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@

#define STASIS_DEBUG_HEALTH "stasis_debug_health"

#define BROKEN_SKULL_EFFECT "broken_head"
#define VAMPIRE_EFFECT "vampire_effect"

// Status effect application helpers.
// These are macros for easier use of adjust_timed_status_effect and set_timed_status_effect.
//
Expand Down
1 change: 1 addition & 0 deletions code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@
#define FIRE_PRIORITY_PROCESS 30
#define FIRE_PRIORITY_NPC_ACTIONS 25
#define FIRE_PRIORITY_NPC 20
#define FIRE_PRIORITY_SLOW_PROCESS 12
#define FIRE_PRIORITY_IDLE_NPC 10
#define FIRE_PRIORITY_GARBAGE 10
#define FIRE_PRIORITY_AMBIENCE 5
Expand Down
1 change: 1 addition & 0 deletions code/__DEFINES/traits_vampire.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define VAMPIRE_TRAIT "vampire_trait"
13 changes: 13 additions & 0 deletions code/__DEFINES/vampire_defines.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#define THIRST_STAGE_BLOODLUST 1
#define THIRST_STAGE_SATED 2
#define THIRST_STAGE_HUNGRY 3
#define THIRST_STAGE_STARVING 4
#define THIRST_STAGE_WASTING 5

// Point thresholds to change stages. 1 point = 1 second
#define THIRST_THRESHOLD_BLOODLUST 0
#define THIRST_THRESHOLD_SATED 300
#define THIRST_THRESHOLD_HUNGERY (THIRST_THRESHOLD_SATED + 300)
#define THIRST_THRESHOLD_STARVING (THIRST_THRESHOLD_HUNGERY + 300)
#define THIRST_THRESHOLD_WASTING (THIRST_THRESHOLD_STARVING + 300)
#define THIRST_THRESHOLD_DEAD (THIRST_THRESHOLD_WASTING + 300)
4 changes: 2 additions & 2 deletions code/__HELPERS/flock_helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@

return TRUE

/proc/flock_pointer(atom/from, atom/towards)
/proc/pointer_image_to(atom/from, atom/towards, color = "#00ff9dff")
var/image/pointer = image(icon = 'icons/hud/screen1.dmi', icon_state = "arrow_greyscale", loc = from)

pointer.plane = HUD_PLANE
pointer.appearance_flags |= RESET_COLOR
pointer.color = "#00ff9dff"
pointer.color = color

var/angle = 180 + get_angle(from, towards)
var/matrix/final_matrix = pointer.transform.Scale(2,2)
Expand Down
8 changes: 8 additions & 0 deletions code/_onclick/hud/fullscreen.dm
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@
layer = CURSE_LAYER
plane = FULLSCREEN_PLANE

/atom/movable/screen/fullscreen/curse/bloodlust

/atom/movable/screen/fullscreen/curse/bloodlust/Initialize(mapload, datum/hud/hud_owner)
. = ..()
color = color_matrix_rotate_hue(90)

/atom/movable/screen/fullscreen/ivanov_display
icon_state = "ivanov"
alpha = 180
Expand Down Expand Up @@ -222,3 +228,5 @@
layer = DITHER_LAYER
show_when_dead = TRUE
screen_loc = "WEST,SOUTH to EAST,NORTH"

/atom/movable/screen/fullscreen/bloodlust
2 changes: 2 additions & 0 deletions code/controllers/configuration/entries/game_options.dm
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@

/datum/config_entry/flag/no_intercept_report //Whether or not to send a communications intercept report roundstart. This may be overridden by gamemodes.

/datum/config_entry/flag/hide_gamemode_name //Whether or not to hide the gamemode name from players.

/datum/config_entry/number/arrivals_shuttle_dock_window //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
default = 55
integer = FALSE
Expand Down
6 changes: 6 additions & 0 deletions code/controllers/subsystem/processing/slowprocess.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
PROCESSING_SUBSYSTEM_DEF(slowprocess)
name = "Slow Processing"
wait = 5 SECONDS
priority = FIRE_PRIORITY_SLOW_PROCESS
stat_tag = "SP"

3 changes: 2 additions & 1 deletion code/controllers/subsystem/server_maint.dm
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,11 @@ SUBSYSTEM_DEF(server_maint)
var/client/C = I
//handle kicking inactive players
if(round_started && kick_inactive && !C.holder && C.is_afk(afk_period))
var/cmob = C.mob
var/mob/cmob = C.mob
if (!isnewplayer(cmob) || !SSticker.queued_players.Find(cmob))
log_access("AFK: [key_name(C)]")
to_chat(C, span_userdanger("You have been inactive for more than [DisplayTimeText(afk_period)] and have been disconnected.</span><br><span class='danger'>You may reconnect via the button in the file menu or by <b><u><a href='byond://winset?command=.reconnect'>clicking here to reconnect</a></u></b>."))
message_admins("[C.ckey] has been disconnected for inactivity. [ADMIN_JMP(cmob)]")
QDEL_IN(C, 1) //to ensure they get our message before getting disconnected
continue

Expand Down
3 changes: 3 additions & 0 deletions code/controllers/subsystem/ticker.dm
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ SUBSYSTEM_DEF(ticker)
if(GLOB.is_debug_server)
mode = new /datum/game_mode/extended

if(CONFIG_GET(flag/hide_gamemode_name))
mode_display_name = "Secret"

return ..()

/datum/controller/subsystem/ticker/fire()
Expand Down
8 changes: 4 additions & 4 deletions code/datums/actions/action.dm
Original file line number Diff line number Diff line change
Expand Up @@ -151,21 +151,21 @@
return FALSE
if((check_flags & AB_CHECK_HANDS_BLOCKED) && HAS_TRAIT(owner, TRAIT_HANDS_BLOCKED))
if (feedback)
to_chat(owner, span_warning("You cannot use [name] without hands!"))
to_chat(owner, span_warning("You cannot use [name] without hands."))
return FALSE
if((check_flags & AB_CHECK_IMMOBILE) && HAS_TRAIT(owner, TRAIT_IMMOBILIZED))
if (feedback)
to_chat(owner, span_warning("You cannot use [name] while immobilized!"))
to_chat(owner, span_warning("You cannot use [name] while immobilized."))
return FALSE
if((check_flags & AB_CHECK_LYING) && isliving(owner))
var/mob/living/action_owner = owner
if(action_owner.body_position == LYING_DOWN)
if (feedback)
to_chat(owner, span_warning("You cannot use [name] while lying down!"))
to_chat(owner, span_warning("You cannot use [name] while lying down."))
return FALSE
if((check_flags & AB_CHECK_CONSCIOUS) && owner.stat != CONSCIOUS)
if (feedback)
to_chat(owner, span_warning("You cannot use [name] while unconscious!"))
to_chat(owner, span_warning("You cannot use [name] while unconscious."))
return FALSE
return TRUE

Expand Down
13 changes: 7 additions & 6 deletions code/datums/actions/cooldown_action.dm
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#define COOLDOWN_NO_DISPLAY_TIME (180 SECONDS)

/// Preset for an action that has a cooldown.
/datum/action/cooldown
check_flags = NONE
Expand Down Expand Up @@ -67,19 +65,22 @@
/datum/action/cooldown/create_button()
var/atom/movable/screen/movable/action_button/button = ..()
button.maptext = ""
button.maptext_x = 6
button.maptext_x = 3
button.maptext_y = 2
button.maptext_width = 24
button.maptext_width = 28
button.maptext_height = 12
return button

/datum/action/cooldown/update_button_status(atom/movable/screen/movable/action_button/button, force = FALSE)
. = ..()
var/time_left = max(next_use_time - world.time, 0)
if(!text_cooldown || !owner || time_left == 0 || time_left >= COOLDOWN_NO_DISPLAY_TIME)
if(!text_cooldown || !owner || time_left == 0)
button.maptext = ""
else
button.maptext = MAPTEXT("<b>[round(time_left/10, 0.1)]</b>")
if(time_left > 60 SECONDS)
button.maptext = MAPTEXT("<b>[ceil(time_left/600)] min")
else
button.maptext = MAPTEXT("<b>[round(time_left/10, 0.1)]</b>")

if(!IsAvailable() || !is_action_active(button))
return
Expand Down
55 changes: 54 additions & 1 deletion code/datums/components/_component.dm
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
*/
var/can_transfer = FALSE

/// A lazy list of the sources for this component
var/list/sources

/**
* Create a new component.
*
Expand Down Expand Up @@ -165,6 +168,28 @@
/datum/component/proc/UnregisterFromParent()
return

/**
* Called when the component has a new source registered.
* Return COMPONENT_INCOMPATIBLE to signal that the source is incompatible and should not be added
*/
/datum/component/proc/on_source_add(source, ...)
SHOULD_CALL_PARENT(TRUE)
if(dupe_mode != COMPONENT_DUPE_SOURCES)
return COMPONENT_INCOMPATIBLE
LAZYOR(sources, source)

/**
* Called when the component has a source removed.
* You probably want to call parent after you do your logic because at the end of this we qdel if we have no sources remaining!
*/
/datum/component/proc/on_source_remove(source)
SHOULD_CALL_PARENT(TRUE)
if(dupe_mode != COMPONENT_DUPE_SOURCES)
CRASH("Component '[type]' does not use sources but is trying to remove a source")
LAZYREMOVE(sources, source)
if(!LAZYLEN(sources))
qdel(src)

/**
* Register to listen for a signal from the passed in target
*
Expand Down Expand Up @@ -396,7 +421,7 @@
*
* Properly handles duplicate situations based on the `dupe_mode` var
*/
/datum/proc/_AddComponent(list/raw_args)
/datum/proc/_AddComponent(list/raw_args, source)
var/new_type = raw_args[1]
var/datum/component/nt = new_type

Expand All @@ -416,6 +441,12 @@
new_comp = nt
nt = new_comp.type

var/uses_sources = (dm == COMPONENT_DUPE_SOURCES)
if(uses_sources && !source)
CRASH("Attempted to add a sourced component of type '[nt]' to '[type]' without a source!")
else if(!uses_sources && source)
CRASH("Attempted to add a normal component of type '[nt]' to '[type]' with a source!")

raw_args[1] = src

if(dm != COMPONENT_DUPE_ALLOWED && dm != COMPONENT_DUPE_SELECTIVE)
Expand All @@ -431,21 +462,33 @@
if(!QDELETED(new_comp))
old_comp.InheritComponent(new_comp, TRUE)
QDEL_NULL(new_comp)

if(COMPONENT_DUPE_HIGHLANDER)
if(!new_comp)
new_comp = new nt(raw_args)
if(!QDELETED(new_comp))
new_comp.InheritComponent(old_comp, FALSE)
QDEL_NULL(old_comp)

if(COMPONENT_DUPE_UNIQUE_PASSARGS)
if(!new_comp)
var/list/arguments = raw_args.Copy(2)
arguments.Insert(1, null, TRUE)
old_comp.InheritComponent(arglist(arguments))
else
old_comp.InheritComponent(new_comp, TRUE)

if(COMPONENT_DUPE_SOURCES)
if(source in old_comp.sources)
return old_comp // source already registered, no work to do

if(old_comp.on_source_add(arglist(list(source) + raw_args.Copy(2))) == COMPONENT_INCOMPATIBLE)
stack_trace("incompatible source added to a [old_comp.type]. Args: [json_encode(raw_args)]")
return null

else if(!new_comp)
new_comp = new nt(raw_args) // There's a valid dupe mode but there's no old component, act like normal

else if(dm == COMPONENT_DUPE_SELECTIVE)
var/list/arguments = raw_args.Copy()
arguments[1] = new_comp
Expand All @@ -465,6 +508,16 @@
return new_comp
return old_comp

/**
* Removes a component source from this datum
*/
/datum/proc/RemoveComponentFrom(source, datum/component/component_type)
if(ispath(component_type))
component_type = GetExactComponent(component_type)
if(!component_type)
return
component_type.on_source_remove(source)

/**
* Get existing component of type, or create it and return a reference to it
*
Expand Down
1 change: 1 addition & 0 deletions code/datums/components/cult_eyes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Applies and removes the glowing cult eyes
*/
/datum/component/cult_eyes
dupe_mode = COMPONENT_DUPE_SOURCES
var/initial_right_color = ""
var/initial_left_color = ""

Expand Down
5 changes: 3 additions & 2 deletions code/datums/pathogens/_MobProcs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
/mob/living/proc/has_pathogen(datum/pathogen/D)
for(var/datum/pathogen/DD in diseases)
if(D.IsSame(DD))
return TRUE
return FALSE
return DD

return null

/// Returns TRUE if src can contract the passed pathogen.
/// Note: This does not mean that the pathogen will be able to be applied to this mob.
Expand Down
2 changes: 1 addition & 1 deletion code/datums/progressbar.dm
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@
underlay = image(underlay, dir = SOUTH)
underlay.filters += filter(type = "outline", size = 1)

underlay.pixel_y += 2
underlay.pixel_y = 2
underlay.alpha = 200
underlay.plane = GAME_PLANE
underlay.layer = FLY_LAYER
Expand Down
Loading

0 comments on commit 52f564c

Please sign in to comment.