diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 50bce2a1f48..0d823aa07a8 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1197,7 +1197,9 @@ ticker.mode.devils += src special_role = "devil" ticker.mode.finalize_devil(src) + ticker.mode.add_devil_objectives(src, 2) announceDevilLaws() + announce_objectives() if("sintouched") if(ishuman(current)) ticker.mode.sintouched += src diff --git a/code/game/gamemodes/devil/devil agent/devil_agent.dm b/code/game/gamemodes/devil/devil agent/devil_agent.dm new file mode 100644 index 00000000000..dfdb957153a --- /dev/null +++ b/code/game/gamemodes/devil/devil agent/devil_agent.dm @@ -0,0 +1,43 @@ +/datum/game_mode/devil/devil_agents + name = "Devil Agents" + config_tag = "devil_agents" + required_players = 25 + required_enemies = 3 + recommended_enemies = 8 + reroll_friendly = 0 + + traitors_possible = 10 //hard limit on traitors if scaling is turned off + num_modifier = 4 + objective_count = 2 + + var/list/target_list = list() + var/list/late_joining_list = list() + minimum_devils = 3 + + announce_text = "There are devil agents onboard the station, trying to outbid each other!\n\ + + Devils: Purchase souls and interfere with your rivals!\n\ + + Crew: Resist the lure of sin and remain pure!" + +/datum/game_mode/devil/devil_agents/post_setup() + var/i = 0 + for(var/datum/mind/devil in devils) + i++ + if(i + 1 > devils.len) + i = 0 + target_list[devil] = devils[i + 1] + ..() + +/datum/game_mode/devil/devil_agents/add_devil_objectives(datum/mind/devil_mind, quantity) + ..(devil_mind, quantity - give_outsell_objective(devil_mind)) + +/datum/game_mode/devil/devil_agents/proc/give_outsell_objective(datum/mind/devil) + //If you override this method, have it return the number of objectives added. + if(target_list.len && target_list[devil]) // Is a double agent + var/datum/mind/target_mind = target_list[devil] + var/datum/objective/devil/outsell/outsellobjective = new + outsellobjective.owner = devil + outsellobjective.target = target_mind + outsellobjective.update_explanation_text() + devil.objectives += outsellobjective + return 1 + return 0 diff --git a/code/game/gamemodes/devil/devil_game_mode.dm b/code/game/gamemodes/devil/devil_game_mode.dm index 97411e87e66..c64653a986b 100644 --- a/code/game/gamemodes/devil/devil_game_mode.dm +++ b/code/game/gamemodes/devil/devil_game_mode.dm @@ -1,111 +1,61 @@ -/datum/game_mode - var/list/datum/mind/sintouched = list() - var/list/datum/mind/devils = list() - var/devil_ascended = 0 // Number of arch devils on station - -/datum/game_mode/proc/auto_declare_completion_sintouched() - var/text = "" - if(sintouched.len) - text += "
The sintouched were:" - var/list/sintouchedUnique = uniqueList(sintouched) - for(var/S in sintouchedUnique) - var/datum/mind/sintouched_mind = S - text += printplayer(sintouched_mind) - text += printobjectives(sintouched_mind) - text += "
" - text += "
" - world << text - -/datum/game_mode/proc/auto_declare_completion_devils() - /var/text = "" - if(devils.len) - text += "
The devils were:" - for(var/D in devils) - var/datum/mind/devil = D - text += printplayer(devil) - text += printdevilinfo(devil) - text += printobjectives(devil) - text += "
" - world << text - /datum/game_mode/devil + name = "devil" + config_tag = "devil" + antag_flag = ROLE_DEVIL + protected_jobs = list("Lawyer", "Librarian", "Chaplain", "Head of Security", "Captain", "AI") + required_players = 0 + required_enemies = 1 + recommended_enemies = 4 + reroll_friendly = 1 + enemy_minimum_age = 0 + + var/traitors_possible = 4 //hard limit on devils if scaling is turned off + var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual. + var/objective_count = 2 + var/minimum_devils = 1 + + announce_text = "There are devils onboard the station!\n\ + + Devils: Purchase souls and tempt the crew to sin!\n\ + + Crew: Resist the lure of sin and remain pure!" + +/datum/game_mode/devil/pre_setup() + + if(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + if(config.protect_assistant_from_antagonist) + restricted_jobs += "Assistant" + + var/num_devils = 1 + + if(config.traitor_scaling_coeff) + num_devils = max(minimum_devils, min( round(num_players()/(config.traitor_scaling_coeff*3))+ 2 + num_modifier, round(num_players()/(config.traitor_scaling_coeff*1.5)) + num_modifier )) + else + num_devils = max(minimum_devils, min(num_players(), traitors_possible)) + + for(var/j = 0, j < num_devils, j++) + if (!antag_candidates.len) + break + var/datum/mind/devil = pick(antag_candidates) + devils += devil + devil.special_role = traitor_name + devil.restricted_roles = restricted_jobs + + log_game("[devil.key] (ckey) has been selected as a [traitor_name]") + antag_candidates.Remove(devil) + + if(devils.len < required_enemies) + return 0 + return 1 -/datum/game_mode/proc/finalize_devil(datum/mind/devil_mind) - var/mob/living/carbon/human/S = devil_mind.current - var/trueName= randomDevilName() - var/datum/objective/devil/soulquantity/soulquant = new - soulquant.owner = devil_mind - var/datum/objective/devil/obj_2 = pick(new /datum/objective/devil/soulquality(null), new /datum/objective/devil/sintouch(null)) - obj_2.owner = devil_mind - devil_mind.objectives += obj_2 - devil_mind.objectives += soulquant - devil_mind.devilinfo = devilInfo(trueName, 1) - devil_mind.store_memory("Your devilic true name is [devil_mind.devilinfo.truename]
[lawlorify[LAW][devil_mind.devilinfo.ban]]
You may not use violence to coerce someone into selling their soul.
You may not directly and knowingly physically harm a devil, other than yourself.
[lawlorify[LAW][devil_mind.devilinfo.bane]]
[lawlorify[LAW][devil_mind.devilinfo.obligation]]
[lawlorify[LAW][devil_mind.devilinfo.banish]]
") - devil_mind.devilinfo.owner = devil_mind - devil_mind.devilinfo.give_base_spells(1) - spawn(10) - devil_mind.devilinfo.update_hud() - if(devil_mind.assigned_role == "Clown") - S << "Your infernal nature has allowed you to overcome your clownishness." - S.dna.remove_mutation(CLOWNMUT) - -/datum/mind/proc/announceDevilLaws() - if(!devilinfo) - return - current << "You remember your link to the infernal. You are [src.devilinfo.truename], an agent of hell, a devil. And you were sent to the plane of creation for a reason. A greater purpose. Convince the crew to sin, and embroiden Hell's grasp." - current << "However, your infernal form is not without weaknesses." - current << "You may not use violence to coerce someone into selling their soul." - current << "You may not directly and knowingly physically harm a devil, other than yourself." - current << lawlorify[LAW][src.devilinfo.bane] - current << lawlorify[LAW][src.devilinfo.ban] - current << lawlorify[LAW][src.devilinfo.obligation] - current << lawlorify[LAW][src.devilinfo.banish] - current << "

