mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
Changeling additions:
* Changelings now have a chance to roll a special team objective (only 1 at the moment) the chance is 20*number_of_lings * Changelings have no chance to roll a "backstab" (Ling vs Ling) objective if they have a team objective * Debrain objective has been removed (it still exists, but is not handed out) as it's basically broken * Engorged glands stats are now the default, engorged glands still functions as normal, adding 25 chem cap and doubling production * Armblades may now break open powered doors after a 10 second wait (With progress bar) * Changelings can now purchase Chameleon skin, which allows them to toggle on or off the genetics mutation "Chameleon skin" which slowly makes them invisible while stood still * Minor adjustments to mimic voice text to line up with changes to chem stats
This commit is contained in:
@@ -40,6 +40,8 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
|
||||
|
||||
var/const/changeling_amount = 4 //hard limit on changelings if scaling is turned off
|
||||
|
||||
var/changeling_team_objective_type = null //If this is not null, we hand our this objective to all lings
|
||||
|
||||
/datum/game_mode/changeling/announce()
|
||||
world << "<b>The current game mode is - Changeling!</b>"
|
||||
world << "<b>There are alien changelings on the station. Do not let the changelings succeed!</b>"
|
||||
@@ -72,6 +74,18 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
|
||||
return 0
|
||||
|
||||
/datum/game_mode/changeling/post_setup()
|
||||
|
||||
//Decide if it's ok for the lings to have a team objective
|
||||
//And then set it up to be handed out in forge_changeling_objectives
|
||||
var/list/team_objectives = typesof(/datum/objective/changeling_team_objective) - /datum/objective/changeling_team_objective
|
||||
var/list/possible_team_objectives = list()
|
||||
for(var/datum/objective/changeling_team_objective/T in team_objectives)
|
||||
if(changelings.len > initial(T.min_lings))
|
||||
possible_team_objectives += T
|
||||
|
||||
if(possible_team_objectives.len && prob(20*changelings.len))
|
||||
changeling_team_objective_type = pick(possible_team_objectives)
|
||||
|
||||
for(var/datum/mind/changeling in changelings)
|
||||
log_game("[changeling.key] (ckey) has been selected as a changeling")
|
||||
changeling.current.make_changeling()
|
||||
@@ -92,12 +106,11 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
|
||||
if(!(character.job in restricted_jobs))
|
||||
character.mind.make_Changling()
|
||||
|
||||
/datum/game_mode/proc/forge_changeling_objectives(datum/mind/changeling)
|
||||
/datum/game_mode/proc/forge_changeling_objectives(datum/mind/changeling, var/team_mode = 0)
|
||||
//OBJECTIVES - random traitor objectives. Unique objectives "steal brain" and "identity theft".
|
||||
//No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting
|
||||
//If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone
|
||||
|
||||
|
||||
var/datum/objective/absorb/absorb_objective = new
|
||||
absorb_objective.owner = changeling
|
||||
absorb_objective.gen_amount_goal(6, 8)
|
||||
@@ -108,12 +121,6 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
|
||||
steal_objective.owner = changeling
|
||||
steal_objective.find_target()
|
||||
changeling.objectives += steal_objective
|
||||
else
|
||||
var/datum/objective/debrain/debrain_objective = new
|
||||
debrain_objective.owner = changeling
|
||||
debrain_objective.find_target()
|
||||
changeling.objectives += debrain_objective
|
||||
|
||||
|
||||
var/list/active_ais = active_ais()
|
||||
if(active_ais.len && prob(100/joined_player_list.len))
|
||||
@@ -125,12 +132,18 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
|
||||
if(prob(70))
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
kill_objective.owner = changeling
|
||||
kill_objective.find_target()
|
||||
if(team_mode) //No backstabbing while in a team
|
||||
kill_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
|
||||
else
|
||||
kill_objective.find_target()
|
||||
changeling.objectives += kill_objective
|
||||
else
|
||||
var/datum/objective/maroon/maroon_objective = new
|
||||
maroon_objective.owner = changeling
|
||||
maroon_objective.find_target()
|
||||
if(team_mode)
|
||||
maroon_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
|
||||
else
|
||||
maroon_objective.find_target()
|
||||
changeling.objectives += maroon_objective
|
||||
|
||||
if (!(locate(/datum/objective/escape) in changeling.objectives))
|
||||
@@ -150,7 +163,17 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
|
||||
identity_theft.owner = changeling
|
||||
identity_theft.find_target()
|
||||
changeling.objectives += identity_theft
|
||||
return
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/changeling/forge_changeling_objectives(datum/mind/changeling)
|
||||
if(changeling_team_objective_type)
|
||||
var/datum/objective/changeling_team_objective/team_objective = new changeling_team_objective_type
|
||||
team_objective.owner = changeling
|
||||
changeling.objectives += team_objective
|
||||
|
||||
..(changeling,1)
|
||||
|
||||
|
||||
/datum/game_mode/proc/greet_changeling(datum/mind/changeling, you_are=1)
|
||||
if (you_are)
|
||||
@@ -237,8 +260,8 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
|
||||
var/dna_max = 4 //How many extra DNA strands the changeling can store for transformation.
|
||||
var/absorbedcount = 1 //We would require at least 1 sample of compatible DNA to have taken on the form of a human.
|
||||
var/chem_charges = 20
|
||||
var/chem_storage = 50
|
||||
var/chem_recharge_rate = 0.5
|
||||
var/chem_storage = 75
|
||||
var/chem_recharge_rate = 1
|
||||
var/chem_recharge_slowdown = 0
|
||||
var/sting_range = 2
|
||||
var/changelingID = "Changeling"
|
||||
|
||||
26
code/game/gamemodes/changeling/powers/chameleon_skin.dm
Normal file
26
code/game/gamemodes/changeling/powers/chameleon_skin.dm
Normal file
@@ -0,0 +1,26 @@
|
||||
/obj/effect/proc_holder/changeling/chameleon_skin
|
||||
name = "Chameleon Skin"
|
||||
desc = "Our skin pigmentation rapidly changes to suit our current environment."
|
||||
helptext = "Allows us to become invisible after a few seconds of standing still. Can be toggled on and off."
|
||||
dna_cost = 2
|
||||
chemical_cost = 25
|
||||
req_human = 1
|
||||
genetic_damage = 10
|
||||
max_genetic_damage = 50
|
||||
|
||||
|
||||
/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user)
|
||||
var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
|
||||
if(!istype(H))
|
||||
return
|
||||
var/datum/mutation/human/HM = mutations_list[CHAMELEON]
|
||||
if(H.dna && H.dna.mutations)
|
||||
if(HM in H.dna.mutations)
|
||||
HM.force_lose(H)
|
||||
else
|
||||
HM.force_give(H)
|
||||
|
||||
feedback_add_details("changeling_powers","CS")
|
||||
return 1
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
changeling.mimicing = mimic_voice
|
||||
changeling.chem_recharge_slowdown += 0.5
|
||||
user << "<span class='notice'>We shape our glands to take the voice of <b>[mimic_voice]</b>, this will stop us from regenerating chemicals while active.</span>"
|
||||
user << "<span class='notice'>Use this power again to return to our original voice and reproduce chemicals again.</span>"
|
||||
user << "<span class='notice'>We shape our glands to take the voice of <b>[mimic_voice]</b>, this will slow down regenerating chemicals while active.</span>"
|
||||
user << "<span class='notice'>Use this power again to return to our original voice and return chemical production to normal levels.</span>"
|
||||
|
||||
feedback_add_details("changeling_powers","MV")
|
||||
|
||||
@@ -159,7 +159,12 @@
|
||||
return
|
||||
|
||||
if(A.hasPower())
|
||||
user << "<span class='warning'>The airlock's motors resist our efforts to force it!</span>"
|
||||
if(A.locked)
|
||||
user << "<span class='warning'>The airlock's bolts prevent it from being forced!</span>"
|
||||
return
|
||||
user << "<span class='warning'>The airlock's motors are resisting, this may take time...</span>"
|
||||
if(do_after(user, 100, target = A))
|
||||
A.open(2)
|
||||
return
|
||||
|
||||
else if(A.locked)
|
||||
|
||||
@@ -33,11 +33,26 @@
|
||||
update_explanation_text()
|
||||
return target
|
||||
|
||||
/datum/objective/proc/find_target_by_role(role, role_type=0)//Option sets either to check assigned role or special role. Default to assigned.
|
||||
/datum/objective/proc/find_target_by_role(role, role_type=0, invert=0)//Option sets either to check assigned role or special role. Default to assigned., invert inverts the check, eg: "Don't choose a Ling"
|
||||
for(var/datum/mind/possible_target in ticker.minds)
|
||||
if((possible_target != owner) && ishuman(possible_target.current) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) )
|
||||
target = possible_target
|
||||
break
|
||||
if((possible_target != owner) && ishuman(possible_target.current))
|
||||
var/is_role = 0
|
||||
if(role_type)
|
||||
if(possible_target.special_role == role)
|
||||
is_role++
|
||||
else
|
||||
if(possible_target.assigned_role == role)
|
||||
is_role++
|
||||
|
||||
if(invert)
|
||||
if(is_role)
|
||||
continue
|
||||
target = possible_target
|
||||
break
|
||||
else if(is_role)
|
||||
target = possible_target
|
||||
break
|
||||
|
||||
update_explanation_text()
|
||||
|
||||
/datum/objective/proc/update_explanation_text()
|
||||
@@ -50,8 +65,9 @@
|
||||
dangerrating = 10
|
||||
martyr_compatible = 1
|
||||
|
||||
/datum/objective/assassinate/find_target_by_role(role, role_type=0)
|
||||
target_role_type = role_type
|
||||
/datum/objective/assassinate/find_target_by_role(role, role_type=0, invert=0)
|
||||
if(!invert)
|
||||
target_role_type = role_type
|
||||
..(role, role_type)
|
||||
return target
|
||||
|
||||
@@ -70,13 +86,13 @@
|
||||
explanation_text = "Free Objective"
|
||||
|
||||
|
||||
|
||||
/datum/objective/mutiny
|
||||
var/target_role_type=0
|
||||
martyr_compatible = 1
|
||||
|
||||
/datum/objective/mutiny/find_target_by_role(role, role_type=0)
|
||||
target_role_type = role_type
|
||||
/datum/objective/mutiny/find_target_by_role(role, role_type=0,invert=0)
|
||||
if(!invert)
|
||||
target_role_type = role_type
|
||||
..(role, role_type)
|
||||
return target
|
||||
|
||||
@@ -104,8 +120,9 @@
|
||||
dangerrating = 5
|
||||
martyr_compatible = 1
|
||||
|
||||
/datum/objective/maroon/find_target_by_role(role, role_type=0)
|
||||
target_role_type = role_type
|
||||
/datum/objective/maroon/find_target_by_role(role, role_type=0, invert=0)
|
||||
if(!invert)
|
||||
target_role_type = role_type
|
||||
..(role, role_type)
|
||||
return target
|
||||
|
||||
@@ -129,8 +146,9 @@
|
||||
var/target_role_type=0
|
||||
dangerrating = 20
|
||||
|
||||
/datum/objective/debrain/find_target_by_role(role, role_type=0)
|
||||
target_role_type = role_type
|
||||
/datum/objective/debrain/find_target_by_role(role, role_type=0, invert=0)
|
||||
if(!invert)
|
||||
target_role_type = role_type
|
||||
..(role, role_type)
|
||||
return target
|
||||
|
||||
@@ -162,8 +180,9 @@
|
||||
dangerrating = 10
|
||||
martyr_compatible = 1
|
||||
|
||||
/datum/objective/protect/find_target_by_role(role, role_type=0)
|
||||
target_role_type = role_type
|
||||
/datum/objective/protect/find_target_by_role(role, role_type=0, invert=0)
|
||||
if(!invert)
|
||||
target_role_type = role_type
|
||||
..(role, role_type)
|
||||
return target
|
||||
|
||||
@@ -640,3 +659,84 @@ var/global/list/possible_items_special = list()
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// Changeling team objectives //
|
||||
////////////////////////////////
|
||||
|
||||
/datum/objective/changeling_team_objective //Abstract type
|
||||
martyr_compatible = 0 //Suicide is not teamwork!
|
||||
explanation_text = "Changeling Friendship!"
|
||||
var/min_lings = 3 //Minimum amount of lings for this team objective to be possible
|
||||
|
||||
|
||||
/datum/objective/changeling_team_objective/impersonate_heads
|
||||
explanation_text = "Have X or more heads of staff escape on the shuttle disguised as heads, while the real heads are dead"
|
||||
var/list/head_minds = list()
|
||||
var/list/head_real_names = list()
|
||||
|
||||
|
||||
/datum/objective/changeling_team_objective/impersonate_heads/New(var/text)
|
||||
..()
|
||||
|
||||
var/needed_heads = 0
|
||||
|
||||
//Heads amount is between min lings and the amount of heads possible
|
||||
var/max_lings = ticker.mode.changelings.len
|
||||
needed_heads = Clamp(needed_heads,min_lings,max_lings)
|
||||
needed_heads = min(command_positions.len,needed_heads)
|
||||
|
||||
for(var/datum/mind/possible_head in ticker.minds)
|
||||
if(possible_head.assigned_job.title in command_positions)
|
||||
if(needed_heads)
|
||||
head_minds += possible_head
|
||||
head_real_names += possible_head.current.real_name
|
||||
needed_heads--
|
||||
|
||||
if(!head_minds.len) //No heads, bail, you saw nothing, you never had a team objective, hahaha!
|
||||
owner.objectives -= src
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
explanation_text = "Ensure changelings impersonate and escape as the following heads of staff: "
|
||||
|
||||
var/first = 1
|
||||
for(var/datum/mind/M in head_minds)
|
||||
var/string = "[M.name] the [M.assigned_role]" //John the Head of Personnel
|
||||
if(!first)
|
||||
string = ", [M.name] the [M.assigned_role]" //Fred the Head of Security
|
||||
else
|
||||
first--
|
||||
explanation_text += string
|
||||
|
||||
explanation_text += ", while the real heads are dead. This is a team objective."
|
||||
|
||||
|
||||
/datum/objective/changeling_team_objective/impersonate_heads/check_completion()
|
||||
//Check each head mind to see if any of them made it to centcomm alive, if they did it's an automatic fail
|
||||
for(var/datum/mind/HM in head_minds)
|
||||
if(HM.current)
|
||||
var/turf/hloc = get_turf(HM.current)
|
||||
if(hloc.onCentcom() && (HM.current.stat != DEAD))
|
||||
return 0 //A Non-ling living head-target got to centcom, fail
|
||||
|
||||
//Check each head has been replaced, by cross referencing changeling minds, changeling current dna, the heads minds and their original DNA names
|
||||
var/success = 0
|
||||
changelings:
|
||||
for(var/datum/mind/changeling in ticker.mode.changelings)
|
||||
if(success >= head_minds.len) //We did it, stop here!
|
||||
return 1
|
||||
if(ishuman(changeling.current))
|
||||
var/mob/living/carbon/human/H = changeling.current
|
||||
var/turf/cloc = get_turf(changeling.current)
|
||||
if(cloc && cloc.onCentcom() && (changeling.current.stat != DEAD)) //Living changeling on centcomm....
|
||||
for(var/name in head_real_names) //Is he (disguised as) a head?
|
||||
if(H.dna && H.dna.real_name == name)
|
||||
head_real_names -= name //This head is accounted for, remove them, so the team don't succeed by escape as 7 John the HoPs
|
||||
success++ //A living changeling head made it to centcomm
|
||||
continue changelings
|
||||
|
||||
if(success >= head_minds.len)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@@ -308,6 +308,7 @@
|
||||
#include "code\game\gamemodes\changeling\powers\absorb.dm"
|
||||
#include "code\game\gamemodes\changeling\powers\adrenaline.dm"
|
||||
#include "code\game\gamemodes\changeling\powers\augmented_eyesight.dm"
|
||||
#include "code\game\gamemodes\changeling\powers\chameleon_skin.dm"
|
||||
#include "code\game\gamemodes\changeling\powers\digitalcamo.dm"
|
||||
#include "code\game\gamemodes\changeling\powers\fakedeath.dm"
|
||||
#include "code\game\gamemodes\changeling\powers\fleshmend.dm"
|
||||
|
||||
Reference in New Issue
Block a user