Merge branch 'dynamicport'

This commit is contained in:
keronshb
2021-10-09 00:28:30 -04:00
76 changed files with 2349 additions and 3077 deletions
@@ -55,9 +55,15 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/specialization(datum/mind/new_owner)
return src
///Called by the transfer_to() mind proc after the mind (mind.current and new_character.mind) has moved but before the player (key and client) is transfered.
/datum/antagonist/proc/on_body_transfer(mob/living/old_body, mob/living/new_body)
SHOULD_CALL_PARENT(TRUE)
remove_innate_effects(old_body)
if(old_body.stat != DEAD && !LAZYLEN(old_body.mind?.antag_datums))
old_body.remove_from_current_living_antags()
apply_innate_effects(new_body)
if(new_body.stat != DEAD)
new_body.add_to_current_living_antags()
//This handles the application of antag huds/special abilities
/datum/antagonist/proc/apply_innate_effects(mob/living/mob_override)
@@ -94,8 +100,9 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/create_team(datum/team/team)
return
//Proc called when the datum is given to a mind.
///Called by the add_antag_datum() mind proc after the instanced datum is added to the mind's antag_datums list.
/datum/antagonist/proc/on_gain()
SHOULD_CALL_PARENT(TRUE)
set waitfor = FALSE
if(!(owner?.current))
return
@@ -113,6 +120,8 @@ GLOBAL_LIST_EMPTY(antagonists)
if(istype(M))
M.name = "[name] Training"
owner.current.AddComponent(/datum/component/activity)
if(owner.current.stat != DEAD)
owner.current.add_to_current_living_antags()
SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src)
/datum/antagonist/proc/is_banned(mob/M)
@@ -131,13 +140,17 @@ GLOBAL_LIST_EMPTY(antagonists)
owner.current.ghostize(0)
C.transfer_ckey(owner.current, FALSE)
///Called by the remove_antag_datum() and remove_all_antag_datums() mind procs for the antag datum to handle its own removal and deletion.
/datum/antagonist/proc/on_removal()
SHOULD_CALL_PARENT(TRUE)
remove_innate_effects()
clear_antag_moodies()
if(owner)
LAZYREMOVE(owner.antag_datums, src)
for(var/A in skill_modifiers)
owner.remove_skill_modifier(GET_SKILL_MOD_ID(A, type))
if(!LAZYLEN(owner.antag_datums))
owner.current.remove_from_current_living_antags()
if(!silent && owner.current)
farewell()
var/datum/team/team = get_team()
@@ -94,15 +94,6 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
if(board.moved)
to_chat(user, "The shuttle has already been moved! You have forfeit the right to declare war.")
return FALSE
if(istype(SSticker.mode, /datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
if(!(mode.storyteller.flags & WAROPS_ALWAYS_ALLOWED))
if(mode.threat_level < CONFIG_GET(number/dynamic_warops_requirement))
to_chat(user, "Due to the dynamic space in which the station resides, you are too deep into Nanotrasen territory to reasonably go loud.")
return FALSE
else if(mode.threat < CONFIG_GET(number/dynamic_warops_cost))
to_chat(user, "Due to recent threats on the station, Nanotrasen is looking too closely for a war declaration to be wise.")
return FALSE
return TRUE
/obj/item/nuclear_challenge/clownops
+156 -19
View File
@@ -1,3 +1,5 @@
#define DECONVERTER_STATION_WIN "gamemode_station_win"
#define DECONVERTER_REVS_WIN "gamemode_revs_win"
//How often to check for promotion possibility
#define HEAD_UPDATE_PERIOD 300
@@ -10,6 +12,11 @@
threat = 2
var/hud_type = "rev"
var/datum/team/revolution/rev_team
///when this antagonist is being de-antagged, this is why
var/deconversion_reason
/// What message should the player receive when they are being demoted, and the revolution has won?
var/victory_message = "The revolution has overpowered the command staff! Viva la revolution! Execute any head of staff and security should you find them alive."
/datum/antagonist/rev/can_be_owned(datum/mind/new_owner)
. = ..()
@@ -201,7 +208,22 @@
new_rev.silent = FALSE
to_chat(old_owner, "<span class='userdanger'>Revolution has been disappointed of your leader traits! You are a regular revolutionary now!</span>")
/// Checks if the revolution succeeded, and lets them know.
/datum/antagonist/rev/proc/announce_victorious()
. = rev_team.check_rev_victory()
if (!.)
return
to_chat(owner, "<span class='deconversion_message bold'>[victory_message]</span>")
var/policy = get_policy(ROLE_REV_SUCCESSFUL)
if (policy)
to_chat(owner, policy)
/datum/antagonist/rev/farewell()
if (announce_victorious())
return
if(ishuman(owner.current))
owner.current.visible_message("<span class='deconversion_message'>[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!</span>", null, null, null, owner.current)
to_chat(owner, "<span class='userdanger'>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel... You don't seem to be able to recall the names of your comrades, not even your leaders...</span>")
@@ -210,15 +232,17 @@
to_chat(owner, "<span class='userdanger'>The frame's firmware detects and deletes your neural reprogramming! You remember nothing of your time spent reprogrammed, you can't even remember the names or identities of anyone involved...</span>")
/datum/antagonist/rev/head/farewell()
if((ishuman(owner.current) || ismonkey(owner.current)))
if (announce_victorious() || deconversion_reason == DECONVERTER_STATION_WIN)
return
if((ishuman(owner.current)))
if(owner.current.stat != DEAD)
owner.current.visible_message("<span class='deconversion_message'>[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!</span>", null, null, null, owner.current)
owner.current.visible_message(span_deconversion_message("[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!"), null, null, null, owner.current)
to_chat(owner, "<span class ='deconversion_message bold'>You have given up your cause of overthrowing the command staff. You are no longer a Head Revolutionary.</span>")
else
to_chat(owner, "<span class ='deconversion_message bold'>The sweet release of death. You are no longer a Head Revolutionary.</span>")
else if(issilicon(owner.current))
owner.current.visible_message("<span class='deconversion_message'>The frame beeps contentedly, suppressing the disloyal personality traits from the MMI before initalizing it.</span>", null, null, null, owner.current)
to_chat(owner, "<span class='userdanger'>The frame's firmware detects and suppresses your unwanted personality traits! You feel more content with the leadership around these parts.</span>")
owner.current.visible_message(span_deconversion_message("The frame beeps contentedly, suppressing the disloyal personality traits from the MMI before initalizing it."), null, null, null, owner.current)
to_chat(owner, span_userdanger("The frame's firmware detects and suppresses your unwanted personality traits! You feel more content with the leadership around these parts."))
//blunt trauma deconversions call this through species.dm spec_attacked_by()
/datum/antagonist/rev/proc/remove_revolutionary(borged, deconverter)
@@ -226,13 +250,14 @@
if(borged)
message_admins("[ADMIN_LOOKUPFLW(owner.current)] has been borged while being a [name]")
owner.special_role = null
if(iscarbon(owner.current))
if(iscarbon(owner.current) && deconverter != DECONVERTER_REVS_WIN)
var/mob/living/carbon/C = owner.current
C.Unconscious(100)
deconversion_reason = deconverter
owner.remove_antag_datum(type)
/datum/antagonist/rev/head/remove_revolutionary(borged,deconverter)
if(borged || deconverter == "gamemode")
if(borged || deconverter == DECONVERTER_STATION_WIN || deconverter == DECONVERTER_REVS_WIN)
. = ..()
/datum/antagonist/rev/head/equip_rev()
@@ -262,6 +287,21 @@
S.Insert(H, special = FALSE, drop_if_replaced = FALSE)
to_chat(H, "Your eyes have been implanted with a cybernetic security HUD which will help you keep track of who is mindshield-implanted, and therefore unable to be recruited.")
/// "Enemy of the Revolutionary", given to heads and security when the revolution wins
/datum/antagonist/revolution_enemy
name = "Enemy of the Revolution"
show_in_antagpanel = FALSE
/datum/antagonist/revolution_enemy/on_gain()
owner.special_role = "revolution enemy"
var/datum/objective/survive/survive = new /datum/objective/survive
survive.owner = owner
survive.explanation_text = "The station has been overrun by revolutionaries, stay alive until the end."
objectives += survive
return ..()
/datum/team/revolution
name = "Revolution"
var/max_headrevs = 3
@@ -314,6 +354,100 @@
ex_headrevs = get_antag_minds(/datum/antagonist/rev/head, TRUE)
ex_revs = get_antag_minds(/datum/antagonist/rev, TRUE)
/// Checks if revs have won
/datum/team/revolution/proc/check_rev_victory()
for(var/datum/objective/mutiny/objective in objectives)
if(!(objective.check_completion()))
return FALSE
return TRUE
/// Checks if heads have won
/datum/team/revolution/proc/check_heads_victory()
for(var/datum/mind/rev_mind in head_revolutionaries())
var/turf/rev_turf = get_turf(rev_mind.current)
if(!considered_afk(rev_mind) && considered_alive(rev_mind) && is_station_level(rev_turf.z))
if(ishuman(rev_mind.current))
return FALSE
return TRUE
/// Updates the state of the world depending on if revs won or loss.
/// Returns who won, at which case this method should no longer be called.
/// If revs_win_injection_amount is passed, then that amount of threat will be added if the revs win.
/datum/team/revolution/proc/process_victory(revs_win_injection_amount)
if (check_rev_victory())
. = REVOLUTION_VICTORY
else if (check_heads_victory())
. = STATION_VICTORY
else
return
SSshuttle.clearHostileEnvironment(src)
save_members()
// Remove everyone as a revolutionary
for (var/_rev_mind in members)
var/datum/mind/rev_mind = _rev_mind
if (rev_mind.has_antag_datum(/datum/antagonist/rev))
var/datum/antagonist/rev/rev_antag = rev_mind.has_antag_datum(/datum/antagonist/rev)
rev_antag.remove_revolutionary(FALSE, . == STATION_VICTORY ? DECONVERTER_STATION_WIN : DECONVERTER_REVS_WIN)
LAZYADD(rev_mind.special_statuses, "<span class='bad'>Former [(rev_mind in ex_headrevs) ? "head revolutionary" : "revolutionary"]</span>")
if (. == STATION_VICTORY)
// If the revolution was quelled, make rev heads unable to be revived through pods
for (var/_rev_head_mind in ex_revs)
var/datum/mind/rev_head_mind = _rev_head_mind
var/mob/living/carbon/rev_head_body = rev_head_mind.current
if(istype(rev_head_body) && rev_head_body.stat == DEAD)
rev_head_body.makeUncloneable()
priority_announce("It appears the mutiny has been quelled. Please return yourself and your incapacitated colleagues to work. \
We have remotely blacklisted the head revolutionaries in your medical records to prevent accidental revival.", null, 'sound/announcer/classic/attention.ogg', null, "Central Command Loyalty Monitoring Division")
else
for (var/_player in GLOB.player_list)
var/mob/player = _player
var/datum/mind/mind = player.mind
if (isnull(mind))
continue
if (!(mind.assigned_role in GLOB.command_positions + GLOB.security_positions))
continue
var/mob/living/carbon/target_body = mind.current
mind.add_antag_datum(/datum/antagonist/revolution_enemy)
if (!istype(target_body))
continue
if (target_body.stat == DEAD)
target_body.makeUncloneable()
else
mind.announce_objectives()
for (var/job_name in GLOB.command_positions + GLOB.security_positions)
var/datum/job/job = SSjob.GetJob(job_name)
job.allow_bureaucratic_error = FALSE
job.total_positions = 0
if (revs_win_injection_amount)
var/datum/game_mode/dynamic/dynamic = SSticker.mode
dynamic.create_threat(revs_win_injection_amount)
dynamic.threat_log += "[worldtime2text()]: Revolution victory. Added [revs_win_injection_amount] threat."
priority_announce("A recent assessment of your station has marked your station as a severe risk area for high ranking Nanotrasen officials. \
For the safety of our staff, we have blacklisted your station for new employment of security and command. \
[pick(world.file2list("strings/anti_union_propaganda.txt"))]", null, 'sound/announcer/classic/attention.ogg', null, "Central Command Loyalty Monitoring Division")
/// Mutates the ticker to report that the revs have won
/datum/team/revolution/proc/round_result(finished)
if (finished == REVOLUTION_VICTORY)
SSticker.mode_result = "win - heads killed"
SSticker.news_report = REVS_WIN
else if (finished == STATION_VICTORY)
SSticker.mode_result = "loss - rev heads killed"
SSticker.news_report = REVS_LOSE
/datum/team/revolution/roundend_report()
if(!members.len && !ex_headrevs.len)
return
@@ -322,18 +456,6 @@
result += "<div class='panel redborder'>"
var/num_revs = 0
var/num_survivors = 0
for(var/mob/living/carbon/survivor in GLOB.alive_mob_list)
if(survivor.ckey)
num_survivors++
if(survivor.mind)
if(is_revolutionary(survivor))
num_revs++
if(num_survivors)
result += "Command's Approval Rating: <B>[100 - round((num_revs/num_survivors)*100, 0.1)]%</B><br>"
var/list/targets = list()
var/list/datum/mind/headrevs
var/list/datum/mind/revs
@@ -346,10 +468,22 @@
revs = ex_revs
else
revs = get_antag_minds(/datum/antagonist/rev, TRUE)
var/num_revs = 0
var/num_survivors = 0
for(var/mob/living/carbon/survivor in GLOB.alive_mob_list)
if(survivor.ckey)
num_survivors += 1
if ((survivor.mind in revs) || (survivor.mind in headrevs))
num_revs += 1
if(num_survivors)
result += "Command's Approval Rating: <B>[100 - round((num_revs/num_survivors)*100, 0.1)]%</B><br>"
if(headrevs.len)
var/list/headrev_part = list()
headrev_part += "<span class='header'>The head revolutionaries were:</span>"
headrev_part += printplayerlist(headrevs,TRUE)
headrev_part += printplayerlist(headrevs, !check_rev_victory())
result += headrev_part.Join("<br>")
if(revs.len)
@@ -408,3 +542,6 @@
/datum/team/revolution/is_gamemode_hero()
return SSticker.mode.name == "revolution"
#undef DECONVERTER_STATION_WIN
#undef DECONVERTER_REVS_WIN
@@ -3,7 +3,6 @@
typepath = /datum/round_event/ghost_role/slaughter
weight = 1 //Very rare
max_occurrences = 1
gamemode_blacklist = list("dynamic")
earliest_start = 1 HOURS
min_players = 20
@@ -5,6 +5,7 @@
max_occurrences = 1 //Only once okay fam
earliest_start = 30 MINUTES
min_players = 35
dynamic_should_hijack = TRUE
/datum/round_event/spawn_swarmer
@@ -28,17 +28,11 @@
/datum/traitor_class/human/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/assassin_prob = 50
var/is_dynamic = FALSE
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
assassin_prob = max(0,mode.threat_level-20)
if(prob(assassin_prob))
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[T.owner.name] added [threat_spent] on an assassination target.")
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
@@ -46,17 +46,13 @@
traitor_kind.on_process(src)
/proc/get_random_traitor_kind(var/list/blacklist = list())
var/chaos_weight = 0
if(istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
chaos_weight = (mode.threat - 50)/50
var/list/weights = list()
for(var/C in GLOB.traitor_classes)
if(!(C in blacklist))
var/datum/traitor_class/class = GLOB.traitor_classes[C]
if(class.min_players > length(GLOB.joined_player_list))
continue
var/weight = LOGISTIC_FUNCTION(1.5*class.weight,chaos_weight,class.chaos,0)
var/weight = LOGISTIC_FUNCTION(1.5*class.weight,0,class.chaos,0)
weights[C] = weight * 1000
var/choice = pickweight(weights, 0)
if(!choice)