Remember, the crew can research your weaknesses if they find out your devil name.
" - var/obj_count = 1 - current << "Your current objectives:" - for(var/O in objectives) - var/datum/objective/objective = O - current << "Objective #[obj_count]: [objective.explanation_text]" - obj_count++ - -/datum/game_mode/proc/printdevilinfo(datum/mind/ply) - if(!ply.devilinfo) - return "" - var/text = "
The devil's true name is: [ply.devilinfo.truename]
" - text += "The devil's bans were:
" - text += " [lawlorify[LORE][ply.devilinfo.ban]]
" - text += " [lawlorify[LORE][ply.devilinfo.bane]]
" - text += " [lawlorify[LORE][ply.devilinfo.obligation]]
" - text += " [lawlorify[LORE][ply.devilinfo.banish]]
" - return text - -/datum/game_mode/proc/update_devil_icons_added(datum/mind/devil_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_DEVIL] - hud.join_hud(devil_mind.current) - set_antag_hud(devil_mind.current, "devil") - -/datum/game_mode/proc/update_devil_icons_removed(datum/mind/devil_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_DEVIL] - hud.leave_hud(devil_mind.current) - set_antag_hud(devil_mind.current, null) - -/datum/game_mode/proc/update_sintouch_icons_added(datum/mind/sin_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SINTOUCHED] - hud.join_hud(sin_mind.current) - set_antag_hud(sin_mind.current, "sintouched") - -/datum/game_mode/proc/update_sintouch_icons_removed(datum/mind/sin_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SINTOUCHED] - hud.leave_hud(sin_mind.current) - set_antag_hud(sin_mind.current, null) - -/datum/game_mode/proc/update_soulless_icons_added(datum/mind/soulless_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SOULLESS] - hud.join_hud(soulless_mind.current) - set_antag_hud(soulless_mind.current, "soulless") - -/datum/game_mode/proc/update_soulless_icons_removed(datum/mind/soulless_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SOULLESS] - hud.leave_hud(soulless_mind.current) - set_antag_hud(soulless_mind.current, null) +/datum/game_mode/devil/post_setup() + for(var/datum/mind/devil in devils) + spawn(rand(10,100)) + finalize_devil(devil, objective_count) + spawn(100) + add_devil_objectives(devil, objective_count) //This has to be in a separate loop, as we need devil names to be generated before we give objectives in devil agent. + devil.announceDevilLaws() + devil.announce_objectives() + modePlayer += devils + ..() + return 1 diff --git a/code/game/gamemodes/devil/devilinfo.dm b/code/game/gamemodes/devil/devilinfo.dm index 75d5c0ca724..0b9b4b59213 100644 --- a/code/game/gamemodes/devil/devilinfo.dm +++ b/code/game/gamemodes/devil/devilinfo.dm @@ -7,6 +7,8 @@ #define TRUE_DEVIL 2 #define ARCH_DEVIL 3 +#define LOSS_PER_DEATH 2 + #define SOULVALUE soulsOwned.len-reviveNumber #define DEVILRESURRECTTIME 600 @@ -162,16 +164,16 @@ var/global/list/lawlorify = list ( update_hud() /datum/devilinfo/proc/check_regression() - if (form == ARCH_DEVIL) + if(form == ARCH_DEVIL) return //arch devil can't regress - switch(SOULVALUE) - if(-1) - remove_spells() - owner.current << "As punishment for your failures, all of your powers except contract creation have been revoked." - if(BLOOD_THRESHOLD-1) - regress_humanoid() - if(TRUE_THRESHOLD-1) - regress_blood_lizard() + //Yes, fallthrough behavior is intended, so I can't use a switch statement. + if(form == TRUE_DEVIL && SOULVALUE < TRUE_THRESHOLD) + regress_blood_lizard() + if(form == BLOOD_LIZARD && SOULVALUE < BLOOD_THRESHOLD) + regress_humanoid() + if(SOULVALUE < 0) + remove_spells() + owner.current << "As punishment for your failures, all of your powers except contract creation have been revoked." /datum/devilinfo/proc/increase_form() switch(form) @@ -386,7 +388,7 @@ var/global/list/lawlorify = list ( /datum/devilinfo/proc/hellish_resurrection(mob/living/body) message_admins("[owner.name] (true name is: [truename]) is resurrecting using hellish energy.") if(SOULVALUE <= ARCH_THRESHOLD) // once ascended, arch devils do not go down in power by any means. - reviveNumber++ + reviveNumber += LOSS_PER_DEATH update_hud() if(body) body.revive(1,0) diff --git a/code/game/gamemodes/devil/game_mode.dm b/code/game/gamemodes/devil/game_mode.dm new file mode 100644 index 00000000000..5f0846ac1e4 --- /dev/null +++ b/code/game/gamemodes/devil/game_mode.dm @@ -0,0 +1,111 @@ +/datum/game_mode + var/list/datum/mind/sintouched = list() + var/list/datum/mind/devils = list() + var/devil_ascended = 0 // Number of arch devils on station + +/datum/game_mode/proc/auto_declare_completion_sintouched() + var/text = "" + if(sintouched.len) + text += "
The sintouched were:" + var/list/sintouchedUnique = uniqueList(sintouched) + for(var/S in sintouchedUnique) + var/datum/mind/sintouched_mind = S + text += printplayer(sintouched_mind) + text += printobjectives(sintouched_mind) + text += "
" + text += "
" + world << text + +/datum/game_mode/proc/auto_declare_completion_devils() + /var/text = "" + if(devils.len) + text += "
The devils were:" + for(var/D in devils) + var/datum/mind/devil = D + text += printplayer(devil) + text += printdevilinfo(devil) + text += printobjectives(devil) + text += "
" + text += "
" + world << text + + +/datum/game_mode/proc/finalize_devil(datum/mind/devil_mind) + var/mob/living/carbon/human/S = devil_mind.current + var/trueName= randomDevilName() + + devil_mind.devilinfo = devilInfo(trueName, 1) + devil_mind.store_memory("Your devilic true name is [devil_mind.devilinfo.truename]
[lawlorify[LAW][devil_mind.devilinfo.ban]]
You may not use violence to coerce someone into selling their soul.
You may not directly and knowingly physically harm a devil, other than yourself.
[lawlorify[LAW][devil_mind.devilinfo.bane]]
[lawlorify[LAW][devil_mind.devilinfo.obligation]]
[lawlorify[LAW][devil_mind.devilinfo.banish]]
") + devil_mind.devilinfo.owner = devil_mind + devil_mind.devilinfo.give_base_spells(1) + spawn(10) + devil_mind.devilinfo.update_hud() + if(devil_mind.assigned_role == "Clown") + S << "Your infernal nature has allowed you to overcome your clownishness." + S.dna.remove_mutation(CLOWNMUT) + +/datum/game_mode/proc/add_devil_objectives(datum/mind/devil_mind, quantity) + var/list/validtypes = list(/datum/objective/devil/soulquantity, /datum/objective/devil/soulquality, /datum/objective/devil/sintouch, /datum/objective/devil/buy_target) + for(var/i = 1 to quantity) + var/type = pick(validtypes) + var/datum/objective/devil/objective = new type(null) + objective.owner = devil_mind + devil_mind.objectives += objective + if(!istype(objective, /datum/objective/devil/buy_target)) + validtypes -= type //prevent duplicate objectives, EXCEPT for buy_target. + else + objective.find_target() + +/datum/mind/proc/announceDevilLaws() + if(!devilinfo) + return + current << "You remember your link to the infernal. You are [src.devilinfo.truename], an agent of hell, a devil. And you were sent to the plane of creation for a reason. A greater purpose. Convince the crew to sin, and embroiden Hell's grasp." + current << "However, your infernal form is not without weaknesses." + current << "You may not use violence to coerce someone into selling their soul." + current << "You may not directly and knowingly physically harm a devil, other than yourself." + current << lawlorify[LAW][src.devilinfo.bane] + current << lawlorify[LAW][src.devilinfo.ban] + current << lawlorify[LAW][src.devilinfo.obligation] + current << lawlorify[LAW][src.devilinfo.banish] + current << "

