Moves revolution code of out of flash code, fixes April Fool conversion forcesay never working in any cirumstances (#74411)

## About The Pull Request

- Signallizes head revolutionary flash conversion code, moving it out of
core flash code.
- Removes "tacticool" flashing from head revs, but they can still
convert from any direction
 
- Fixes April Fools "You son of a bitch! I'm in" force say never
working.
   - Revs are muted on conversion so they couldn't talk.
       - Fixed by only muting revs on non-holidays
   - Cultists are unconscious on conversion so they couldn't talk
       - Fixed by only unconscious-ing cultists on non-holidays
- Brainwash victims are more often than not unconscious / asleep so they
couldn't talk
       - Just left this one. 

- Reduced the chance of them occurring and limits it to April Fools only
- A 1% chance of the force says ocurring means they will happen pretty
much once a week, given multiple rev / cult rounds happen every week and
on average like, 20 people are converted. A little absurd, it's good
that it never worked?

## Why It's Good For The Game

Antag code in core item code is bad

It's funny this meme has existed for like 2, 3 years now? No one's
tested it, it's never worked

## Changelog

🆑 Melbert
refactor: Removes Rev code from core flash code
fix: Getting converted on April Fools now triggers the meme force say as
always intended
del: The meme force say can no longer trigger on any day (it didn't work
before anyways)
/🆑
This commit is contained in:
MrMelbert
2023-04-06 08:28:35 +12:00
committed by GitHub
parent 7777348020
commit 00f8bcfe75
9 changed files with 145 additions and 72 deletions
@@ -172,6 +172,16 @@
///from living/flash_act(), when a mob is successfully flashed.
#define COMSIG_MOB_FLASHED "mob_flashed"
/// from /obj/item/assembly/flash/flash_carbon, to the mob flashing another carbon
#define COMSIG_MOB_FLASHED_CARBON "mob_flashed_carbon"
/// Return to override deviation to be full deviation (fail the flash, usually)
#define DEVIATION_OVERRIDE_FULL (1<<0)
/// Return to override deviation to be partial deviation
#define DEVIATION_OVERRIDE_PARTIAL (1<<1)
/// Return to override deviation to be no deviation
#define DEVIATION_OVERRIDE_NONE (1<<2)
/// Return to stop the flash entirely
#define STOP_FLASH (1<<3)
/// from mob/get_status_tab_items(): (list/items)
#define COMSIG_MOB_GET_STATUS_TAB_ITEMS "mob_get_status_tab_items"
+8
View File
@@ -880,6 +880,14 @@ GLOBAL_LIST_INIT(layers_to_offset, list(
#define READING_CHECK_LITERACY (1<<0)
#define READING_CHECK_LIGHT (1<<1)
// Flash deviation defines
/// No deviation at all. Flashed from the front or front-left/front-right. Alternatively, flashed in direct view.
#define DEVIATION_NONE 0
/// Partial deviation. Flashed from the side. Alternatively, flashed out the corner of your eyes.
#define DEVIATION_PARTIAL 1
/// Full deviation. Flashed from directly behind or behind-left/behind-rack. Not flashed at all.
#define DEVIATION_FULL 2
/// In dynamic human icon gen we don't replace the held item.
#define NO_REPLACE 0
+1 -1
View File
@@ -201,7 +201,7 @@
else if(IS_REVOLUTIONARY(creator))
var/datum/antagonist/rev/converter = creator.mind.has_antag_datum(/datum/antagonist/rev,TRUE)
converter.add_revolutionary(src,FALSE)
converter.add_revolutionary(src, stun = FALSE, mute = FALSE)
else if(IS_NUKE_OP(creator))
var/datum/antagonist/nukeop/converter = creator.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE)
@@ -22,8 +22,9 @@
var/end_message = "."
var/rendered = begin_message + obj_message + end_message
deadchat_broadcast(rendered, "<b>[L]</b>", follow_target = L, turf_target = get_turf(L), message_type=DEADCHAT_ANNOUNCEMENT)
if(prob(1) || check_holidays(APRIL_FOOLS))
L.say("You son of a bitch! I'm in.", forced = "That son of a bitch! They're in.")
if(check_holidays(APRIL_FOOLS))
// Note: most of the time you're getting brainwashed you're unconscious
L.say("You son of a bitch! I'm in.", forced = "That son of a bitch! They're in. (April Fools)")
/datum/antagonist/brainwashed
name = "\improper Brainwashed Victim"
+31 -16
View File
@@ -262,30 +262,45 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(M, span_warning("Something is shielding [convertee]'s mind!"))
log_game("Offer rune with [convertee] on it failed - convertee had anti-magic.")
return FALSE
var/brutedamage = convertee.getBruteLoss()
var/burndamage = convertee.getFireLoss()
if(brutedamage || burndamage)
convertee.adjustBruteLoss(-(brutedamage * 0.75))
convertee.adjustFireLoss(-(burndamage * 0.75))
convertee.visible_message("<span class='warning'>[convertee] writhes in pain \
[brutedamage || burndamage ? "even as [convertee.p_their()] wounds heal and close" : "as the markings below [convertee.p_them()] glow a bloody red"]!</span>", \
span_cultlarge("<i>AAAAAAAAAAAAAA-</i>"))
convertee.mind?.add_antag_datum(/datum/antagonist/cult)
convertee.Unconscious(100)
convertee.visible_message(
span_warning("[convertee] writhes in pain [(brutedamage || burndamage) \
? "even as [convertee.p_their()] wounds heal and close" \
: "as the markings below [convertee.p_them()] glow a bloody red"]!"),
span_cultlarge("<i>AAAAAAAAAAAAAA-</i>"),
)
// We're not guaranteed to be a human but we'll cast here since we use it in a few branches
var/mob/living/carbon/human/human_convertee = convertee
if(check_holidays(APRIL_FOOLS) && prob(10))
convertee.Paralyze(10 SECONDS)
if(istype(human_convertee))
human_convertee.force_say()
convertee.say("You son of a bitch! I'm in.", forced = "That son of a bitch! They're in. (April Fools)")
else
convertee.Unconscious(10 SECONDS)
new /obj/item/melee/cultblade/dagger(get_turf(src))
convertee.mind.special_role = ROLE_CULTIST
to_chat(convertee, "<span class='cult italic'><b>Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
and something evil takes root.</b></span>")
to_chat(convertee, "<span class='cult italic'><b>Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.\
</b></span>")
if(ishuman(convertee))
var/mob/living/carbon/human/H = convertee
H.uncuff()
H.remove_status_effect(/datum/status_effect/speech/slurring/cult)
H.remove_status_effect(/datum/status_effect/speech/stutter)
if(prob(1) || check_holidays(APRIL_FOOLS))
H.say("You son of a bitch! I'm in.", forced = "That son of a bitch! They're in.")
to_chat(convertee, span_cultitalic("<b>Your blood pulses. Your head throbs. The world goes red. \
All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
and something evil takes root.</b>"))
to_chat(convertee, span_cultitalic("<b>Assist your new compatriots in their dark dealings. \
Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.</b>"))
if(istype(human_convertee))
human_convertee.uncuff()
human_convertee.remove_status_effect(/datum/status_effect/speech/slurring/cult)
human_convertee.remove_status_effect(/datum/status_effect/speech/stutter)
if(isshade(convertee))
convertee.icon_state = "shade_cult"
convertee.name = convertee.real_name
@@ -184,6 +184,51 @@
S.Remove(C)
return ..()
/datum/antagonist/rev/head/apply_innate_effects(mob/living/mob_override)
. = ..()
var/mob/living/real_mob = mob_override || owner.current
RegisterSignal(real_mob, COMSIG_MOB_FLASHED_CARBON, PROC_REF(on_flash))
/datum/antagonist/rev/head/remove_innate_effects(mob/living/mob_override)
. = ..()
var/mob/living/real_mob = mob_override || owner.current
UnregisterSignal(real_mob, COMSIG_MOB_FLASHED_CARBON)
/// Signal proc for [COMSIG_MOB_FLASHED_CARBON].
/// The bread and butter of head revolutionary conversions.
/datum/antagonist/rev/head/proc/on_flash(mob/living/source, mob/living/carbon/flashed, obj/item/assembly/flash/flash, deviation)
SIGNAL_HANDLER
// Always partial flash at the very least
. = (deviation == DEVIATION_FULL) ? DEVIATION_OVERRIDE_PARTIAL : NONE
if(flashed.stat == DEAD)
return .
if(flashed.stat != CONSCIOUS)
to_chat(source, span_warning("[flashed.p_they(capitalized = TRUE)] must be conscious before you can convert [flashed.p_them()]!"))
return .
if(isnull(flashed.mind) || !GET_CLIENT(flashed))
to_chat(source, span_warning("[flashed]'s mind is so vacant that it is not susceptible to influence!"))
return .
var/holiday_meme_chance = check_holidays(APRIL_FOOLS) && prob(10)
if(add_revolutionary(flashed.mind, mute = !holiday_meme_chance)) // don't mute if we roll the meme holiday chance
if(holiday_meme_chance)
INVOKE_ASYNC(src, PROC_REF(_async_holiday_meme_say), flashed)
flash.times_used-- // Flashes are less likely to burn out for headrevs, when used for conversion
else
to_chat(source, span_warning("[flashed] seems resistant to [flash]!"))
return .
/// Used / called async from [proc/on_flash] to deliver a funny meme line
/datum/antagonist/rev/head/proc/_async_holiday_meme_say(mob/living/carbon/flashed)
if(ishuman(flashed))
var/mob/living/carbon/human/human_flashed = flashed
human_flashed.force_say()
flashed.say("You son of a bitch! I'm in.", forced = "That son of a bitch! They're in. (April Fools)")
/datum/antagonist/rev/head/antag_listing_name()
return ..() + "(Leader)"
@@ -228,11 +273,20 @@
return FALSE
return TRUE
/datum/antagonist/rev/proc/add_revolutionary(datum/mind/rev_mind,stun = TRUE)
/**
* Adds a new mind to our revoltuion
*
* * rev_mind - the mind we're adding
* * stun - If TRUE, we will flash act and apply a long stun when we're applied
* * mute - If TRUE, we will apply a mute when we're applied
*/
/datum/antagonist/rev/proc/add_revolutionary(datum/mind/rev_mind, stun = TRUE, mute = TRUE)
if(!can_be_converted(rev_mind.current))
return FALSE
if(stun)
if(mute)
rev_mind.current.set_silence_if_lower(10 SECONDS)
if(stun)
rev_mind.current.flash_act(1, 1)
rev_mind.current.Stun(10 SECONDS)
+13 -51
View File
@@ -1,13 +1,5 @@
#define CONFUSION_STACK_MAX_MULTIPLIER 2
/// No deviation at all. Flashed from the front or front-left/front-right. Alternatively, flashed in direct view.
#define DEVIATION_NONE 0
/// Partial deviation. Flashed from the side. Alternatively, flashed out the corner of your eyes.
#define DEVIATION_PARTIAL 1
/// Full deviation. Flashed from directly behind or behind-left/behind-rack. Not flashed at all.
#define DEVIATION_FULL 2
/obj/item/assembly/flash
name = "flash"
desc = "A powerful and versatile flashbulb device, with applications ranging from disorienting attackers to acting as visual receptors in robot production."
@@ -156,25 +148,26 @@
var/deviation = calculate_deviation(flashed, user || src)
var/datum/antagonist/rev/head/converter = user?.mind?.has_antag_datum(/datum/antagonist/rev/head)
if(user)
var/sigreturn = SEND_SIGNAL(user, COMSIG_MOB_FLASHED_CARBON, flashed, src, deviation)
if(sigreturn & STOP_FLASH)
return
if(sigreturn & DEVIATION_OVERRIDE_FULL)
deviation = DEVIATION_FULL
else if(sigreturn & DEVIATION_OVERRIDE_PARTIAL)
deviation = DEVIATION_PARTIAL
else if(sigreturn & DEVIATION_OVERRIDE_NONE)
deviation = DEVIATION_NONE
//If you face away from someone they shouldnt notice any effects.
if(deviation == DEVIATION_FULL && !converter)
if(deviation == DEVIATION_FULL)
return
if(targeted)
if(flashed.flash_act(1, 1))
flashed.set_confusion_if_lower(confusion_duration * CONFUSION_STACK_MAX_MULTIPLIER)
// Special check for if we're a revhead. Special cases to attempt conversion.
if(converter)
// Did we try to flash them from behind?
if(deviation == DEVIATION_FULL)
// Headrevs can use a tacticool leaning technique so that they don't have to worry about facing for their conversions.
to_chat(user, span_notice("You use the tacticool tier, lean over the shoulder technique to blind [flashed] with a flash!"))
deviation = DEVIATION_PARTIAL
// Convert them. Terribly.
terrible_conversion_proc(flashed, user)
visible_message(span_danger("[user] blinds [flashed] with the flash!"), span_userdanger("[user] blinds you with the flash!"))
visible_message(span_danger("[user] blinds [flashed] with the flash!"), span_userdanger("[user] blinds you with the flash!"))
//easy way to make sure that you can only long stun someone who is facing in your direction
flashed.adjustStaminaLoss(rand(80, 120) * (1 - (deviation * 0.5)))
flashed.Paralyze(rand(25, 50) * (1 - (deviation * 0.5)))
@@ -277,34 +270,6 @@
return
AOE_flash()
/**
* Converts the victim to revs
*
* Arguments:
* * victim - Victim
* * aggressor - Attacker
*/
/obj/item/assembly/flash/proc/terrible_conversion_proc(mob/living/carbon/victim, mob/aggressor)
if(!istype(victim) || victim.stat == DEAD)
return
if(!aggressor.mind)
return
if(!victim.client)
to_chat(aggressor, span_warning("This mind is so vacant that it is not susceptible to influence!"))
return
if(victim.stat != CONSCIOUS)
to_chat(aggressor, span_warning("They must be conscious before you can convert [victim.p_them()]!"))
return
//If this proc fires the mob must be a revhead
var/datum/antagonist/rev/head/converter = aggressor.mind.has_antag_datum(/datum/antagonist/rev/head)
if(converter.add_revolutionary(victim.mind))
if(prob(1) || check_holidays(APRIL_FOOLS))
victim.say("You son of a bitch! I'm in.", forced = "That son of a bitch! They're in.")
times_used -- //Flashes less likely to burn out for headrevs when used for conversion
else
to_chat(aggressor, span_warning("This mind seems resistant to the flash!"))
/obj/item/assembly/flash/cyborg
/obj/item/assembly/flash/cyborg/attack(mob/living/M, mob/user)
@@ -415,6 +380,3 @@
M.adjust_pacifism(4 SECONDS)
#undef CONFUSION_STACK_MAX_MULTIPLIER
#undef DEVIATION_NONE
#undef DEVIATION_PARTIAL
#undef DEVIATION_FULL
+1
View File
@@ -181,6 +181,7 @@
#include "reagent_recipe_collisions.dm"
#include "reagent_transfer.dm"
#include "resist.dm"
#include "rev_conversion.dm"
#include "say.dm"
#include "screenshot_antag_icons.dm"
#include "screenshot_basic.dm"
+22
View File
@@ -0,0 +1,22 @@
/// Tests that headrevs can convert people by clicking on them with flashes
/datum/unit_test/revolution_conversion
/datum/unit_test/revolution_conversion/Run()
var/mob/living/carbon/human/leader = allocate(/mob/living/carbon/human/consistent, run_loc_floor_bottom_left)
var/mob/living/carbon/human/peasant = allocate(/mob/living/carbon/human/consistent, run_loc_floor_bottom_left)
leader.mind_initialize()
leader.mock_client = new()
peasant.mind_initialize()
peasant.mock_client = new()
var/datum/antagonist/rev/head/lead_datum = leader.mind.add_antag_datum(/datum/antagonist/rev/head)
var/datum/team/revolution/revolution = lead_datum.get_team()
var/obj/item/assembly/flash/handheld/converter = allocate(/obj/item/assembly/flash/handheld)
leader.put_in_active_hand(converter, forced = TRUE)
leader.ClickOn(peasant)
TEST_ASSERT(peasant.IsParalyzed(), "Peasant was not paralyzed after being flashed by the leader") // Flash paralyze
TEST_ASSERT(peasant.IsStun(), "Peasant was not stunned after being converted by the leader") // Conversion stun
TEST_ASSERT_EQUAL(length(revolution.members), 2, "Expected revolution to have 2 members after the leader flashes the peasant.")