mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
Vampire Gamemode
This commit is contained in:
@@ -6,26 +6,34 @@
|
||||
|
||||
//These are synced with the Database, if you change the values of the defines
|
||||
//then you MUST update the database!
|
||||
#define ROLE_SYNDICATE "Syndicate"
|
||||
#define ROLE_TRAITOR "traitor"
|
||||
#define ROLE_OPERATIVE "operative"
|
||||
#define ROLE_CHANGELING "changeling"
|
||||
#define ROLE_WIZARD "wizard"
|
||||
#define ROLE_MALF "malf AI"
|
||||
#define ROLE_REV "revolutionary"
|
||||
#define ROLE_REV_HEAD "Head Revolutionary"
|
||||
#define ROLE_ALIEN "xenomorph"
|
||||
#define ROLE_PAI "pAI"
|
||||
#define ROLE_CULTIST "cultist"
|
||||
#define ROLE_BLOB "blob"
|
||||
#define ROLE_NINJA "space ninja"
|
||||
#define ROLE_MONKEY "monkey"
|
||||
#define ROLE_ABDUCTOR "abductor"
|
||||
#define ROLE_REVENANT "revenant"
|
||||
#define ROLE_DEVIL "devil"
|
||||
#define ROLE_SERVANT_OF_RATVAR "servant of Ratvar"
|
||||
#define ROLE_BROTHER "blood brother"
|
||||
#define ROLE_BRAINWASHED "brainwashed victim"
|
||||
#define ROLE_SYNDICATE "Syndicate"
|
||||
#define ROLE_TRAITOR "traitor"
|
||||
#define ROLE_OPERATIVE "operative"
|
||||
#define ROLE_CHANGELING "changeling"
|
||||
#define ROLE_WIZARD "wizard"
|
||||
#define ROLE_MALF "malf AI"
|
||||
#define ROLE_REV "revolutionary"
|
||||
#define ROLE_REV_HEAD "Head Revolutionary"
|
||||
#define ROLE_ALIEN "xenomorph"
|
||||
#define ROLE_PAI "pAI"
|
||||
#define ROLE_CULTIST "cultist"
|
||||
#define ROLE_BLOB "blob"
|
||||
#define ROLE_NINJA "space ninja"
|
||||
#define ROLE_MONKEY "monkey"
|
||||
#define ROLE_ABDUCTOR "abductor"
|
||||
#define ROLE_REVENANT "revenant"
|
||||
#define ROLE_DEVIL "devil"
|
||||
#define ROLE_SERVANT_OF_RATVAR "servant of Ratvar"
|
||||
#define ROLE_BROTHER "blood brother"
|
||||
#define ROLE_VAMPIRE "vampire" // Yogs
|
||||
#define ROLE_BRAINWASHED "brainwashed victim"
|
||||
#define ROLE_OVERTHROW "syndicate mutineer"
|
||||
#define ROLE_SENTIENCE "sentience potion spawn"
|
||||
#define ROLE_MIND_TRANSFER "mind transfer potion"
|
||||
#define ROLE_POSIBRAIN "posibrain"
|
||||
#define ROLE_DRONE "drone"
|
||||
#define ROLE_DEATHSQUAD "deathsquad"
|
||||
#define ROLE_LAVALAND "lavaland"
|
||||
|
||||
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
|
||||
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
|
||||
@@ -47,7 +55,10 @@ GLOBAL_LIST_INIT(special_roles, list(
|
||||
ROLE_REVENANT,
|
||||
ROLE_ABDUCTOR,
|
||||
ROLE_DEVIL = /datum/game_mode/devil,
|
||||
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult
|
||||
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult,
|
||||
ROLE_VAMPIRE = /datum/game_mode/vampire, // Yogs
|
||||
ROLE_OVERTHROW = /datum/game_mode/overthrow,
|
||||
ROLE_SENTIENCE
|
||||
))
|
||||
|
||||
//Job defines for what happens when you fail to qualify for any job during job selection
|
||||
|
||||
1
code/__DEFINES/~yogs_defines/antagonists.dm
Normal file
1
code/__DEFINES/~yogs_defines/antagonists.dm
Normal file
@@ -0,0 +1 @@
|
||||
#define ANTAG_DATUM_VAMPIRE /datum/antagonist/vampire
|
||||
1
code/__DEFINES/~yogs_defines/atom_hud.dm
Normal file
1
code/__DEFINES/~yogs_defines/atom_hud.dm
Normal file
@@ -0,0 +1 @@
|
||||
#define ANTAG_HUD_VAMPIRE 20
|
||||
@@ -1,2 +1,3 @@
|
||||
#define COMSIG_ALT_CLICK_ON "alt_click_on" //from base of mob/AltClickOn: (atom/A)
|
||||
#define COMSIG_ATOM_POINTED_AT "atom_pointed_at" //from base of atom/pointed_at(): (mob/user)
|
||||
#define COMSIG_ALT_CLICK_ON "alt_click_on" //from base of mob/AltClickOn(): (atom/A)
|
||||
#define COMSIG_ATOM_POINTED_AT "atom_pointed_at" //from base of atom/pointed_at(): (mob/user)
|
||||
#define COMSIG_PROCESS_MOVE "process_move" //from base of client/Move(): (num/direction)
|
||||
3
code/__DEFINES/~yogs_defines/flags.dm
Normal file
3
code/__DEFINES/~yogs_defines/flags.dm
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
//pass_flags
|
||||
#define PASSDOOR (1<<13)
|
||||
@@ -27,6 +27,7 @@ GLOBAL_LIST_INIT(huds, list(
|
||||
ANTAG_HUD_SOULLESS = new/datum/atom_hud/antag/hidden(),
|
||||
ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(),
|
||||
ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(),
|
||||
ANTAG_HUD_VAMPIRE = new/datum/atom_hud/antag/hidden(), // Yogs
|
||||
))
|
||||
|
||||
/datum/atom_hud
|
||||
|
||||
@@ -200,6 +200,8 @@
|
||||
return
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.a_intent == INTENT_HARM && handle_vamp_biting(H)) // yogs start -- vampire biting
|
||||
return // yogs end
|
||||
dna.species.spec_attack_hand(H, src)
|
||||
|
||||
/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M)
|
||||
|
||||
@@ -77,6 +77,8 @@ ALERT_DELTA Destruction of the station is imminent. All crew are instructed to o
|
||||
PROBABILITY TRAITOR 5
|
||||
PROBABILITY TRAITORBRO 2
|
||||
PROBABILITY TRAITORCHAN 4
|
||||
PROBABILITY TRAITORVAMP 3
|
||||
PROBABILITY VAMPIRE 3
|
||||
PROBABILITY INTERNAL_AFFAIRS 3
|
||||
PROBABILITY NUCLEAR 2
|
||||
PROBABILITY REVOLUTION 2
|
||||
|
||||
6
yogstation/code/_onclick/hud/vampire.dm
Normal file
6
yogstation/code/_onclick/hud/vampire.dm
Normal file
@@ -0,0 +1,6 @@
|
||||
/obj/screen/vampire
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "power_display"
|
||||
name = "usable blood"
|
||||
screen_loc = ui_lingchemdisplay
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
350
yogstation/code/datums/antagonists/vampire.dm
Normal file
350
yogstation/code/datums/antagonists/vampire.dm
Normal file
@@ -0,0 +1,350 @@
|
||||
#define ALL_POWERS_UNLOCKED 800
|
||||
|
||||
/datum/antagonist/vampire
|
||||
|
||||
name = "Vampire"
|
||||
antagpanel_category = "Vampire"
|
||||
roundend_category = "vampires"
|
||||
job_rank = ROLE_VAMPIRE
|
||||
|
||||
var/usable_blood = 0
|
||||
var/total_blood = 0
|
||||
var/fullpower = FALSE
|
||||
var/draining
|
||||
var/list/objectives_given = list()
|
||||
|
||||
var/iscloaking = FALSE
|
||||
|
||||
var/list/powers = list() // list of current powers
|
||||
|
||||
var/obj/item/clothing/suit/draculacoat/coat
|
||||
|
||||
var/list/upgrade_tiers = list(
|
||||
/obj/effect/proc_holder/spell/self/rejuvenate = 0,
|
||||
/obj/effect/proc_holder/spell/targeted/hypnotise = 0,
|
||||
/datum/vampire_passive/vision = 175,
|
||||
/obj/effect/proc_holder/spell/self/shapeshift = 175,
|
||||
/obj/effect/proc_holder/spell/self/cloak = 225,
|
||||
/obj/effect/proc_holder/spell/targeted/disease = 275,
|
||||
/obj/effect/proc_holder/spell/bats = 350,
|
||||
/obj/effect/proc_holder/spell/self/batform = 350,
|
||||
/obj/effect/proc_holder/spell/self/screech = 315,
|
||||
/datum/vampire_passive/regen = 425,
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/mistform = 500,
|
||||
/datum/vampire_passive/full = 666,
|
||||
/obj/effect/proc_holder/spell/self/summon_coat = 666,
|
||||
/obj/effect/proc_holder/spell/targeted/vampirize = 700,
|
||||
/obj/effect/proc_holder/spell/self/revive = 800)
|
||||
|
||||
/datum/antagonist/vampire/get_admin_commands()
|
||||
. = ..()
|
||||
.["Full Power"] = CALLBACK(src,.proc/admin_set_full_power)
|
||||
.["Set Blood Amount"] = CALLBACK(src,.proc/admin_set_blood)
|
||||
|
||||
/datum/antagonist/vampire/proc/admin_set_full_power(mob/admin)
|
||||
usable_blood = ALL_POWERS_UNLOCKED
|
||||
total_blood = ALL_POWERS_UNLOCKED
|
||||
check_vampire_upgrade()
|
||||
message_admins("[key_name_admin(admin)] made [owner.current] a full power vampire..")
|
||||
log_admin("[key_name(admin)] made [owner.current] a full power vampire..")
|
||||
|
||||
/datum/antagonist/vampire/proc/admin_set_blood(mob/admin)
|
||||
total_blood = input(admin, "Set Vampire Total Blood", "Total Blood", total_blood) as null|num
|
||||
usable_blood = min((input(admin, "Set Vampire Usable Blood", "Usable Blood", usable_blood) as null|num), total_blood)
|
||||
check_vampire_upgrade()
|
||||
message_admins("[key_name_admin(admin)] set [owner.current]'s total blood to [total_blood], and usable blood to [usable_blood].")
|
||||
log_admin("[key_name(admin)] set [owner.current]'s total blood to [total_blood], and usable blood to [usable_blood].")
|
||||
|
||||
/datum/antagonist/vampire/on_gain()
|
||||
SSticker.mode.vampires += owner
|
||||
give_objectives()
|
||||
check_vampire_upgrade()
|
||||
owner.special_role = "vampire"
|
||||
owner.current.faction += "vampire"
|
||||
SSticker.mode.update_vampire_icons_added(owner)
|
||||
var/mob/living/carbon/human/C = owner.current
|
||||
if(istype(C))
|
||||
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
if(B)
|
||||
B.vital = FALSE
|
||||
B.decoy_override = TRUE
|
||||
..()
|
||||
|
||||
/datum/antagonist/vampire/on_removal()
|
||||
remove_vampire_powers()
|
||||
owner.current.faction -= "vampire"
|
||||
SSticker.mode.vampires -= owner
|
||||
owner.special_role = null
|
||||
if(ishuman(owner.current))
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(owner && H.hud_used && H.hud_used.vamp_blood_display)
|
||||
H.hud_used.vamp_blood_display.invisibility = INVISIBILITY_ABSTRACT
|
||||
SSticker.mode.update_vampire_icons_removed(owner)
|
||||
for(var/O in objectives_given)
|
||||
owner.objectives -= O
|
||||
LAZYCLEARLIST(objectives_given)
|
||||
if(owner.current)
|
||||
to_chat(owner.current,"<span class='userdanger'>Your powers have been quenched! You are no longer a vampire</span>")
|
||||
owner.special_role = null
|
||||
var/mob/living/carbon/human/C = owner.current
|
||||
if(istype(C))
|
||||
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
if(B && (B.decoy_override != initial(B.decoy_override)))
|
||||
B.vital = TRUE
|
||||
B.decoy_override = FALSE
|
||||
..()
|
||||
|
||||
/datum/antagonist/vampire/greet()
|
||||
to_chat(owner, "<span class='userdanger'>You are a Vampire!</span>")
|
||||
to_chat(owner, "<span class='danger bold'>You are a creature of the night -- holy water, the chapel, and space will cause you to burn.</span>")
|
||||
to_chat(owner, "<span class='notice bold'>Hit someone in the head with harm intent to start sucking their blood. However, only blood from living creatures is usable!</span>")
|
||||
to_chat(owner, "<span class='notice bold'>Coffins will heal you.</span>")
|
||||
if(LAZYLEN(objectives_given))
|
||||
owner.announce_objectives()
|
||||
owner.current.playsound_local(get_turf(owner.current), 'yogstation/sound/ambience/antag/vampire.ogg',80,0)
|
||||
|
||||
/datum/antagonist/vampire/proc/give_objectives()
|
||||
var/datum/objective/blood/blood_objective = new
|
||||
blood_objective.owner = owner
|
||||
blood_objective.gen_amount_goal()
|
||||
add_objective(blood_objective)
|
||||
|
||||
for(var/i = 1, i < CONFIG_GET(number/traitor_objectives_amount), i++)
|
||||
forge_single_objective()
|
||||
|
||||
if(!(locate(/datum/objective/escape) in owner.objectives))
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
add_objective(escape_objective)
|
||||
return
|
||||
|
||||
/datum/antagonist/vampire/proc/add_objective(var/datum/objective/O)
|
||||
owner.objectives += O
|
||||
objectives_given += O
|
||||
|
||||
/datum/antagonist/vampire/proc/forge_single_objective() //Returns how many objectives are added
|
||||
.=1
|
||||
if(prob(50))
|
||||
var/list/active_ais = active_ais()
|
||||
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
|
||||
var/datum/objective/destroy/destroy_objective = new
|
||||
destroy_objective.owner = owner
|
||||
destroy_objective.find_target()
|
||||
add_objective(destroy_objective)
|
||||
else if(prob(30))
|
||||
var/datum/objective/maroon/maroon_objective = new
|
||||
maroon_objective.owner = owner
|
||||
maroon_objective.find_target()
|
||||
add_objective(maroon_objective)
|
||||
else
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
kill_objective.owner = owner
|
||||
kill_objective.find_target()
|
||||
add_objective(kill_objective)
|
||||
else
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = owner
|
||||
steal_objective.find_target()
|
||||
add_objective(steal_objective)
|
||||
|
||||
/datum/antagonist/vampire/proc/vamp_burn(var/severe_burn = FALSE)
|
||||
var/mob/living/L = owner.current
|
||||
if(!L)
|
||||
return
|
||||
var/burn_chance = severe_burn ? 35 : 8
|
||||
if(prob(burn_chance) && L.health >= 50)
|
||||
switch(L.health)
|
||||
if(75 to 100)
|
||||
L.visible_message("<span class='warning'>[L]'s skin begins to flake!</span>", "<span class='danger'>Your skin flakes away...</span>")
|
||||
if(50 to 75)
|
||||
L.visible_message("<span class='warning'>[L]'s skin sizzles loudly!</span>", "<span class='danger'>Your skin sizzles!</span>", "You hear sizzling.")
|
||||
L.adjustFireLoss(3)
|
||||
else if(L.health < 50)
|
||||
if(!L.on_fire)
|
||||
L.visible_message("<span class='warning'>[L] catches fire!</span>", "<span class='danger'>Your skin catches fire!</span>")
|
||||
L.emote("scream")
|
||||
else
|
||||
L.visible_message("<span class='warning'>[L] continues to burn!</span>", "<span class='danger'>Your continue to burn!</span>")
|
||||
L.adjust_fire_stacks(5)
|
||||
L.IgniteMob()
|
||||
return
|
||||
|
||||
/datum/antagonist/vampire/proc/check_sun()
|
||||
var/mob/living/carbon/C = owner.current
|
||||
if(!C)
|
||||
return
|
||||
var/ax = C.x
|
||||
var/ay = C.y
|
||||
|
||||
for(var/i = 1 to 20)
|
||||
ax += SSsun.dx
|
||||
ay += SSsun.dy
|
||||
|
||||
var/turf/T = locate(round(ax, 0.5), round(ay, 0.5), C.z)
|
||||
|
||||
if(T.x == 1 || T.x == world.maxx || T.y == 1 || T.y == world.maxy)
|
||||
break
|
||||
|
||||
if(T.density)
|
||||
return
|
||||
vamp_burn(TRUE)
|
||||
|
||||
/datum/antagonist/vampire/proc/vampire_life()
|
||||
var/mob/living/carbon/C = owner.current
|
||||
if(!C)
|
||||
return
|
||||
if(owner && C.hud_used && C.hud_used.vamp_blood_display)
|
||||
C.hud_used.vamp_blood_display.invisibility = FALSE
|
||||
C.hud_used.vamp_blood_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#dd66dd'>[round(usable_blood, 1)]</font></div>"
|
||||
handle_vampire_cloak()
|
||||
if(istype(C.loc, /obj/structure/closet/crate/coffin))
|
||||
C.adjustBruteLoss(-4)
|
||||
C.adjustFireLoss(-4)
|
||||
C.adjustToxLoss(-4)
|
||||
C.adjustOxyLoss(-4)
|
||||
return
|
||||
if(!get_ability(/datum/vampire_passive/full) && istype(get_area(C.loc), /area/chapel))
|
||||
vamp_burn()
|
||||
if(isspaceturf(C.loc))
|
||||
check_sun()
|
||||
|
||||
|
||||
/datum/antagonist/vampire/proc/handle_bloodsucking(mob/living/carbon/human/H)
|
||||
draining = H
|
||||
var/mob/living/carbon/human/O = owner.current
|
||||
var/blood = 0
|
||||
var/old_bloodtotal = 0 //used to see if we increased our blood total
|
||||
var/old_bloodusable = 0 //used to see if we increased our blood usable
|
||||
log_attack("[O] ([O.ckey]) bit [H] ([H.ckey]) in the neck")
|
||||
O.visible_message("<span class='danger'>[O] grabs [H]'s neck harshly and sinks in their fangs!</span>", "<span class='danger'>You sink your fangs into [H] and begin to drain their blood.</span>", "<span class='notice'>You hear a soft puncture and a wet sucking noise.</span>")
|
||||
if(!iscarbon(owner))
|
||||
H.LAssailant = null
|
||||
else
|
||||
H.LAssailant = O
|
||||
playsound(O.loc, 'sound/weapons/bite.ogg', 50, 1)
|
||||
while(do_mob(O, H, 50))
|
||||
if(!is_vampire(O))
|
||||
to_chat(O, "<span class='warning'>Your fangs have disappeared!</span>")
|
||||
return
|
||||
old_bloodtotal = total_blood
|
||||
old_bloodusable = usable_blood
|
||||
if(!H.blood_volume)
|
||||
to_chat(O, "<span class='warning'>They've got no blood left to give.</span>")
|
||||
break
|
||||
if(H.stat != DEAD)
|
||||
blood = min(20, H.blood_volume)// if they have less than 20 blood, give them the remnant else they get 20 blood
|
||||
total_blood += blood / 2 //divide by 2 to counted the double suction since removing cloneloss -Melandor0
|
||||
usable_blood += blood / 2
|
||||
else
|
||||
blood = min(5, H.blood_volume) // The dead only give 5 blood
|
||||
total_blood += blood
|
||||
check_vampire_upgrade()
|
||||
if(old_bloodtotal != total_blood)
|
||||
to_chat(O, "<span class='notice'><b>You have accumulated [total_blood] [total_blood > 1 ? "units" : "unit"] of blood[usable_blood != old_bloodusable ? ", and have [usable_blood] left to use" : ""].</b></span>")
|
||||
H.blood_volume = max(H.blood_volume - 25, 0)
|
||||
if(ishuman(O))
|
||||
O.nutrition = min(O.nutrition + (blood / 2), NUTRITION_LEVEL_WELL_FED)
|
||||
playsound(O.loc, 'sound/items/eatfood.ogg', 40, 1)
|
||||
|
||||
draining = null
|
||||
to_chat(owner, "<span class='notice'>You stop draining [H.name] of blood.</span>")
|
||||
|
||||
/datum/antagonist/vampire/proc/force_add_ability(path)
|
||||
var/spell = new path(owner)
|
||||
if(istype(spell, /obj/effect/proc_holder/spell))
|
||||
owner.AddSpell(spell)
|
||||
powers += spell
|
||||
|
||||
/datum/antagonist/vampire/proc/get_ability(path)
|
||||
for(var/P in powers)
|
||||
var/datum/power = P
|
||||
if(power.type == path)
|
||||
return power
|
||||
return null
|
||||
|
||||
/datum/antagonist/vampire/proc/add_ability(path)
|
||||
if(!get_ability(path))
|
||||
force_add_ability(path)
|
||||
|
||||
/datum/antagonist/vampire/proc/remove_ability(ability)
|
||||
if(ability && (ability in powers))
|
||||
powers -= ability
|
||||
owner.spell_list.Remove(ability)
|
||||
qdel(ability)
|
||||
|
||||
|
||||
/datum/antagonist/vampire/proc/remove_vampire_powers()
|
||||
for(var/P in powers)
|
||||
remove_ability(P)
|
||||
owner.current.alpha = 255
|
||||
|
||||
/datum/antagonist/vampire/proc/check_vampire_upgrade(var/announce = TRUE)
|
||||
var/list/old_powers = powers.Copy()
|
||||
for(var/ptype in upgrade_tiers)
|
||||
var/level = upgrade_tiers[ptype]
|
||||
if(total_blood >= level)
|
||||
add_ability(ptype)
|
||||
if(announce)
|
||||
announce_new_power(old_powers)
|
||||
owner.current.update_sight() //deal with sight abilities
|
||||
|
||||
/datum/antagonist/vampire/proc/announce_new_power(list/old_powers)
|
||||
for(var/p in powers)
|
||||
if(!(p in old_powers))
|
||||
if(istype(p, /obj/effect/proc_holder/spell))
|
||||
var/obj/effect/proc_holder/spell/power = p
|
||||
to_chat(owner.current, "<span class='notice'>[power.gain_desc]</span>")
|
||||
else if(istype(p, /datum/vampire_passive))
|
||||
var/datum/vampire_passive/power = p
|
||||
to_chat(owner, "<span class='notice'>[power.gain_desc]</span>")
|
||||
|
||||
/datum/antagonist/vampire/proc/handle_vampire_cloak()
|
||||
if(!ishuman(owner.current))
|
||||
owner.current.alpha = 255
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/turf/T = get_turf(H)
|
||||
var/light_available = T.get_lumcount()
|
||||
|
||||
if(!istype(T))
|
||||
return 0
|
||||
|
||||
if(!iscloaking)
|
||||
H.alpha = 255
|
||||
return 0
|
||||
|
||||
if(light_available <= 0.25)
|
||||
H.alpha = round((255 * 0.15))
|
||||
return 1
|
||||
else
|
||||
H.alpha = round((255 * 0.80))
|
||||
|
||||
/datum/antagonist/vampire/roundend_report()
|
||||
var/list/result = list()
|
||||
|
||||
var/vampwin = TRUE
|
||||
|
||||
result += printplayer(owner)
|
||||
|
||||
var/objectives_text = ""
|
||||
if(objectives_given.len)//If the vampire had no objectives, don't need to process this.
|
||||
var/count = 1
|
||||
for(var/datum/objective/objective in objectives_given)
|
||||
if(objective.check_completion())
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'>Success!</span>"
|
||||
else
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
vampwin = FALSE
|
||||
count++
|
||||
|
||||
result += objectives_text
|
||||
|
||||
if(vampwin)
|
||||
result += "<span class='greentext'>The vampire was successful!</span>"
|
||||
else
|
||||
result += "<span class='redtext'>The vampire has failed!</span>"
|
||||
SEND_SOUND(owner.current, 'sound/ambience/ambifailure.ogg')
|
||||
|
||||
return result.Join("<br>")
|
||||
|
||||
#undef ALL_POWERS_UNLOCKED
|
||||
@@ -1,2 +1,49 @@
|
||||
/datum/mind
|
||||
var/quiet_round = FALSE //Won't be picked as target in most cases
|
||||
var/quiet_round = FALSE //Won't be picked as target in most cases
|
||||
|
||||
|
||||
|
||||
/datum/mind/proc/vampire_hook()
|
||||
var/text = "vampire"
|
||||
if(SSticker.mode.config_tag == "vampire")
|
||||
text = uppertext(text)
|
||||
text = "<i><b>[text]</b></i>: "
|
||||
if(is_vampire(current))
|
||||
text += "<b>VAMPIRE</b> | <a href='?src=\ref[src];vampire=clear'>human</a> | <a href='?src=\ref[src];vampire=full'>full-power</a>"
|
||||
else
|
||||
text += "<a href='?src=\ref[src];vampire=vampire'>vampire</a> | <b>HUMAN</b> | <a href='?src=\ref[src];vampire=full'>full-power</a>"
|
||||
if(current && current.client && (ROLE_VAMPIRE in current.client.prefs.be_special))
|
||||
text += " | Enabled in Prefs"
|
||||
else
|
||||
text += " | Disabled in Prefs"
|
||||
return text
|
||||
|
||||
/datum/mind/proc/vampire_href(href, mob/M)
|
||||
switch(href)
|
||||
if("clear")
|
||||
remove_vampire(current)
|
||||
message_admins("[key_name_admin(usr)] has de-vampired [current].")
|
||||
log_admin("[key_name(usr)] has de-vampired [current].")
|
||||
if("vampire")
|
||||
if(!is_vampire(current))
|
||||
message_admins("[key_name_admin(usr)] has vampired [current].")
|
||||
log_admin("[key_name(usr)] has vampired [current].")
|
||||
add_vampire(current)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>[current] is already a vampire!</span>")
|
||||
if("full")
|
||||
message_admins("[key_name_admin(usr)] has full-vampired [current].")
|
||||
log_admin("[key_name(usr)] has full-vampired [current].")
|
||||
if(!is_vampire(current))
|
||||
add_vampire(current)
|
||||
var/datum/antagonist/vampire/V = has_antag_datum(ANTAG_DATUM_VAMPIRE)
|
||||
if(V)
|
||||
V.total_blood = 1500
|
||||
V.usable_blood = 1500
|
||||
V.check_vampire_upgrade()
|
||||
else
|
||||
var/datum/antagonist/vampire/V = has_antag_datum(ANTAG_DATUM_VAMPIRE)
|
||||
if(V)
|
||||
V.total_blood = 1500
|
||||
V.usable_blood = 1500
|
||||
V.check_vampire_upgrade()
|
||||
31
yogstation/code/game/gamemodes/vampire/grave_fever.dm
Normal file
31
yogstation/code/game/gamemodes/vampire/grave_fever.dm
Normal file
@@ -0,0 +1,31 @@
|
||||
/datum/disease/vampire
|
||||
name = "Grave Fever"
|
||||
max_stages = 3
|
||||
stage_prob = 5
|
||||
spread_text = "Non-Contagious"
|
||||
spread_flags = DISEASE_SPREAD_SPECIAL
|
||||
cure_text = "Antibiotics"
|
||||
cures = list("spaceacillin")
|
||||
agent = "Grave Dust"
|
||||
cure_chance = 20
|
||||
viable_mobtypes = list(/mob/living/carbon/human)
|
||||
severity = DISEASE_SEVERITY_DANGEROUS
|
||||
disease_flags = CURABLE
|
||||
|
||||
/datum/disease/vampire/stage_act()
|
||||
..()
|
||||
var/toxdamage = stage * 2
|
||||
var/stuntime = (stage * 2) * 10
|
||||
|
||||
if(prob(10))
|
||||
affected_mob.emote(pick("cough","groan", "gasp"))
|
||||
|
||||
if(prob(15))
|
||||
if(prob(33))
|
||||
to_chat(affected_mob, "<span class='danger'>You feel sickly and weak.</span>")
|
||||
affected_mob.adjustToxLoss(toxdamage)
|
||||
|
||||
if(prob(5))
|
||||
to_chat(affected_mob, "<span class='danger'>Your joints ache horribly!</span>")
|
||||
affected_mob.Knockdown(stuntime)
|
||||
affected_mob.Stun(stuntime)
|
||||
80
yogstation/code/game/gamemodes/vampire/traitor_vamp.dm
Normal file
80
yogstation/code/game/gamemodes/vampire/traitor_vamp.dm
Normal file
@@ -0,0 +1,80 @@
|
||||
/datum/game_mode/traitor/vampire
|
||||
name = "traitor+vampire"
|
||||
config_tag = "traitorvamp"
|
||||
false_report_weight = 10
|
||||
traitors_possible = 3 //hard limit on traitors if scaling is turned off
|
||||
restricted_jobs = list("AI", "Cyborg")
|
||||
required_players = 25
|
||||
required_enemies = 1 // how many of each type are required
|
||||
recommended_enemies = 3
|
||||
reroll_friendly = 1
|
||||
|
||||
var/list/possible_vampires = list()
|
||||
var/const/vampire_amt = 2 //hard limit on vampires if scaling is turned off
|
||||
var/list/pre_vamps = list()
|
||||
|
||||
/datum/game_mode/traitor/vampire/announce()
|
||||
to_chat(world, "<B>The current game mode is - Traitor+Vampire!</B>")
|
||||
to_chat(world, "<B>There are vampires on the station along with some syndicate operatives out for their own gain! Do not let the vampires and the traitors succeed!</B>")
|
||||
|
||||
/datum/game_mode/traitor/vampire/can_start()
|
||||
if(!..())
|
||||
return 0
|
||||
possible_vampires = get_players_for_role(ROLE_VAMPIRE)
|
||||
if(possible_vampires.len < required_enemies)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/game_mode/traitor/vampire/pre_setup()
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/list/datum/mind/possible_vamps = get_players_for_role(ROLE_VAMPIRE)
|
||||
|
||||
var/num_vamp = 1
|
||||
|
||||
if(CONFIG_GET(number/traitor_scaling_coeff))
|
||||
num_vamp = max(1, min( round(num_players()/(CONFIG_GET(number/traitor_scaling_coeff)*4))+2, round(num_players()/(CONFIG_GET(number/traitor_scaling_coeff)*2)) ))
|
||||
else
|
||||
num_vamp = max(1, min(num_players(), vampire_amt/2))
|
||||
|
||||
var/list/old_antag_candidates = antag_candidates.Copy()
|
||||
if(possible_vamps.len>0)
|
||||
for(var/j = 0, j < num_vamp, j++)
|
||||
if(!possible_vamps.len) break
|
||||
var/datum/mind/vamp = pick(possible_vamps)
|
||||
pre_vamps += vamp
|
||||
possible_vamps -= vamp
|
||||
antag_candidates -= vamp
|
||||
vamp.special_role = "Vampire"
|
||||
vamp.restricted_roles = restricted_jobs
|
||||
antag_candidates = old_antag_candidates // So we still have a chance for a traitor vampire.
|
||||
return ..()
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/datum/game_mode/traitor/vampire/post_setup()
|
||||
for(var/datum/mind/vamp in pre_vamps)
|
||||
vamp.add_antag_datum(/datum/antagonist/vampire)
|
||||
..()
|
||||
return
|
||||
|
||||
/datum/game_mode/traitor/vampire/make_antag_chance(mob/living/carbon/human/character) //Assigns vampire to latejoiners
|
||||
var/vampcap = min( round(GLOB.joined_player_list.len/(CONFIG_GET(number/traitor_scaling_coeff)*4))+2, round(GLOB.joined_player_list.len/(CONFIG_GET(number/traitor_scaling_coeff)*2)) )
|
||||
if(SSticker.mode.vampires.len >= vampcap) //Caps number of latejoin antagonists
|
||||
..()
|
||||
return
|
||||
if(SSticker.mode.vampires.len <= (vampcap - 2) || prob(100 / (CONFIG_GET(number/traitor_scaling_coeff) * 4)))
|
||||
if(ROLE_VAMPIRE in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_VAMPIRE) && !jobban_isbanned(character, "Syndicate"))
|
||||
if(age_check(character.client))
|
||||
if(!(character.job in restricted_jobs))
|
||||
add_vampire(character)
|
||||
..()
|
||||
|
||||
/datum/game_mode/traitor/vampire/generate_report()
|
||||
return "We have received some fuzzy reports about the Syndicate cooperating with a bluespace demon.\
|
||||
Keep a watch out for syndicate agents, and have your Chaplain on standby."
|
||||
142
yogstation/code/game/gamemodes/vampire/vampire.dm
Normal file
142
yogstation/code/game/gamemodes/vampire/vampire.dm
Normal file
@@ -0,0 +1,142 @@
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/vampires = list()
|
||||
|
||||
/mob/living/carbon/human/Stat()
|
||||
. = ..()
|
||||
var/datum/antagonist/vampire/vamp = mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(vamp && statpanel("Status"))
|
||||
stat("Total Blood", vamp.total_blood)
|
||||
stat("Usable Blood", vamp.usable_blood)
|
||||
|
||||
/mob/living/carbon/human/Life()
|
||||
. = ..()
|
||||
if(is_vampire(src))
|
||||
var/datum/antagonist/vampire/vamp = mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
vamp.vampire_life()
|
||||
|
||||
|
||||
/datum/game_mode/vampire
|
||||
name = "vampire"
|
||||
config_tag = "vampire"
|
||||
antag_flag = ROLE_VAMPIRE
|
||||
false_report_weight = 1
|
||||
restricted_jobs = list("AI", "Cyborg")
|
||||
protected_jobs = list("Head of Security", "Captain", "Security Officer", "Chaplain", "Detective", "Warden", "Head of Personnel")
|
||||
required_players = 15
|
||||
required_enemies = 1
|
||||
recommended_enemies = 3
|
||||
enemy_minimum_age = 0
|
||||
|
||||
announce_text = "There are vampires onboard the station!\n\
|
||||
+ <span class='danger'>Vampires</span>: Suck the blood of the crew and complete your objectives!\n\
|
||||
+ <span class='notice'>Crew</span>: Kill the unholy vampires!"
|
||||
|
||||
var/vampires_possible = 4 //hard limit on vampires if scaling is turned off
|
||||
var/num_modifier = 0
|
||||
var/list/datum/mind/pre_vamps = list()
|
||||
|
||||
/datum/game_mode/vampire/pre_setup()
|
||||
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/num_vamps = 1
|
||||
|
||||
var/tsc = CONFIG_GET(number/traitor_scaling_coeff)
|
||||
if(tsc)
|
||||
num_vamps = max(1, min(round(num_players() / (tsc * 2)) + 2 + num_modifier, round(num_players() / tsc) + num_modifier))
|
||||
else
|
||||
num_vamps = max(1, min(num_players(), vampires_possible))
|
||||
|
||||
for(var/j = 0, j < num_vamps, j++)
|
||||
if (!antag_candidates.len)
|
||||
break
|
||||
var/datum/mind/vamp = pick(antag_candidates)
|
||||
pre_vamps += vamp
|
||||
vamp.special_role = "Vampire"
|
||||
vamp.restricted_roles = restricted_jobs
|
||||
log_game("[vamp.key] (ckey) has been selected as a Vampire")
|
||||
antag_candidates.Remove(vamp)
|
||||
|
||||
return pre_vamps.len > 0
|
||||
|
||||
|
||||
/datum/game_mode/vampire/post_setup()
|
||||
for(var/datum/mind/vamp in pre_vamps)
|
||||
vamp.add_antag_datum(/datum/antagonist/vampire)
|
||||
..()
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/proc/auto_declare_completion_vampire()
|
||||
if(vampires.len)
|
||||
var/text = "<br><font size=3><b>The vampires were:</b></font>"
|
||||
for(var/datum/mind/vamp in vampires)
|
||||
var/vampwin = 1
|
||||
if(!vamp.current)
|
||||
vampwin = 0
|
||||
|
||||
var/datum/antagonist/vampire/V = vamp.has_antag_datum(/datum/antagonist/vampire)
|
||||
|
||||
if(!V)
|
||||
continue
|
||||
|
||||
text += printplayer(vamp)
|
||||
|
||||
//Removed sanity if(vampire) because we -want- a runtime to inform us that the vampire list is incorrect and needs to be fixed.
|
||||
text += "<br><b>Usable Blood:</b> [V.usable_blood]."
|
||||
text += "<br><b>Total Blood:</b> [V.total_blood]"
|
||||
|
||||
if(vamp.objectives.len)
|
||||
var/count = 1
|
||||
for(var/datum/objective/objective in vamp.objectives)
|
||||
if(objective.check_completion())
|
||||
text += "<br><b>Objective #[count]</b>: [objective.explanation_text] <font color='green'><b>Success!</b></font>"
|
||||
SSblackbox.record_feedback("tally", "vampire_objective", 1, "[objective.type]|SUCCESS")
|
||||
else
|
||||
text += "<br><b>Objective #[count]</b>: [objective.explanation_text] <span class='danger'>Fail.</span>"
|
||||
SSblackbox.record_feedback("tally", "vampire_objective", 1, "[objective.type]|FAIL")
|
||||
vampwin = 0
|
||||
count++
|
||||
|
||||
if(vampwin)
|
||||
text += "<br><font color='green'><b>The vampire was successful!</b></font>"
|
||||
SSblackbox.record_feedback("tally", "vampire_success", 1, "SUCCESS")
|
||||
else
|
||||
text += "<br><span class='boldannounce'>The vampire has failed.</span>"
|
||||
SSblackbox.record_feedback("tally", "vampire_success", 1, "FAIL")
|
||||
text += "<br>"
|
||||
|
||||
to_chat(world, text)
|
||||
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/proc/add_vampire(mob/living/L)
|
||||
if(!L || !L.mind || is_vampire(L))
|
||||
return FALSE
|
||||
var/datum/antagonist/vampire/vamp = L.mind.add_antag_datum(/datum/antagonist/vampire)
|
||||
return vamp
|
||||
|
||||
/proc/remove_vampire(mob/living/L)
|
||||
if(!L || !L.mind || !is_vampire(L))
|
||||
return FALSE
|
||||
var/datum/antagonist/vamp = L.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
vamp.on_removal()
|
||||
return TRUE
|
||||
|
||||
/proc/is_vampire(mob/living/M)
|
||||
return M && M.mind && M.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
|
||||
/datum/game_mode/proc/update_vampire_icons_added(datum/mind/traitor_mind)
|
||||
var/datum/atom_hud/antag/vamphud = GLOB.huds[ANTAG_HUD_VAMPIRE]
|
||||
vamphud.join_hud(traitor_mind.current)
|
||||
set_antag_hud(traitor_mind.current, "vampire")
|
||||
|
||||
/datum/game_mode/proc/update_vampire_icons_removed(datum/mind/traitor_mind)
|
||||
var/datum/atom_hud/antag/vamphud = GLOB.huds[ANTAG_HUD_VAMPIRE]
|
||||
vamphud.leave_hud(traitor_mind.current)
|
||||
set_antag_hud(traitor_mind.current, null)
|
||||
52
yogstation/code/game/gamemodes/vampire/vampire_bat.dm
Normal file
52
yogstation/code/game/gamemodes/vampire/vampire_bat.dm
Normal file
@@ -0,0 +1,52 @@
|
||||
/mob/living/simple_animal/hostile/vampire_bat
|
||||
name = "vampire bat"
|
||||
desc = "A bat that sucks blood. Keep away from medical bays."
|
||||
icon_state = "bat"
|
||||
icon_living = "bat"
|
||||
icon_dead = "bat_dead"
|
||||
icon_gib = "bat_dead"
|
||||
turns_per_move = 1
|
||||
response_help = "brushes aside"
|
||||
response_disarm = "flails at"
|
||||
response_harm = "hits"
|
||||
speak_chance = 0
|
||||
maxHealth = 20
|
||||
health = 20
|
||||
see_in_dark = 10
|
||||
harm_intent_damage = 7
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 7
|
||||
attacktext = "bites"
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1)
|
||||
pass_flags = PASSTABLE
|
||||
faction = list("hostile", "vampire")
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
obj_damage = 0
|
||||
environment_smash = ENVIRONMENT_SMASH_NONE
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
mob_size = MOB_SIZE_TINY
|
||||
movement_type = FLYING
|
||||
speak_emote = list("squeaks")
|
||||
var/max_co2 = 0 //to be removed once metastation map no longer use those for Sgt Araneus
|
||||
var/min_oxy = 0
|
||||
var/max_tox = 0
|
||||
|
||||
var/mob/living/controller
|
||||
|
||||
|
||||
//Space bats need no air to fly in.
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/vampire_bat/CanAttack(atom/the_target)
|
||||
. = ..()
|
||||
if(isliving(the_target) && is_vampire(the_target))
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/vampire_bat/death()
|
||||
if(isliving(controller))
|
||||
controller.forceMove(loc)
|
||||
mind.transfer_to(controller)
|
||||
controller.Knockdown(120)
|
||||
to_chat(controller, "<span class='userdanger'>The force of being exiled from your bat form knocks you down!</span>")
|
||||
. = ..()
|
||||
20
yogstation/code/game/gamemodes/vampire/vampire_bite.dm
Normal file
20
yogstation/code/game/gamemodes/vampire/vampire_bite.dm
Normal file
@@ -0,0 +1,20 @@
|
||||
/mob/living/carbon/human/proc/handle_vamp_biting(var/mob/living/carbon/human/M)
|
||||
if(!is_vampire(M) || M == src || M.zone_selected != "head")
|
||||
return FALSE
|
||||
var/datum/antagonist/vampire/V = M.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
if((NOBLOOD in dna.species.species_traits) || dna.species.exotic_blood || !blood_volume)
|
||||
to_chat(M, "<span class='warning'>They have no blood!</span>")
|
||||
return FALSE
|
||||
if(is_vampire(src))
|
||||
to_chat(M, "<span class='warning'>Your fangs fail to pierce [name]'s cold flesh</span>")
|
||||
return FALSE
|
||||
if(dna.species.name == "skeleton")
|
||||
to_chat(M, "<span class='warning'>There is no blood in a skeleton!</span>")
|
||||
return FALSE
|
||||
if(!ckey)
|
||||
to_chat(M, "<span class='warning'>[src]'s blood is stale and useless.</span>")
|
||||
return FALSE
|
||||
if(V.draining)
|
||||
return FALSE
|
||||
V.handle_bloodsucking(src)
|
||||
return TRUE
|
||||
15
yogstation/code/game/gamemodes/vampire/vampire_hud.dm
Normal file
15
yogstation/code/game/gamemodes/vampire/vampire_hud.dm
Normal file
@@ -0,0 +1,15 @@
|
||||
/datum/hud
|
||||
var/obj/screen/vampire/vamp_blood_display
|
||||
|
||||
/datum/hud/New(mob/owner, ui_style = 'icons/mob/screen_midnight.dmi')
|
||||
. = ..()
|
||||
vamp_blood_display = new /obj/screen/vampire()
|
||||
|
||||
/datum/hud/human/New(mob/living/carbon/human/owner, ui_style = 'icons/mob/screen_midnight.dmi')
|
||||
. = ..()
|
||||
vamp_blood_display = new /obj/screen/vampire()
|
||||
infodisplay += vamp_blood_display
|
||||
|
||||
/datum/hud/Destroy()
|
||||
. = ..()
|
||||
vamp_blood_display = null
|
||||
13
yogstation/code/game/gamemodes/vampire/vampire_objectives.dm
Normal file
13
yogstation/code/game/gamemodes/vampire/vampire_objectives.dm
Normal file
@@ -0,0 +1,13 @@
|
||||
/datum/objective/blood/proc/gen_amount_goal(lowbound = 450, highbound = 700)
|
||||
target_amount = rand (lowbound,highbound)
|
||||
explanation_text = "Extract [target_amount] units of blood."
|
||||
return target_amount
|
||||
|
||||
/datum/objective/blood/check_completion()
|
||||
if(!owner)
|
||||
return FALSE
|
||||
var/datum/antagonist/vampire/vamp = owner.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(vamp && target_amount <= vamp.total_blood)
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
31
yogstation/code/game/gamemodes/vampire/vampire_other.dm
Normal file
31
yogstation/code/game/gamemodes/vampire/vampire_other.dm
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
In this file:
|
||||
various vampire interactions and items
|
||||
*/
|
||||
|
||||
|
||||
/obj/item/clothing/suit/draculacoat
|
||||
name = "Vampire Coat"
|
||||
desc = "What is a man? A miserable little pile of secrets."
|
||||
alternate_worn_icon = 'yogstation/icons/mob/suit.dmi'
|
||||
icon = 'yogstation/icons/obj/clothing/suits.dmi'
|
||||
icon_state = "draculacoat"
|
||||
item_state = "draculacoat"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
flags_inv = HIDEJUMPSUIT
|
||||
armor = list("melee" = 30, "bullet" = 20, "laser" = 10, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0)
|
||||
|
||||
/mob/living/carbon/human/handle_fire()
|
||||
. = ..()
|
||||
if(mind)
|
||||
var/datum/antagonist/vampire/L = mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(on_fire && stat == DEAD && L && !L.get_ability(/datum/vampire_passive/full))
|
||||
dust()
|
||||
|
||||
/obj/item/storage/book/bible/attack(mob/living/M, mob/living/carbon/human/user, heal_mode = TRUE)
|
||||
. = ..()
|
||||
if(!(user.mind && user.mind.isholy) && is_vampire(user))
|
||||
to_chat(user, "<span class='danger'>[deity_name] channels through \the [src] and sets you ablaze for your blasphemy!</span>")
|
||||
user.fire_stacks += 5
|
||||
user.IgniteMob()
|
||||
user.emote("scream", 1)
|
||||
403
yogstation/code/game/gamemodes/vampire/vampire_powers.dm
Normal file
403
yogstation/code/game/gamemodes/vampire/vampire_powers.dm
Normal file
@@ -0,0 +1,403 @@
|
||||
/obj/effect/proc_holder/spell
|
||||
var/gain_desc
|
||||
var/blood_used = 0
|
||||
var/vamp_req = FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/cast_check(skipcharge = 0, mob/user = usr)
|
||||
. = ..(skipcharge, user)
|
||||
if(vamp_req)
|
||||
if(!is_vampire(user))
|
||||
return FALSE
|
||||
var/datum/antagonist/vampire/V = user.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(!V)
|
||||
return FALSE
|
||||
if(V.usable_blood < blood_used)
|
||||
to_chat(user, "<span class='warning'>You do not have enough blood to cast this!</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/Initialize()
|
||||
. = ..()
|
||||
if(vamp_req)
|
||||
clothes_req = FALSE
|
||||
range = 1
|
||||
human_req = FALSE //so we can cast stuff while a bat, too
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/before_cast(list/targets)
|
||||
. = ..()
|
||||
if(vamp_req)
|
||||
// sanity check before we cast
|
||||
if(!is_vampire(usr))
|
||||
targets.Cut()
|
||||
return
|
||||
|
||||
if(!blood_used)
|
||||
return
|
||||
|
||||
// enforce blood
|
||||
var/datum/antagonist/vampire/vampire = usr.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
|
||||
if(blood_used <= vampire.usable_blood)
|
||||
vampire.usable_blood -= blood_used
|
||||
else
|
||||
// stop!!
|
||||
targets.Cut()
|
||||
|
||||
if(LAZYLEN(targets))
|
||||
to_chat(usr, "<span class='notice'><b>You have [vampire.usable_blood] left to use.</b></span>")
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/can_target(mob/living/target)
|
||||
. = ..()
|
||||
if(vamp_req && is_vampire(target))
|
||||
return FALSE
|
||||
/datum/vampire_passive
|
||||
var/gain_desc
|
||||
|
||||
/datum/vampire_passive/New()
|
||||
..()
|
||||
if(!gain_desc)
|
||||
gain_desc = "You have gained \the [src] ability."
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/datum/vampire_passive/regen
|
||||
gain_desc = "Your rejuvination abilities have improved and will now heal you over time when used."
|
||||
|
||||
/datum/vampire_passive/vision
|
||||
gain_desc = "Your vampiric vision has improved."
|
||||
|
||||
/datum/vampire_passive/full
|
||||
gain_desc = "You have reached your full potential and are no longer weak to the effects of anything holy and your vision has been improved greatly."
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/effect/proc_holder/spell/self/rejuvenate
|
||||
name = "Rejuvenate"
|
||||
desc= "Flush your system with spare blood to remove any incapacitating effects."
|
||||
action_icon_state = "rejuv"
|
||||
charge_max = 200
|
||||
stat_allowed = 1
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_background_icon_state = "bg_demon"
|
||||
vamp_req = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/self/rejuvenate/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/U = user
|
||||
U.stuttering = 0
|
||||
|
||||
var/datum/antagonist/vampire/V = U.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(!V) //sanity check
|
||||
return
|
||||
for(var/i = 1 to 5)
|
||||
U.adjustStaminaLoss(-10)
|
||||
if(V.get_ability(/datum/vampire_passive/regen))
|
||||
U.adjustBruteLoss(-1)
|
||||
U.adjustOxyLoss(-2.5)
|
||||
U.adjustToxLoss(-1)
|
||||
U.adjustFireLoss(-1)
|
||||
sleep(7.5)
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/hypnotise
|
||||
name = "Hypnotize (20)"
|
||||
desc= "A piercing stare that incapacitates your victim for a good length of time."
|
||||
action_icon_state = "hypnotize"
|
||||
blood_used = 20
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_background_icon_state = "bg_demon"
|
||||
vamp_req = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/hypnotise/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/target in targets)
|
||||
user.visible_message("<span class='warning'>[user]'s eyes flash briefly as he stares into [target]'s eyes</span>")
|
||||
if(do_mob(user, target, 50))
|
||||
to_chat(user, "<span class='warning'>Your piercing gaze knocks out [target].</span>")
|
||||
to_chat(target, "<span class='warning'>You find yourself unable to move and barely able to speak.</span>")
|
||||
target.Knockdown(150)
|
||||
target.Stun(150)
|
||||
target.stuttering = 10
|
||||
else
|
||||
revert_cast(usr)
|
||||
to_chat(usr, "<span class='warning'>You broke your gaze.</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/self/shapeshift
|
||||
name = "Shapeshift (50)"
|
||||
desc = "Changes your name and appearance at the cost of 50 blood and has a cooldown of 3 minutes."
|
||||
gain_desc = "You have gained the shapeshifting ability, at the cost of stored blood you can change your form permanently."
|
||||
action_icon_state = "genetic_poly"
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_background_icon_state = "bg_demon"
|
||||
blood_used = 50
|
||||
vamp_req = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/self/shapeshift/cast(list/targets, mob/user = usr)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
user.visible_message("<span class='warning'>[H] transforms!</span>")
|
||||
randomize_human(H)
|
||||
user.regenerate_icons()
|
||||
|
||||
/obj/effect/proc_holder/spell/self/cloak
|
||||
name = "Cloak of Darkness"
|
||||
desc = "Toggles whether you are currently cloaking yourself in darkness."
|
||||
gain_desc = "You have gained the Cloak of Darkness ability which when toggled makes you near invisible in the shroud of darkness."
|
||||
action_icon_state = "cloak"
|
||||
charge_max = 10
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_background_icon_state = "bg_demon"
|
||||
vamp_req = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/self/cloak/Initialize()
|
||||
. = ..()
|
||||
update_name()
|
||||
|
||||
/obj/effect/proc_holder/spell/self/cloak/proc/update_name()
|
||||
var/mob/living/user = loc
|
||||
if(!ishuman(user) || !is_vampire(user))
|
||||
return
|
||||
var/datum/antagonist/vampire/V = user.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
name = "[initial(name)] ([V.iscloaking ? "Deactivate" : "Activate"])"
|
||||
|
||||
/obj/effect/proc_holder/spell/self/cloak/cast(list/targets, mob/user = usr)
|
||||
var/datum/antagonist/vampire/V = user.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(!V)
|
||||
return
|
||||
V.iscloaking = !V.iscloaking
|
||||
update_name()
|
||||
to_chat(user, "<span class='notice'>You will now be [V.iscloaking ? "hidden" : "seen"] in darkness.</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/disease
|
||||
name = "Diseased Touch (100)"
|
||||
desc = "Touches your victim with infected blood giving them Grave Fever, which will, left untreated, causes toxic building and frequent collapsing."
|
||||
gain_desc = "You have gained the Diseased Touch ability which causes those you touch to become weak unless treated medically."
|
||||
action_icon_state = "disease"
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_background_icon_state = "bg_demon"
|
||||
blood_used = 100
|
||||
vamp_req = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/disease/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/carbon/target in targets)
|
||||
to_chat(user, "<span class='warning'>You stealthily infect [target] with your diseased touch.</span>")
|
||||
target.help_shake_act(user)
|
||||
if(is_vampire(target))
|
||||
to_chat(user, "<span class='warning'>They seem to be unaffected.</span>")
|
||||
continue
|
||||
var/datum/disease/D = new /datum/disease/vampire
|
||||
target.ForceContractDisease(D)
|
||||
|
||||
/obj/effect/proc_holder/spell/self/screech
|
||||
name = "Chiropteran Screech (30)"
|
||||
desc = "An extremely loud shriek that stuns nearby humans and breaks windows as well."
|
||||
gain_desc = "You have gained the Chiropteran Screech ability which stuns anything with ears in a large radius and shatters glass in the process."
|
||||
action_icon_state = "reeee"
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_background_icon_state = "bg_demon"
|
||||
blood_used = 30
|
||||
vamp_req = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/self/screech/cast(list/targets, mob/user = usr)
|
||||
user.visible_message("<span class='warning'>[user] lets out an ear piercing shriek!</span>", "<span class='warning'>You let out a loud shriek.</span>", "<span class='warning'>You hear a loud painful shriek!</span>")
|
||||
for(var/mob/living/carbon/C in hearers(4))
|
||||
if(C == user || (ishuman(C) && C.get_ear_protection()) || is_vampire(C))
|
||||
continue
|
||||
to_chat(C, "<span class='warning'><font size='3'><b>You hear a ear piercing shriek and your senses dull!</font></b></span>")
|
||||
C.Knockdown(4)
|
||||
C.adjustEarDamage(0, 30)
|
||||
C.stuttering = 250
|
||||
C.Stun(4)
|
||||
C.Jitter(150)
|
||||
for(var/obj/structure/window/W in view(4))
|
||||
W.take_damage(75)
|
||||
playsound(user.loc, 'sound/effects/screech.ogg', 100, 1)
|
||||
|
||||
/obj/effect/proc_holder/spell/bats
|
||||
name = "Summon Bats (75)"
|
||||
desc = "You summon a pair of space bats who attack nearby targets until they or their target is dead."
|
||||
gain_desc = "You have gained the Summon Bats ability."
|
||||
action_icon_state = "bats"
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_background_icon_state = "bg_demon"
|
||||
charge_max = 1200
|
||||
vamp_req = TRUE
|
||||
blood_used = 75
|
||||
var/num_bats = 2
|
||||
|
||||
/obj/effect/proc_holder/spell/bats/choose_targets(mob/user = usr)
|
||||
var/list/turf/locs = new
|
||||
for(var/direction in GLOB.alldirs) //looking for bat spawns
|
||||
if(locs.len == num_bats) //we found 2 locations and thats all we need
|
||||
break
|
||||
var/turf/T = get_step(usr, direction) //getting a loc in that direction
|
||||
if(AStar(user, T, /turf/proc/Distance, 1, simulated_only = 0)) // if a path exists, so no dense objects in the way its valid salid
|
||||
locs += T
|
||||
|
||||
// pad with player location
|
||||
for(var/i = locs.len + 1 to num_bats)
|
||||
locs += user.loc
|
||||
|
||||
perform(locs, user = user)
|
||||
|
||||
/obj/effect/proc_holder/spell/bats/cast(list/targets, mob/user = usr)
|
||||
for(var/T in targets)
|
||||
new /mob/living/simple_animal/hostile/vampire_bat(T)
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/mistform
|
||||
name = "Mist Form (30)"
|
||||
gain_desc = "You have gained the Mist Form ability which allows you to take on the form of mist for a short period and pass over any obstacle in your path."
|
||||
blood_used = 30
|
||||
action_background_icon_state = "bg_demon"
|
||||
vamp_req = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/mistform/Initialize()
|
||||
. = ..()
|
||||
range = -1
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/vampirize
|
||||
name = "Lilith's Pact (500)"
|
||||
desc = "You drain a victim's blood, and fill them with new blood, blessed by Lilith, turning them into a new vampire."
|
||||
gain_desc = "You have gained the ability to force someone, given time, to become a vampire."
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_background_icon_state = "bg_demon"
|
||||
action_icon_state = "oath"
|
||||
blood_used = 500
|
||||
vamp_req = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/vampirize/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/carbon/target in targets)
|
||||
if(is_vampire(target))
|
||||
to_chat(user, "<span class='warning'>They're already a vampire!</span>")
|
||||
continue
|
||||
target.visible_message("<span class='warning'>[user] latches onto [target]'s neck, and a pure dread eminates from them.</span>", "<span class='warning'>You latch onto [target]'s neck, preparing to transfer your unholy blood to them.</span>", "<span class='warning'>A dreadful feeling overcomes you</span>")
|
||||
target.reagents.add_reagent("salbutamol", 10) //incase you're choking the victim
|
||||
for(var/progress = 0, progress <= 3, progress++)
|
||||
switch(progress)
|
||||
if(1)
|
||||
to_chat(target, "<span class='warning'>Visions of dread flood your vision...</span>")
|
||||
to_chat(user, "<span class='notice'>We begin to drain [target]'s blood in, so Lilith can bless it.</span>")
|
||||
if(2)
|
||||
to_chat(target, "<span class='danger'>Demonic whispers fill your mind, and they become irressistible...</span>")
|
||||
if(3)
|
||||
to_chat(target, "<span class='danger'>The world blanks out, and you see a demo- no ange- demon- lil- glory- blessing... Lilith.</span>")
|
||||
to_chat(user, "<span class='notice'>Excitement builds up in you as [target] sees the blessing of Lilith.</span>")
|
||||
if(!do_mob(user, target, 70))
|
||||
to_chat(user, "<span class='danger'>The pact has failed! [target] has not became a vampire.</span>")
|
||||
to_chat(target, "<span class='notice'>The visions stop, and you relax.</span>")
|
||||
return
|
||||
if(!QDELETED(user) && !QDELETED(target))
|
||||
to_chat(user, "<span class='notice'>. . .</span>")
|
||||
to_chat(target, "<span class='italics'>Come to me, child.</span>")
|
||||
sleep(10)
|
||||
to_chat(target, "<span class='italics'>The world hasn't treated you well, has it?</span>")
|
||||
sleep(15)
|
||||
to_chat(target, "<span class='italics'>Strike fear into their hearts...</span>")
|
||||
to_chat(user, "<span class='notice italics bold'>They have signed the pact!</span>")
|
||||
to_chat(target, "<span class='userdanger'>You sign Lilith's Pact.</span>")
|
||||
target.mind.store_memory("<B>[user] showed you the glory of Lilith. <I>You are not required to respect or obey [user] in any way</I></B>")
|
||||
add_vampire(target)
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/self/revive
|
||||
name = "Revive"
|
||||
gain_desc = "You have gained the ability to revive after death... However you can still be cremated/gibbed, and you will disintergrate if you're in the chapel!"
|
||||
desc = "Revives you, provided you are not in the chapel!"
|
||||
blood_used = 0
|
||||
stat_allowed = TRUE
|
||||
charge_max = 1000
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_icon_state = "coffin"
|
||||
action_background_icon_state = "bg_demon"
|
||||
vamp_req = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/self/revive/cast(list/targets, mob/user = usr)
|
||||
if(!is_vampire(user) || !isliving(user))
|
||||
revert_cast()
|
||||
return
|
||||
if(user.stat != DEAD)
|
||||
to_chat(user, "<span class='notice'>We aren't dead enough to do that yet!</span>")
|
||||
revert_cast()
|
||||
return
|
||||
if(user.reagents.has_reagent("holywater"))
|
||||
to_chat(user, "<span class='danger'>We cannot revive, holy water is in our system!</span>")
|
||||
return
|
||||
var/mob/living/L = user
|
||||
if(istype(get_area(L.loc), /area/chapel))
|
||||
L.visible_message("<span class='warning'>[L] disintergrates into dust!</span>", "<span class='userdanger'>Holy energy seeps into our very being, disintergrating us instantly!</span>", "You hear sizzling.")
|
||||
new /obj/effect/decal/remains/human(L.loc)
|
||||
L.dust()
|
||||
to_chat(L, "<span class='notice'>We begin to reanimate... this will take a minute.</span>")
|
||||
addtimer(CALLBACK(src, .proc/revive, L), 600)
|
||||
|
||||
/obj/effect/proc_holder/spell/self/revive/proc/revive(mob/living/user)
|
||||
if(user.reagents.has_reagent("holywater"))
|
||||
to_chat(user, "<span class='danger'>We cannot revive, holy water is in our system!</span>")
|
||||
return
|
||||
user.revive()
|
||||
user.visible_message("<span class='warning'>[user] reanimates from death!</span>", "<span class='notice'>We get back up.</span>")
|
||||
user.fully_heal(TRUE)
|
||||
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/self/summon_coat
|
||||
name = "Summon Dracula Coat (5)"
|
||||
gain_desc = "Now that you have reached full power, you can now pull a vampiric coat out of thin air!"
|
||||
blood_used = 5
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_icon_state = "coat"
|
||||
action_background_icon_state = "bg_demon"
|
||||
vamp_req = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/self/summon_coat/cast(list/targets, mob/user = usr)
|
||||
if(!is_vampire(user) || !isliving(user))
|
||||
revert_cast()
|
||||
return
|
||||
var/datum/antagonist/vampire/V = user.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(!V)
|
||||
return
|
||||
if(QDELETED(V.coat) || !V.coat)
|
||||
V.coat = new /obj/item/clothing/suit/draculacoat(user.loc)
|
||||
else if(get_dist(V.coat, user) > 1 || !(V.coat in user.GetAllContents()))
|
||||
V.coat.forceMove(user.loc)
|
||||
user.put_in_hands(V.coat)
|
||||
to_chat(user, "<span class='notice'>You summon your dracula coat.</span>")
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/self/batform
|
||||
name = "Bat Form (15)"
|
||||
gain_desc = "You now have the Bat Form ability, which allows you to turn into a bat (and back!)"
|
||||
desc = "Transform into a bat!"
|
||||
action_icon_state = "bat"
|
||||
charge_max = 200
|
||||
blood_used = 0 //this is only 0 so we can do our own custom checks
|
||||
action_icon = 'yogstation/icons/mob/vampire.dmi'
|
||||
action_background_icon_state = "bg_demon"
|
||||
vamp_req = TRUE
|
||||
var/mob/living/simple_animal/hostile/vampire_bat/bat
|
||||
|
||||
/obj/effect/proc_holder/spell/self/batform/cast(list/targets, mob/user = usr)
|
||||
var/datum/antagonist/vampire/V = user.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(!V)
|
||||
return FALSE
|
||||
if(!bat)
|
||||
if(V.usable_blood < 15)
|
||||
to_chat(user, "<span class='warning'>You do not have enough blood to cast this!</span>")
|
||||
return FALSE
|
||||
bat = new /mob/living/simple_animal/hostile/vampire_bat(user.loc)
|
||||
user.forceMove(bat)
|
||||
bat.controller = user
|
||||
user.status_flags |= GODMODE
|
||||
user.mind.transfer_to(bat)
|
||||
charge_counter = charge_max //so you don't need to wait 20 seconds to turn BACK.
|
||||
recharging = FALSE
|
||||
action.UpdateButtonIcon()
|
||||
else
|
||||
bat.controller.forceMove(bat.loc)
|
||||
bat.controller.status_flags &= ~GODMODE
|
||||
bat.mind.transfer_to(bat.controller)
|
||||
bat.controller = null //just so we don't accidently trigger the death() thing
|
||||
qdel(bat)
|
||||
7
yogstation/code/modules/admin/topic.dm
Normal file
7
yogstation/code/modules/admin/topic.dm
Normal file
@@ -0,0 +1,7 @@
|
||||
/datum/admins/proc/hippie_makeVampire(datum/admins/sr)
|
||||
if(sr.makeVampire())
|
||||
message_admins("[key_name(usr)] created a vampire.")
|
||||
log_admin("[key_name(usr)] created a vampire.")
|
||||
else
|
||||
message_admins("[key_name_admin(usr)] tried to create a vampire. Unfortunately, there were no candidates available.")
|
||||
log_admin("[key_name(usr)] failed to create a vampire.")
|
||||
19
yogstation/code/modules/admin/verbs/one_click_antag.dm
Normal file
19
yogstation/code/modules/admin/verbs/one_click_antag.dm
Normal file
@@ -0,0 +1,19 @@
|
||||
/datum/admins/proc/makeVampire()
|
||||
var/datum/game_mode/vampire/temp = new
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
temp.restricted_jobs += temp.protected_jobs
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
temp.restricted_jobs += "Assistant"
|
||||
var/list/mob/living/carbon/human/candidates = list()
|
||||
var/mob/living/carbon/human/H
|
||||
for(var/mob/living/carbon/human/applicant in GLOB.player_list)
|
||||
if((ROLE_VAMPIRE in applicant.client.prefs.be_special) && !applicant.stat && applicant.mind && !applicant.mind.special_role)
|
||||
if(!jobban_isbanned(applicant, "vampire") && !jobban_isbanned(applicant, "Syndicate"))
|
||||
if(temp.age_check(applicant.client) && !(applicant.job in temp.restricted_jobs) && !is_vampire(applicant))
|
||||
candidates += applicant
|
||||
|
||||
if(LAZYLEN(candidates))
|
||||
H = pick(candidates)
|
||||
add_vampire(H)
|
||||
return TRUE
|
||||
return FALSE
|
||||
@@ -1,2 +1,12 @@
|
||||
/atom/proc/pointed_at(var/mob/user)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_POINTED_AT, user)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_POINTED_AT, user) //why the hell is this here?
|
||||
|
||||
/mob
|
||||
var/client/oobe_client //when someone aghosts/uses a scrying orb, this holds the client while it's somewhere else
|
||||
|
||||
/atom/prepare_huds()
|
||||
hud_list = list()
|
||||
for(var/hud in hud_possible)
|
||||
var/image/I = image('yogstation/icons/mob/hud.dmi', src, "")
|
||||
I.appearance_flags = RESET_COLOR|RESET_TRANSFORM
|
||||
hud_list[hud] = I
|
||||
@@ -0,0 +1,17 @@
|
||||
/datum/reagent/holywater/on_mob_life(mob/living/M)
|
||||
. = ..()
|
||||
if(ishuman(M) && is_vampire(M) && prob(80))
|
||||
var/datum/antagonist/vampire/V = M.mind.has_antag_datum(ANTAG_DATUM_VAMPIRE)
|
||||
if(!V.get_ability(/datum/vampire_passive/full))
|
||||
switch(current_cycle)
|
||||
if(1 to 4)
|
||||
to_chat(M, "<span class='warning'>Something sizzles in your veins!</span>")
|
||||
M.adjustFireLoss(0.5)
|
||||
if(5 to 12)
|
||||
to_chat(M, "<span class='danger'>You feel an intense burning inside of you!</span>")
|
||||
M.adjustFireLoss(1)
|
||||
if(13 to INFINITY)
|
||||
M.visible_message("<span class='danger'>[M] suddenly bursts into flames!<span>", "<span class='userdanger'>You suddenly ignite in a holy fire!</span>")
|
||||
M.adjust_fire_stacks(3)
|
||||
M.IgniteMob() //Only problem with igniting people is currently the commonly availible fire suits make you immune to being on fire
|
||||
M.adjustFireLoss(3) //Hence the other damages... ain't I a bastard?
|
||||
BIN
yogstation/icons/mob/hud.dmi
Normal file
BIN
yogstation/icons/mob/hud.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 278 B |
Binary file not shown.
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 9.2 KiB |
BIN
yogstation/icons/mob/vampire.dmi
Normal file
BIN
yogstation/icons/mob/vampire.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.4 KiB |
Reference in New Issue
Block a user