Remember, the crew can research your weaknesses if they find out your devil name.
" + +/datum/game_mode/proc/printdevilinfo(datum/mind/ply) + if(!ply.devilinfo) + return "Target is not a devil." + var/text = "
The devil's true name is: [ply.devilinfo.truename]
" + text += "The devil's bans were:
" + text += " [lawlorify[LORE][ply.devilinfo.ban]]
" + text += " [lawlorify[LORE][ply.devilinfo.bane]]
" + text += " [lawlorify[LORE][ply.devilinfo.obligation]]
" + text += " [lawlorify[LORE][ply.devilinfo.banish]]

" + return text + +/datum/game_mode/proc/update_devil_icons_added(datum/mind/devil_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_DEVIL] + hud.join_hud(devil_mind.current) + set_antag_hud(devil_mind.current, "devil") + +/datum/game_mode/proc/update_devil_icons_removed(datum/mind/devil_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_DEVIL] + hud.leave_hud(devil_mind.current) + set_antag_hud(devil_mind.current, null) + +/datum/game_mode/proc/update_sintouch_icons_added(datum/mind/sin_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SINTOUCHED] + hud.join_hud(sin_mind.current) + set_antag_hud(sin_mind.current, "sintouched") + +/datum/game_mode/proc/update_sintouch_icons_removed(datum/mind/sin_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SINTOUCHED] + hud.leave_hud(sin_mind.current) + set_antag_hud(sin_mind.current, null) + +/datum/game_mode/proc/update_soulless_icons_added(datum/mind/soulless_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SOULLESS] + hud.join_hud(soulless_mind.current) + set_antag_hud(soulless_mind.current, "soulless") + +/datum/game_mode/proc/update_soulless_icons_removed(datum/mind/soulless_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SOULLESS] + hud.leave_hud(soulless_mind.current) + set_antag_hud(soulless_mind.current, null) diff --git a/code/game/gamemodes/devil/objectives.dm b/code/game/gamemodes/devil/objectives.dm index 0a9d7083e92..bd4d3091273 100644 --- a/code/game/gamemodes/devil/objectives.dm +++ b/code/game/gamemodes/devil/objectives.dm @@ -3,29 +3,33 @@ /datum/objective/devil/soulquantity explanation_text = "You shouldn't see this text. Error:DEVIL1" - var/quantity = 4 + target_amount = 4 /datum/objective/devil/soulquantity/New() - quantity = pick(6,8) - explanation_text = "Purchase, and retain control over at least [quantity] souls." + target_amount = pick(6,7,8) + update_explanation_text() + +/datum/objective/devil/soulquantity/update_explanation_text() + explanation_text = "Purchase, and retain control over at least [target_amount] souls." /datum/objective/devil/soulquantity/check_completion() var/count = 0 for(var/S in owner.devilinfo.soulsOwned) var/datum/mind/L = S - if(L.soulOwner != L) + if(L.soulOwner == owner) count++ - return count >= quantity + return count >= target_amount + + /datum/objective/devil/soulquality explanation_text = "You shouldn't see this text. Error:DEVIL2" var/contractType - var/quantity + var/contractName /datum/objective/devil/soulquality/New() contractType = pick(CONTRACT_POWER, CONTRACT_WEALTH, CONTRACT_PRESTIGE, CONTRACT_MAGIC, CONTRACT_REVIVE, CONTRACT_KNOWLEDGE/*, CONTRACT_UNWILLING*/) - var/contractName - quantity = pick(1,2) + target_amount = pick(1,2) switch(contractType) if(CONTRACT_POWER) contractName = "for power" @@ -41,7 +45,10 @@ contractName = "for knowledge" //if(CONTRACT_UNWILLING) //Makes round unfun. // contractName = "against their will" - explanation_text = "Have mortals sign at least [quantity] contracts [contractName]" + update_explanation_text() + +/datum/objective/devil/soulquality/update_explanation_text() + explanation_text = "Have mortals sign at least [target_amount] contracts [contractName]" /datum/objective/devil/soulquality/check_completion() var/count = 0 @@ -49,14 +56,52 @@ var/datum/mind/L = S if(L.soulOwner != L && L.damnation_type == contractType) count++ - return count>=quantity + return count>=target_amount + + /datum/objective/devil/sintouch - var/quantity + explanation_text = "You shouldn't see this text. Error:DEVIL3" /datum/objective/devil/sintouch/New() - quantity = pick(4,5) - explanation_text = "Ensure at least [quantity] mortals are sintouched." + target_amount = pick(4,5) + explanation_text = "Ensure at least [target_amount] mortals are sintouched." /datum/objective/devil/sintouch/check_completion() - return quantity>=ticker.mode.sintouched.len \ No newline at end of file + return target_amount>=ticker.mode.sintouched.len + + + +/datum/objective/devil/buy_target + explanation_text = "You shouldn't see this text. Error:DEVIL4" + +/datum/objective/devil/buy_target/update_explanation_text() + if(target) + explanation_text = "Purchase and retain the soul of [target.name], the [target.assigned_role]." + else + explanation_text = "Free objective." + +/datum/objective/devil/buy_target/check_completion() + return target.soulOwner == owner + + +/datum/objective/devil/outsell + explanation_text = "You shouldn't see this text. Error:DEVIL5" + +/datum/objective/devil/outsell/New() + +/datum/objective/devil/outsell/update_explanation_text() + explanation_text = "Purchase and retain control over more souls than [target.devilinfo.truename], known to mortals as [target.name], the [target.assigned_role]." + +/datum/objective/devil/outsell/check_completion() + var/selfcount = 0 + for(var/S in owner.devilinfo.soulsOwned) + var/datum/mind/L = S + if(L.soulOwner == owner) + selfcount++ + var/targetcount = 0 + for(var/S in target.devilinfo.soulsOwned) + var/datum/mind/L = S + if(L.soulOwner == target) + targetcount++ + return selfcount > targetcount diff --git a/code/game/gamemodes/devil/true_devil/_true_devil.dm b/code/game/gamemodes/devil/true_devil/_true_devil.dm index 474024a4231..a99c95801d1 100644 --- a/code/game/gamemodes/devil/true_devil/_true_devil.dm +++ b/code/game/gamemodes/devil/true_devil/_true_devil.dm @@ -12,7 +12,7 @@ health = 350 maxHealth = 350 ventcrawler = 0 - density = 0 + density = 1 pass_flags = 0 var/ascended = 0 sight = (SEE_TURFS | SEE_OBJS) @@ -45,6 +45,7 @@ /mob/living/carbon/true_devil/Login() ..() mind.announceDevilLaws() + mind.announce_objectives() /mob/living/carbon/true_devil/death(gibbed) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 90e04375553..844fcd3a1c6 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -703,7 +703,7 @@ var/global/BSACooldown = 0 if(!ai_number) usr << "No AIs located" //Just so you know the thing is actually working and not just ignoring you. -/datum/admins/proc/output_devil_info() +/datum/admins/proc/output_all_devil_info() var/devil_number = 0 for(var/D in ticker.mode.devils) devil_number++ @@ -711,6 +711,12 @@ var/global/BSACooldown = 0 if(!devil_number) usr << "No Devils located" //Just so you know the thing is actually working and not just ignoring you. +/datum/admins/proc/output_devil_info(mob/living/M) + if(istype(M) && M.mind && M.mind.devilinfo) + usr << ticker.mode.printdevilinfo(M.mind) + else + usr << "[M] is not a devil." + /datum/admins/proc/manage_free_slots() if(!check_rights()) return diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 5526308de7b..618c5303b6f 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1621,7 +1621,8 @@ output_ai_laws() else if(href_list["admincheckdevilinfo"]) - output_devil_info() + var/mob/M = locate(href_list["admincheckdevilinfo"]) + output_devil_info(M) else if(href_list["adminmoreinfo"]) var/mob/M = locate(href_list["adminmoreinfo"]) diff --git a/code/modules/events/devil.dm b/code/modules/events/devil.dm index 21fad5037da..4f683a8f6f2 100644 --- a/code/modules/events/devil.dm +++ b/code/modules/events/devil.dm @@ -33,7 +33,9 @@ var/mob/living/carbon/human/devil = create_event_devil(spawn_loc) Mind.transfer_to(devil) ticker.mode.finalize_devil(Mind) + ticker.mode.add_devil_objectives(src, 2) Mind.announceDevilLaws() + Mind.announce_objectives() spawned_mobs += devil diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ab5600cfa12..eb4e7d9c45d 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1062,12 +1062,7 @@ O = new /datum/objective/sintouched/pride ticker.mode.sintouched += src.mind src.mind.objectives += O - var/obj_count = 1 - src << "Your current objectives:" - for(O in src.mind.objectives) - var/datum/objective/objective = O - src << "Objective #[obj_count]: [objective.explanation_text]" - obj_count++ + src.mind.announce_objectives() /mob/living/carbon/human/check_weakness(obj/item/weapon, mob/living/attacker) . = ..() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index be826e0fd91..a7036f009e5 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1036,7 +1036,10 @@ Sorry Giacom. Please don't be mad :( return 1 /mob/living/proc/return_soul() + hellbound = 0 if(mind) + if(mind.soulOwner.devilinfo)//Not sure how this could happen, but whatever. + mind.soulOwner.devilinfo.remove_soul(mind) mind.soulOwner = mind /mob/living/proc/has_bane(banetype) diff --git a/code/modules/paperwork/contract.dm b/code/modules/paperwork/contract.dm index 9974737affd..5817b793899 100644 --- a/code/modules/paperwork/contract.dm +++ b/code/modules/paperwork/contract.dm @@ -3,7 +3,7 @@ /obj/item/weapon/paper/contract throw_range = 3 throw_speed = 3 - var/signed = 0 + var/signed = FALSE var/datum/mind/target flags = NOBLUDGEON @@ -107,7 +107,7 @@ ..() /obj/item/weapon/paper/contract/infernal/update_text() - info = "This shouldn't be seen. Error DEVIL:5" + info = "This shouldn't be seen. Error DEVIL:6" /obj/item/weapon/paper/contract/infernal/power/update_text(var/signature = "____________") info = "
Contract for infernal power



I, [target] of sound mind, do hereby willingly offer my soul to the infernal hells by way of the infernal agent [owner.devilinfo.truename], in exchange for power and physical strength. I understand that upon my demise, my soul shall fall into the infernal hells, and my body may not be resurrected, cloned, or otherwise brought back to life. I also understand that this will prevent my brain from being used in an MMI.


Signed, [signature]" @@ -143,25 +143,28 @@ /obj/item/weapon/paper/contract/infernal/attack(mob/M, mob/living/user) add_fingerprint(user) - if(M == user && target == M.mind && M.mind.soulOwner == M.mind && attempt_signature(user)) + if(M == user && target == M.mind && M.mind.soulOwner != owner && attempt_signature(user)) user.visible_message("[user] slices their wrist with [src], and scrawls their name in blood.", "You slice your wrist open and scrawl your name in blood.") user.blood_volume = max(user.blood_volume - 10, 0) else return ..() /obj/item/weapon/paper/contract/infernal/proc/attempt_signature(mob/living/carbon/human/user) - if(user.IsAdvancedToolUser()) + if(user.IsAdvancedToolUser() && user.is_literate()) if(user.mind == target) - if(user.mind.soulOwner == user.mind) + if(user.mind.soulOwner != owner) if (contractType == CONTRACT_REVIVE) user << "You are already alive, this contract would do nothing." else - user << "You quickly scrawl your name on the contract" - if(FulfillContract()<=0) - user << "But it seemed to have no effect, perhaps even Hell itself cannot grant this boon?" - return 1 + if(signed) + user<< "This contract has already been signed. It may not be signed again." + else + user << "You quickly scrawl your name on the contract" + if(FulfillContract()<=0) + user << "But it seemed to have no effect, perhaps even Hell itself cannot grant this boon?" + return 1 else - user << "You are not in possession of your soul, you may not sell it." + user << "This devil already owns your soul, you may not sell it to them again." else user << "Your signature simply slides off the sheet, it seems this contract is not meant for you to sign." else @@ -196,6 +199,8 @@ /obj/item/weapon/paper/contract/infernal/proc/FulfillContract(mob/living/carbon/human/user = target.current) signed = 1 + if(user.mind.soulOwner != user.mind) //They already sold their soul to someone else? + user.mind.soulOwner.devilinfo.remove_soul(user.mind) //Then they lose their claim. user.mind.soulOwner = owner user.hellbound = contractType user.mind.damnation_type = contractType diff --git a/code/modules/spells/spell_types/devil.dm b/code/modules/spells/spell_types/devil.dm index 87e1d2fcd24..04792d84b6c 100644 --- a/code/modules/spells/spell_types/devil.dm +++ b/code/modules/spells/spell_types/devil.dm @@ -108,12 +108,17 @@ if(istype(user)) if(istype(user.loc, /obj/effect/dummy/slaughter/)) var/continuing = 0 - for(var/mob/living/C in orange(2, get_turf(user.loc))) - if (C.mind && C.mind.soulOwner == C.mind) - continuing = 1 - break + if(istype(get_area(user), /area/shuttle/)) // Can always phase in in a shuttle. + continuing = 1 + else + for(var/mob/living/C in orange(2, get_turf(user.loc))) //Can also phase in when nearby a potential buyer. + if (C.mind && C.mind.soulOwner == C.mind) + continuing = 1 + break if(continuing) - addtimer(user,"infernalphasein",150,TRUE) + user << "You are now phasing in." + if(do_mob(user,user,150)) + user.infernalphasein() else user << "You can only re-appear near a potential signer." revert_cast() @@ -122,21 +127,22 @@ user.notransform = 1 user.fakefire() src << "You begin to phase back into sinful flames." - addtimer(user, "infernalphaseout",150,TRUE,get_turf(user)) + if(do_mob(user,user,150)) + user.infernalphaseout() + else + user << "You must remain still while exiting." + user.ExtinguishMob() start_recharge() return revert_cast() -/mob/living/proc/infernalphaseout(var/turf/mobloc) - if(get_turf(src) != mobloc) - src << "You must remain still while exiting." - return +/mob/living/proc/infernalphaseout() dust_animation() spawn_dust() src.visible_message("[src] disappears in a flashfire!") playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1) - var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc) + var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,loc) src.ExtinguishMob() if(buckled) buckled.unbuckle_mob(src,force=1) diff --git a/config/game_options.txt b/config/game_options.txt index 696eb46c1f8..798460b4c1b 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -96,6 +96,8 @@ PROBABILITY RAGINMAGES 2 PROBABILITY MONKEY 0 PROBABILITY METEOR 0 PROBABILITY EXTENDED 0 +PROBABILITY DEVIL 0 +PROBABILITY DEVIL_AGENTS 0 ## You probably want to keep sandbox off by default for secret and random. PROBABILITY SANDBOX 0 diff --git a/tgstation.dme b/tgstation.dme index b9f4e975f30..dc0efcc497d 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -343,7 +343,9 @@ #include "code\game\gamemodes\devil\devil.dm" #include "code\game\gamemodes\devil\devil_game_mode.dm" #include "code\game\gamemodes\devil\devilinfo.dm" +#include "code\game\gamemodes\devil\game_mode.dm" #include "code\game\gamemodes\devil\objectives.dm" +#include "code\game\gamemodes\devil\devil agent\devil_agent.dm" #include "code\game\gamemodes\devil\imp\imp.dm" #include "code\game\gamemodes\devil\true_devil\_true_devil.dm" #include "code\game\gamemodes\devil\true_devil\inventory.dm"