diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index e1228b1506c4..52f595380821 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -51,6 +51,7 @@ #define ROLE_VAMPIRICACCIDENT "Vampiric Accident" #define ROLE_BLOODSUCKERBREAKOUT "Bloodsucker Breakout" #define ROLE_MONSTERHUNTER "Monster Hunter" +#define ROLE_SINFULDEMON "Demon of Sin" //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 @@ -91,6 +92,7 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_FUGITIVE, ROLE_BLOODSUCKER = /datum/game_mode/bloodsucker, ROLE_MONSTERHUNTER, + ROLE_SINFULDEMON )) //Job defines for what happens when you fail to qualify for any job during job selection diff --git a/code/__DEFINES/{yogs_defines}/antagonists.dm b/code/__DEFINES/{yogs_defines}/antagonists.dm index 0cfa66b79b1c..7afc8ce41334 100644 --- a/code/__DEFINES/{yogs_defines}/antagonists.dm +++ b/code/__DEFINES/{yogs_defines}/antagonists.dm @@ -5,6 +5,7 @@ #define ANTAG_DATUM_VEIL /datum/antagonist/veil #define ANTAG_DATUM_INFILTRATOR /datum/antagonist/infiltrator #define ANTAG_DATUM_HIJACKEDAI /datum/antagonist/hijacked_ai +#define ANTAG_DATUM_SINFULDEMON /datum/antagonist/sinfuldemon #define NOT_DOMINATING -1 #define MAX_LEADERS_GANG 3 diff --git a/code/__DEFINES/{yogs_defines}/is_helpers.dm b/code/__DEFINES/{yogs_defines}/is_helpers.dm index c694ceab2ea0..2d0791cb8c73 100644 --- a/code/__DEFINES/{yogs_defines}/is_helpers.dm +++ b/code/__DEFINES/{yogs_defines}/is_helpers.dm @@ -8,6 +8,8 @@ #define is_clockcult(M) (istype(M, /mob/living) && M.mind && M.mind.has_antag_datum(/datum/antagonist/clockcult)) +#define is_sinfuldemon(M) (M.mind && M.mind.has_antag_datum(/datum/antagonist/sinfuldemon)) + #define is_mindslaved(M) (istype(M, /mob/living) && M.mind && M.mind.has_antag_datum(/datum/antagonist/mindslave)) #define is_traitor(M) (istype(M, /mob/living) && M.mind && M.mind.has_antag_datum(/datum/antagonist/traitor) || is_mindslaved(M)) #define is_blood_brother(M) (istype(M, /mob/living) && M.mind && M.mind.has_antag_datum(/datum/antagonist/brother)) diff --git a/code/modules/antagonists/demon/demons.dm b/code/modules/antagonists/demon/demons.dm new file mode 100644 index 000000000000..98955d468ae1 --- /dev/null +++ b/code/modules/antagonists/demon/demons.dm @@ -0,0 +1,173 @@ +#define SIN_GLUTTONY "gluttony" +#define SIN_GREED "greed" +#define SIN_SLOTH "sloth" +#define SIN_WRATH "wrath" +#define SIN_ENVY "envy" +#define SIN_PRIDE "pride" + +/mob/living/carbon/human/Life() + . = ..() + if(is_sinfuldemon(src)) + var/datum/antagonist/sinfuldemon/demon = mind.has_antag_datum(/datum/antagonist/sinfuldemon) + demon.sinfuldemon_life() + +/datum/antagonist/sinfuldemon + name = "Sinful Demon" + roundend_category = "demons of sin" + antagpanel_category = "Demon" + job_rank = ROLE_SINFULDEMON + show_to_ghosts = TRUE + ///The sin a specific demon is assigned to. Defines what objectives and powers they'll receive. + var/demonsin + ///The list of choosable sins for demons. One will be assigned to a demon when spawned naturally. + var/static/list/demonsins = list(SIN_GLUTTONY, SIN_GREED, SIN_WRATH, SIN_ENVY, SIN_PRIDE) + var/static/list/demon_spells = typecacheof(list( + /obj/effect/proc_holder/spell/targeted/shapeshift/demon, + /obj/effect/proc_holder/spell/targeted/shapeshift/demon/gluttony, + /obj/effect/proc_holder/spell/targeted/shapeshift/demon/wrath, + /obj/effect/proc_holder/spell/targeted/forcewall/gluttony, + /obj/effect/proc_holder/spell/aoe_turf/conjure/summon_greedslots, + /obj/effect/proc_holder/spell/targeted/inflict_handler/ignite, + /obj/effect/proc_holder/spell/targeted/touch/envy, + /obj/effect/proc_holder/spell/aoe_turf/conjure/summon_mirror)) + +/datum/antagonist/sinfuldemon/proc/sinfuldemon_life() + var/mob/living/carbon/C = owner.current + if(!C) + return + if(istype(get_area(C), /area/chapel)) + demon_burn() + +///Handles burning and hurting sinful demons while they're in the chapel. +/datum/antagonist/sinfuldemon/proc/demon_burn() //sinful demons are even more vulnerable to the chapel than vampires, but can turn into their true form to negate this. + var/mob/living/L = owner.current + if(!L) + return + if(L.stat != DEAD) //demons however wont dust from the chapel so this needs to be a check to avoid spam while they're already dead + if(prob(50) && L.health >= 50) + switch(L.health) + if(85 to 100) + L.visible_message(span_warning("[L]'s skin begins to heat up and darken!"), span_danger("Your flesh begins to sear...")) + if(60 to 85) + L.visible_message(span_warning("[L]'s skin begins to melt apart!"), span_danger("Your skin is melting!"), "You hear sizzling.") + L.adjustFireLoss(5) + else if(L.health < 60) + if(!L.on_fire) + L.visible_message(span_warning("[L] lights up in a holy blaze!"), span_danger("Your skin catches fire!")) + L.emote("scream") + else + L.visible_message(span_warning("[L] continues to burn!"), span_danger("You continue to burn!")) + L.adjust_fire_stacks(5) + L.IgniteMob() + return + +/datum/antagonist/sinfuldemon/New() + . = ..() + demonsin = pick(demonsins) + +/datum/antagonist/sinfuldemon/proc/forge_objectives() + var/datum/objective/demon/O + switch(demonsin)//the 5 most interesting of the 8 sins. Left out sloth because it sounds boring, couldn't think of a good enough objective/power for acedia, and lust for obvious reasons. + if(SIN_GLUTTONY) + O = new /datum/objective/demon/gluttony + if(SIN_GREED) + O = new /datum/objective/demon/greed + if(SIN_WRATH) + O = new /datum/objective/demon/wrath + if(prob(50)) + var/N = pick(/datum/objective/assassinate, /datum/objective/assassinate/cloned, /datum/objective/assassinate/once) + var/datum/objective/assassinate/kill_objective = new N + kill_objective.owner = owner + kill_objective.find_target() + objectives += kill_objective + if(SIN_ENVY) + O = new /datum/objective/demon/envy + if(prob(50)) + var/datum/objective/escape/escape_with_identity/identity_theft = new + identity_theft.owner = owner + identity_theft.find_target() + identity_theft.update_explanation_text() + objectives += identity_theft + if(SIN_PRIDE) + O = new /datum/objective/demon/pride + objectives += O + +/datum/antagonist/sinfuldemon/can_be_owned(datum/mind/new_owner) + . = ..() + return . && (ishuman(new_owner.current) || iscyborg(new_owner.current)) + +/datum/antagonist/sinfuldemon/admin_add(datum/mind/new_owner,mob/admin) + var/choices = demonsins + "Random" + var/chosen_sin = input(admin,"What kind ?","Sin kind") as null|anything in choices + if(!chosen_sin) + return + if(chosen_sin in demonsins) + demonsin = chosen_sin + new_owner.add_antag_datum(src) + message_admins("[key_name_admin(admin)] has demonized [key_name_admin(new_owner)].") + log_admin("[key_name(admin)] has demonized [key_name(new_owner)].") + +/datum/antagonist/sinfuldemon/antag_listing_name() + return ..() + "(, demon of [demonsin])" // Boris Smith, demon of Wrath + +/datum/antagonist/sinfuldemon/greet() + to_chat(owner.current, span_warning("You remember your link to the infernal. You are a demon of [demonsin] released from hell to spread sin amongst the living.")) + to_chat(owner.current, span_warning("However, your infernal form is not without weaknesses.")) + to_chat(owner.current, "You are incredibly vulnerable to holy artifacts and influence.") + to_chat(owner.current, "While blessed with the unholy ability to transform into your true form, this form is extremely obvious and vulnerable to holy weapons.") + to_chat(owner.current, "[span_warning("Do your best to complete your objectives without unnessecary death, unless you are a wrathful demon.")]
") + owner.announce_objectives() + SEND_SOUND(owner.current, sound('sound/magic/ethereal_exit.ogg')) + .=..() + +/datum/antagonist/sinfuldemon/on_gain() + forge_objectives() + owner.special_role = "sinfuldemon" + owner.current.faction += "hell" + if(owner.assigned_role == "Clown" && ishuman(owner.current)) + var/mob/living/carbon/human/S = owner.current + to_chat(S, span_notice("Your infernal nature has allowed you to overcome your clownishness.")) + S.dna.remove_mutation(CLOWNMUT) + switch(demonsin) + if(SIN_GLUTTONY) + owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/shapeshift/demon/gluttony) + owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/forcewall/gluttony) + if(SIN_GREED) + owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/shapeshift/demon) + owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/summon_greedslots) + if(SIN_WRATH) + owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/shapeshift/demon/wrath) + owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/inflict_handler/ignite) + if(SIN_ENVY) + owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/shapeshift/demon) + owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/touch/envy) + if(SIN_PRIDE) + owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/shapeshift/demon) + owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/summon_mirror) + .=..() + +/datum/antagonist/sinfuldemon/on_removal() + owner.special_role = null + owner.current.faction -= "hell" + remove_spells() + to_chat(owner.current, span_userdanger("Your infernal link has been severed! You are no longer a demon!")) + .=..() + +/datum/antagonist/sinfuldemon/proc/remove_spells() + for(var/X in owner.spell_list) + var/obj/effect/proc_holder/spell/S = X + if(is_type_in_typecache(S, demon_spells)) + owner.RemoveSpell(S) + +/datum/antagonist/sinfuldemon/roundend_report() + var/list/parts = list() + parts += printplayer(owner) + parts += printobjectives(objectives) + return parts.Join("
") + +#undef SIN_ENVY +#undef SIN_GLUTTONY +#undef SIN_GREED +#undef SIN_PRIDE +#undef SIN_SLOTH +#undef SIN_WRATH diff --git a/code/modules/antagonists/demon/general_powers.dm b/code/modules/antagonists/demon/general_powers.dm new file mode 100644 index 000000000000..78702ac67410 --- /dev/null +++ b/code/modules/antagonists/demon/general_powers.dm @@ -0,0 +1,68 @@ +/obj/effect/proc_holder/spell/targeted/shapeshift/demon //emergency get out of jail card. + name = "Lesser Demon Form" + desc = "Take on your true demon form. This form is strong but very obvious, and especially weak to holy influence. \ + Also, note that damage taken in this form can transform into your normal body. Heal by attacking living creatures before transforming back if gravely wounded!" + invocation = "COWER, MORTALS!!" + shapeshift_type = /mob/living/simple_animal/lesserdemon + action_icon = 'icons/mob/actions/actions_minor_antag.dmi' + action_icon_state = "daemontransform" + action_background_icon_state = "bg_demon" + +/mob/living/simple_animal/lesserdemon + name = "demon" + real_name = "demon" + desc = "A large, menacing creature covered in armored red scales." + speak_emote = list("cackles") + emote_hear = list("cackles","screeches") + response_help = "thinks better of touching" + response_disarm = "flails at" + response_harm = "punches" + icon = 'icons/mob/mob.dmi' + icon_state = "lesserdaemon" + icon_living = "lesserdaemon" + mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + speed = 0.33 + a_intent = INTENT_HARM + stop_automated_movement = 1 + status_flags = CANPUSH + attack_sound = 'sound/magic/demon_attack1.ogg' + deathsound = 'sound/magic/demon_dies.ogg' + deathmessage = "wails in anger and fear as it collapses in defeat!" + 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 = 250 //Weak to cold + maxbodytemp = INFINITY + faction = list("hell") + attacktext = "wildly tears into" + maxHealth = 200 + health = 200 + environment_smash = ENVIRONMENT_SMASH_STRUCTURES + obj_damage = 40 + melee_damage_lower = 24 + melee_damage_upper = 24 + wound_bonus = -15 + see_in_dark = 8 + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + loot = (/obj/effect/decal/cleanable/blood) + del_on_death = 1 + +/mob/living/simple_animal/lesserdemon/attackby(obj/item/W, mob/living/user, params) + . = ..() + if(istype(W, /obj/item/nullrod)) + visible_message(span_warning("[src] screams in unholy pain from the blow!"), \ + span_cult("As \the [W] hits you, you feel holy power blast through your form, tearing it apart!")) + adjustBruteLoss(22) //22 extra damage from the nullrod while in your true form. On average this means 40 damage is taken now. + +/mob/living/simple_animal/lesserdemon/UnarmedAttack(mob/living/L, proximity)//10 hp healed from landing a hit. + if(isliving(L)) + if(L.stat != DEAD && !L.anti_magic_check(TRUE, TRUE)) //demons do not gain succor from the dead or holy + adjustHealth(-maxHealth * 0.05) + return ..() + +/mob/living/simple_animal/lesserdemon/Life() + . = ..() + if(!src) + return + if(istype(get_area(src.loc), /area/chapel)) //being a non-carbon will not save you! + if(src.stat != DEAD) //being dead, however, will save you + src.visible_message(span_warning("[src] begins to melt apart!"), span_danger("Your very soul melts from the holy room!"), "You hear sizzling.") + adjustHealth(20) //20 damage every ~2 seconds. About 20 seconds for a full HP demon to melt apart in the chapel. diff --git a/code/modules/antagonists/demon/objectives.dm b/code/modules/antagonists/demon/objectives.dm new file mode 100644 index 000000000000..3540bbfe3842 --- /dev/null +++ b/code/modules/antagonists/demon/objectives.dm @@ -0,0 +1,17 @@ +/datum/objective/demon + completed = TRUE + +/datum/objective/demon/gluttony + explanation_text = "Devour as much food as possible." + +/datum/objective/demon/greed + explanation_text = "Acquire as much wealth as possible." + +/datum/objective/demon/wrath + explanation_text = "Inflict as much pain as possible." + +/datum/objective/demon/envy + explanation_text = "Do not allow anyone to become more popular than you." + +/datum/objective/demon/pride + explanation_text = "Become as popular, powerful, and influential to as many people possible." diff --git a/code/modules/antagonists/demon/sins/envy.dm b/code/modules/antagonists/demon/sins/envy.dm new file mode 100644 index 000000000000..66cfbdc7a46e --- /dev/null +++ b/code/modules/antagonists/demon/sins/envy.dm @@ -0,0 +1,40 @@ +/obj/effect/proc_holder/spell/targeted/touch/envy + name = "Vanity Steal" + desc = "Engulfs your arm in a jealous might, allowing you to steal the look of the first human-like struck with it. Note, the form change is not reversible." + hand_path = /obj/item/melee/touch_attack/envy + school = "evocation" + charge_max = 150 + clothes_req = FALSE + invocation = "ETERNAL FLAMES" + invocation_type = "whisper" + action_icon = 'icons/mob/actions/actions_changeling.dmi' + action_icon_state = "transform" + action_background_icon_state = "bg_demon" + +/obj/item/melee/touch_attack/envy + name = "Envious Hand" + desc = "A writhing, burning aura of jealousy, ready to be unleashed." + icon_state = "flagellation" + item_state = "hivemind" + catchphrase = "I'M BETTER THAN YOU!!" + +/obj/item/melee/touch_attack/envy/afterattack(atom/target, mob/living/carbon/human/user, proximity_flag, click_parameters) + if(!proximity_flag) + return + var/mob/living/M = target + if(M.anti_magic_check()) + to_chat(user, span_warning("[M] resists your unholy jealousy!")) + to_chat(M, span_warning("A creeping feeling of jealousy dances around your mind before being suddenly dispelled.")) + ..() + return + playsound(user, 'sound/magic/demon_attack1.ogg', 75, TRUE) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(user.real_name != H.dna.real_name) + user.real_name = H.dna.real_name + H.dna.transfer_identity(user, transfer_SE=1) + user.updateappearance(mutcolor_update=1) + user.domutcheck() + user.visible_message(span_warning("[user]'s appearance shifts into [H]'s!"), \ + span_boldannounce("[H.p_they(TRUE)] think[H.p_s()] [H.p_theyre()] sooo much better than you. Not anymore, [H.p_they()] won't.")) + return ..() diff --git a/code/modules/antagonists/demon/sins/gluttony.dm b/code/modules/antagonists/demon/sins/gluttony.dm new file mode 100644 index 000000000000..7720b8f9ac48 --- /dev/null +++ b/code/modules/antagonists/demon/sins/gluttony.dm @@ -0,0 +1,56 @@ +/obj/effect/proc_holder/spell/targeted/forcewall/gluttony + name = "Gluttonous Wall" + desc = "Create a magical barrier that only allows fat people to pass through." + school = "transmutation" + charge_max = 150 + clothes_req = FALSE + invocation = "INDULGE" + invocation_type = "shout" + sound = 'sound/magic/forcewall.ogg' + action_icon = 'icons/mob/actions/actions_minor_antag.dmi' + action_icon_state = "blob" + action_background_icon_state = "bg_demon" + range = -1 + include_user = TRUE + cooldown_min = 50 //12 deciseconds reduction per rank + wall_type = /obj/effect/gluttony/timed + +/obj/effect/proc_holder/spell/targeted/shapeshift/demon/gluttony //emergency get out of jail card, but better. It also eats everything. + name = "Gluttony Demon Form" + desc = "Take on your true demon form. This form is strong but very obvious and especially weak to holy influence. \ + Also, note that damage taken in this form can transform into your normal body. Heal by attacking living creatures before transforming back if gravely wounded! \ + Your unique form as a demon of gluttony also allows you to eat corpses to heal yourself." + shapeshift_type = /mob/living/simple_animal/lesserdemon/gluttony + +/mob/living/simple_animal/lesserdemon/gluttony //capable of devouring corpses for health + name = "gluttonous demon" + real_name = "gluttonous demon" + icon_state = "lesserdaemon_gluttony" + icon_living = "lesserdaemon_gluttony" + +/mob/living/simple_animal/lesserdemon/gluttony/UnarmedAttack(mob/living/L) + if(isliving(L)) //Eat Corpses to regen health + if(L.stat == DEAD) + if(do_after(src, 3 SECONDS, target = L)) + devour(L) + return + return ..() + +/mob/living/simple_animal/lesserdemon/gluttony/proc/devour(mob/living/L) + if(!L) + return FALSE + visible_message( + span_danger("[src] devours [L]!"), + span_userdanger("You feast on [L], restoring your health!")) + adjustBruteLoss(-50) + L.gib() + return TRUE + +/obj/effect/gluttony/timed + ///Time in deciseconds before it deletes itself. + var/timeleft = 150 + +/obj/effect/gluttony/timed/Initialize() + . = ..() + if(timeleft) + QDEL_IN(src, timeleft) diff --git a/code/modules/antagonists/demon/sins/greed.dm b/code/modules/antagonists/demon/sins/greed.dm new file mode 100644 index 000000000000..248f88b7119d --- /dev/null +++ b/code/modules/antagonists/demon/sins/greed.dm @@ -0,0 +1,17 @@ +/obj/effect/proc_holder/spell/aoe_turf/conjure/summon_greedslots + name = "Summon Slotmachine" + desc = "Summon forth a temporary slot machine of greed, allowing you to offer patrons a deadly game where the price is their life (and some money if you'd like) and the possible prize is a one use die of fate." + invocation = "Just one game?" + invocation_type = "whisper" + clothes_req = FALSE + charge_max = 600 + cooldown_min = 200 + summon_type = list(/obj/structure/cursed_slot_machine/betterchance) + summon_lifespan = 600 + summon_amt = 1 + range = 1 + action_icon = 'icons/mob/actions/actions_minor_antag.dmi' + action_icon_state = "slots" + action_background_icon_state = "bg_demon" + + diff --git a/code/modules/antagonists/demon/sins/pride.dm b/code/modules/antagonists/demon/sins/pride.dm new file mode 100644 index 000000000000..1bde7d4bb18a --- /dev/null +++ b/code/modules/antagonists/demon/sins/pride.dm @@ -0,0 +1,17 @@ +/obj/effect/proc_holder/spell/aoe_turf/conjure/summon_mirror + name = "Summon Mirror" + desc = "Summon forth a temporary mirror of sin that will allow you and others to change anything they want about themselves." + invocation = "Aren't I so amazing?" + invocation_type = "whisper" + clothes_req = FALSE + charge_max = 600 + cooldown_min = 200 + summon_type = list(/obj/structure/mirror/magic/lesser) + summon_lifespan = 60 SECONDS + range = 1 + action_icon = 'icons/mob/actions/actions_minor_antag.dmi' + action_icon_state = "magic_mirror" + action_background_icon_state = "bg_demon" + + + diff --git a/code/modules/antagonists/demon/sins/wrath.dm b/code/modules/antagonists/demon/sins/wrath.dm new file mode 100644 index 000000000000..48974d3d3937 --- /dev/null +++ b/code/modules/antagonists/demon/sins/wrath.dm @@ -0,0 +1,41 @@ +/obj/effect/proc_holder/spell/targeted/shapeshift/demon/wrath //emergency get out of jail card, but better. + name = "Wrath Demon Form" + shapeshift_type = /mob/living/simple_animal/lesserdemon/wrath + +/mob/living/simple_animal/lesserdemon/wrath //slightly more damage. + name = "wrathful demon" + real_name = "wrathful demon" + melee_damage_lower = 28 + melee_damage_upper = 28 + icon_state = "lesserdaemon_wrath" + icon_living = "lesserdaemon_wrath" + +/obj/effect/proc_holder/spell/pointed/trigger/ignite + name = "Ignite" + desc = "This ranged spell sets a person on fire." + school = "transmutation" + charge_max = 600 + clothes_req = FALSE + invocation = "BURN IN HELL!!" + invocation_type = "shout" + message = span_notice("You ignite in a flash of hellfire!") + cooldown_min = 75 + ranged_mousepointer = 'icons/effects/mouse_pointers/throw_target.dmi' + action_icon = 'icons/mob/actions/humble/actions_humble.dmi' + action_icon_state = "sacredflame" + active_msg = "You prepare to ignite a target..." + +/obj/effect/proc_holder/spell/targeted/inflict_handler/ignite + name = "Ignite" + desc = "This spell sets a person on fire from range." + school = "transmutation" + invocation = "BURN IN HELL!!" + invocation_type = "shout" + charge_max = 600 + clothes_req = FALSE + action_icon = 'icons/mob/actions/humble/actions_humble.dmi' + action_icon_state = "sacredflame" + amt_firestacks = 5 + ignites = TRUE + sound = 'sound/magic/fireball.ogg' + diff --git a/code/modules/events/sinfuldemon.dm b/code/modules/events/sinfuldemon.dm new file mode 100644 index 000000000000..dd1c8c3515fb --- /dev/null +++ b/code/modules/events/sinfuldemon.dm @@ -0,0 +1,61 @@ +/datum/round_event_control/sinfuldemon + name = "Create Demon of Sin" + typepath = /datum/round_event/ghost_role/sinfuldemon + max_occurrences = 2 //misery loves company + min_players = 15 + earliest_start = 20 MINUTES + +/datum/round_event/ghost_role/sinfuldemon + var/success_spawn = 0 + minimum_required = 1 + role_name = "demon of sin" + fakeable = FALSE + +/datum/round_event/ghost_role/sinfuldemon/kill() + if(!success_spawn && control) + control.occurrences-- + return ..() + +/datum/round_event/ghost_role/sinfuldemon/spawn_role() + //selecting a spawn_loc + if(!SSjob.latejoin_trackers.len) + return MAP_ERROR + + //selecting a candidate player + var/list/candidates = get_candidates(ROLE_SINFULDEMON, null, ROLE_SINFULDEMON) + if(!candidates.len) + return NOT_ENOUGH_PLAYERS + + var/mob/dead/selected_candidate = pick_n_take(candidates) + var/key = selected_candidate.key + + var/datum/mind/Mind = create_sinfuldemon_mind(key) + Mind.active = TRUE + + var/mob/living/carbon/human/sinfuldemon = create_event_sinfuldemon() + Mind.transfer_to(sinfuldemon) + Mind.add_antag_datum(/datum/antagonist/sinfuldemon) + + spawned_mobs += sinfuldemon + message_admins("[ADMIN_LOOKUPFLW(sinfuldemon)] has been made into a demon of sin by an event.") + log_game("[key_name(sinfuldemon)] was spawned as a demon of sin by an event.") + var/datum/job/jobdatum = SSjob.GetJob("Assistant") + sinfuldemon.job = jobdatum.title + jobdatum.equip(sinfuldemon) + return SUCCESSFUL_SPAWN + + +/proc/create_event_sinfuldemon(spawn_loc) + var/mob/living/carbon/human/new_sinfuldemon = new(spawn_loc) + if(!spawn_loc) + SSjob.SendToLateJoin(new_sinfuldemon) + var/datum/preferences/A = new() //Randomize appearance for the demon. + A.copy_to(new_sinfuldemon) + new_sinfuldemon.dna.update_dna_identity() + return new_sinfuldemon + +/proc/create_sinfuldemon_mind(key) + var/datum/mind/Mind = new /datum/mind(key) + Mind.assigned_role = ROLE_SINFULDEMON + Mind.special_role = ROLE_SINFULDEMON + return Mind diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 02771207decf..e21a9523c3ea 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -268,6 +268,23 @@ 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? // Yogs End + if(ishuman(M) && is_sinfuldemon(M) && prob(80)) + switch(data) + if(1 to 4) + to_chat(M, span_warning("Your unholy blood begins to burn as holy power creeps through you.")) + M.adjustFireLoss(1) + if(5 to 10) + to_chat(M, span_danger("The burning deepens and strengthens!")) + M.adjustFireLoss(2) + if(11 to 12) + to_chat(M, span_danger("Your flesh itself begins to melt apart in agony!")) + M.adjustFireLoss(3) + M.emote("scream") + if(13 to INFINITY) + M.visible_message("[M] suddenly ignites in a brilliant flash of white!", span_userdanger("You suddenly ignite in a holy fire!")) + M.adjust_fire_stacks(3) + M.IgniteMob() + M.adjustFireLoss(4) holder.remove_reagent(type, 0.4) //fixed consumption to prevent balancing going out of whack /datum/reagent/water/holywater/reaction_turf(turf/T, reac_volume) @@ -936,6 +953,8 @@ /datum/reagent/silver/reaction_mob(mob/living/M, method=TOUCH, reac_volume) if(M.has_bane(BANE_SILVER)) M.reagents.add_reagent(/datum/reagent/toxin, reac_volume) + if(ishuman(M) && is_sinfuldemon(M) && prob(80)) //sinful demons have a lesser reaction to silver + M.reagents.add_reagent(/datum/reagent/toxin, reac_volume) ..() /datum/reagent/uranium diff --git a/code/modules/ruins/objects_and_mobs/sin_ruins.dm b/code/modules/ruins/objects_and_mobs/sin_ruins.dm index 63234595ced1..b4d8834df172 100644 --- a/code/modules/ruins/objects_and_mobs/sin_ruins.dm +++ b/code/modules/ruins/objects_and_mobs/sin_ruins.dm @@ -14,6 +14,9 @@ return if(obj_flags & IN_USE) return + if(is_sinfuldemon(user)) //this is probably a snowflake way of doing it but sure. Demons of Greed don't need to farm this. + to_chat(user,"Reserve this foolish game for mortals.") + return obj_flags |= IN_USE user.health -= 20 user.maxHealth -= 20 @@ -41,6 +44,8 @@ if(user) to_chat(user, span_boldwarning("Fucking machine! Must be rigged. Still... one more try couldn't hurt, right?")) +/obj/structure/cursed_slot_machine/betterchance //doubled chance of winnning. + win_prob = 10 /obj/structure/cursed_money name = "bag of money" diff --git a/code/modules/spells/spell_types/inflict_handler.dm b/code/modules/spells/spell_types/inflict_handler.dm index 2ad9a5ed169b..f590d3b72a07 100644 --- a/code/modules/spells/spell_types/inflict_handler.dm +++ b/code/modules/spells/spell_types/inflict_handler.dm @@ -1,6 +1,6 @@ /obj/effect/proc_holder/spell/targeted/inflict_handler name = "Inflict Handler" - desc = "This spell blinds and/or destroys/damages/heals and/or knockdowns/stuns the target." + desc = "This spell blinds and/or destroys/damages/heals/ignites and/or knockdowns/stuns the target." var/amt_paralyze = 0 var/amt_unconscious = 0 @@ -18,6 +18,9 @@ var/amt_eye_blind = 0 var/amt_eye_blurry = 0 + var/amt_firestacks = 0 + var/ignites = FALSE + var/destroys = "none" //can be "none", "gib" or "disintegrate" var/summon_type = null //this will put an obj at the target's location @@ -50,6 +53,7 @@ target.blind_eyes(amt_eye_blind) target.blur_eyes(amt_eye_blurry) + target.adjust_fire_stacks(amt_firestacks) //summoning if(summon_type) new summon_type(target.loc, target) @@ -58,3 +62,6 @@ var/list/stat_args = status_params.Copy() stat_args.Insert(1,inflict_status) target.apply_status_effect(arglist(stat_args)) + + if(ignites) + target.IgniteMob() diff --git a/icons/mob/actions/actions_minor_antag.dmi b/icons/mob/actions/actions_minor_antag.dmi index 3b9fe54577e6..9e4da8f6524b 100644 Binary files a/icons/mob/actions/actions_minor_antag.dmi and b/icons/mob/actions/actions_minor_antag.dmi differ diff --git a/icons/mob/actions/actions_spells.dmi b/icons/mob/actions/actions_spells.dmi index ca84f29d4a2e..82ba375a4fe8 100644 Binary files a/icons/mob/actions/actions_spells.dmi and b/icons/mob/actions/actions_spells.dmi differ diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index b8792a8eab26..ba2ee1ee3df7 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index 1e2fa42d973e..3f1756ca8c37 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/yogstation.dme b/yogstation.dme index 863334705385..efc99a907b20 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -1513,6 +1513,14 @@ #include "code\modules\antagonists\cult\ritual.dm" #include "code\modules\antagonists\cult\rune_spawn_action.dm" #include "code\modules\antagonists\cult\runes.dm" +#include "code\modules\antagonists\demon\demons.dm" +#include "code\modules\antagonists\demon\general_powers.dm" +#include "code\modules\antagonists\demon\objectives.dm" +#include "code\modules\antagonists\demon\sins\envy.dm" +#include "code\modules\antagonists\demon\sins\gluttony.dm" +#include "code\modules\antagonists\demon\sins\greed.dm" +#include "code\modules\antagonists\demon\sins\pride.dm" +#include "code\modules\antagonists\demon\sins\wrath.dm" #include "code\modules\antagonists\devil\devil.dm" #include "code\modules\antagonists\devil\devil_helpers.dm" #include "code\modules\antagonists\devil\imp\imp.dm" @@ -1913,6 +1921,7 @@ #include "code\modules\events\sentience.dm" #include "code\modules\events\shuttle_catastrophe.dm" #include "code\modules\events\shuttle_loan.dm" +#include "code\modules\events\sinfuldemon.dm" #include "code\modules\events\space_dragon.dm" #include "code\modules\events\spacevine.dm" #include "code\modules\events\spider_infestation.dm"