Skip to content

Commit

Permalink
Replaces the poster and graffiti objectives with assault and early st…
Browse files Browse the repository at this point in the history
…eal & destroy ones. (tgstation#77029)

## About The Pull Request

With the blessings of @Watermelon914 I am removing the two objectives
for placing posters and spraying graffiti.

These old objectives are not dead. Their items have moved to the
Badassery section of the uplink.

A box of 3 demotivational posters can be bought for 1TC with 0 rep.
The spraycan can be bought for 1TC with 0 rep.

In their place comes one new objective and one extended objective.

The new objective is Assault a Crewmember. This objective requires you
to attack the specified target 2-5 times (random on objective
generation). It tallies from any attack that filters through the
`/datum/element/relay_attackers` element and has an "attacker"
associated with it.

Although it asks you not to kill the other player, it doesn't fail if
you kill them.

I have expanded the low-risk theft objectives with items like a mime
mask, lawyer badge and a fake moustache (commonly on cooks).

Finally, I've added a very low level set of steal-and-destroy objectives
aimed at some items that will require a bit of basic breaking and
entering, and the destruction of which may hurt crew morale.

```
/datum/objective_item/steal/traitor/donut_box
/datum/objective_item/steal/traitor/rpd
/datum/objective_item/steal/traitor/space_law
/datum/objective_item/steal/traitor/granted_stamp
/datum/objective_item/steal/traitor/denied_stamp
/datum/objective_item/steal/traitor/lizard_plush
/datum/objective_item/steal/traitor/moth_plush
/datum/objective_item/steal/traitor/insuls
```

This PR also fixes clown shoes missing a proc override to allow them to
actually register as a theft objective.


![image](https://github.com/tgstation/tgstation/assets/24975989/775d46cf-f40a-43e5-9bf1-3aa4a31d436e)

![image](https://github.com/tgstation/tgstation/assets/24975989/66c77815-1f2b-4dfb-99c6-b8f2e0061654)

![image](https://github.com/tgstation/tgstation/assets/24975989/85d3878a-c598-4ec0-9bb1-920380a004c6)
## Why It's Good For The Game

Basically my discussion with Watermelon focused on the idea that the
graffiti and poster objectives weren't really crimes. They baited
antagonists into very passive play early-game.

These new replacements encourage a more antagonistic playstyle. Starting
fights plus B&E are two bread-and-butter play paradigms for antaggery.

Giving a few early game theft + destroy options with a mix of impactful
items (like insuls and RPDs) versus more symbolic or emotive items
(plushies, donut boxes, Cargonia stamps) gets antagonists out and about
in the station, warming themselves up.

And having an objective to assault players (even if you don't kill them)
allows cheeky antags with a penchant for shittery to start fights with
players and start genuinely impacting the shift, involving sec and
drawing players into their antaggery.

Both of these natually ease players into the more substantive theft and
murder objectives.

The existing spray and posters are actually thematically super cool.
Traitors now have even more access to them since they can be bought for
1TC per spraycan/3-pack of posters. This lets antags with TC to spare
run gimmicks around them and adds extra fun to the Badassery section.
## Changelog
:cl:
del: Traitor objectives to place posters and graffiti the station have
been removed.
add: The items associated with the poster and graffiti objectives can
now be purchased from the Badassery section of the uplink. The posters
come in a box of 3 for 1TC, and the spraycans are 1TC each.
add: Adds a new Assault traitor objective, requiring you to the attack
the target a few times without needing to kill them. Earn TC and
reputation by starting barroom fights and bait players into escalation
battles for fun and profit.
add: Expands low-risk steal objectives to include the Chef's fake
moustache, Lawyer's badge, and Mime's mask.
add: Adds brand new shift start Steal & Destroy objectives for early
breaking and entering. Smash your way into a sec checkpoint to grab a
Space Law book, engineering to grab some insulated gloves or the psych
office to kidnap their moth plush.
fix: Fixes an issue where the steal clown shoes objective would never be
valid.
/:cl:
  • Loading branch information
Timberpoes authored Aug 21, 2023
1 parent 689b5f1 commit 2d4d23d
Show file tree
Hide file tree
Showing 15 changed files with 344 additions and 241 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,5 @@
#define ATTACKER_STAMINA_ATTACK (1<<0)
///the attacker is shoving the source
#define ATTACKER_SHOVING (1<<1)
/// The attack is a damaging-type attack
#define ATTACKER_DAMAGING_ATTACK (1<<2)
25 changes: 16 additions & 9 deletions code/datums/elements/relay_attackers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,25 @@
/datum/element/relay_attackers/proc/after_attackby(atom/target, obj/item/weapon, mob/attacker)
SIGNAL_HANDLER
if(weapon.force)
relay_attacker(target, attacker, weapon.damtype == STAMINA ? ATTACKER_STAMINA_ATTACK : NONE)
relay_attacker(target, attacker, weapon.damtype == STAMINA ? ATTACKER_STAMINA_ATTACK : ATTACKER_DAMAGING_ATTACK)

/datum/element/relay_attackers/proc/on_attack_generic(atom/target, mob/living/attacker, list/modifiers)
SIGNAL_HANDLER
var/shoving = LAZYACCESS(modifiers, RIGHT_CLICK) ? ATTACKER_SHOVING : NONE
if(attacker.combat_mode || shoving)
relay_attacker(target, attacker, shoving)

// Check for a shove.
if(LAZYACCESS(modifiers, RIGHT_CLICK))
relay_attacker(target, attacker, ATTACKER_SHOVING)
return

// Else check for combat mode.
if(attacker.combat_mode)
relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK)
return

/datum/element/relay_attackers/proc/on_attack_npc(atom/target, mob/living/attacker)
SIGNAL_HANDLER
if(attacker.melee_damage_upper > 0)
relay_attacker(target, attacker)
relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK)

/// Even if another component blocked this hit, someone still shot at us
/datum/element/relay_attackers/proc/on_bullet_act(atom/target, list/bullet_args, obj/projectile/hit_projectile)
Expand All @@ -54,7 +61,7 @@
return
if(!ismob(hit_projectile.firer))
return
relay_attacker(target, hit_projectile.firer, hit_projectile.damage_type == STAMINA ? ATTACKER_STAMINA_ATTACK : NONE)
relay_attacker(target, hit_projectile.firer, hit_projectile.damage_type == STAMINA ? ATTACKER_STAMINA_ATTACK : ATTACKER_DAMAGING_ATTACK)

/// Even if another component blocked this hit, someone still threw something
/datum/element/relay_attackers/proc/on_hitby(atom/target, atom/movable/hit_atom, datum/thrownthing/throwingdatum)
Expand All @@ -67,15 +74,15 @@
var/mob/thrown_by = hit_item.thrownby?.resolve()
if(!ismob(thrown_by))
return
relay_attacker(target, thrown_by, hit_item.damtype == STAMINA ? ATTACKER_STAMINA_ATTACK : NONE)
relay_attacker(target, thrown_by, hit_item.damtype == STAMINA ? ATTACKER_STAMINA_ATTACK : ATTACKER_DAMAGING_ATTACK)

/datum/element/relay_attackers/proc/on_attack_hulk(atom/target, mob/attacker)
SIGNAL_HANDLER
relay_attacker(target, attacker)
relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK)

/datum/element/relay_attackers/proc/on_attack_mech(atom/target, obj/vehicle/sealed/mecha/mecha_attacker, mob/living/pilot)
SIGNAL_HANDLER
relay_attacker(target, mecha_attacker)
relay_attacker(target, mecha_attacker, ATTACKER_DAMAGING_ATTACK)

/// Send out a signal identifying whoever just attacked us (usually a mob but sometimes a mech or turret)
/datum/element/relay_attackers/proc/relay_attacker(atom/victim, atom/attacker, attack_flags)
Expand Down
120 changes: 120 additions & 0 deletions code/game/gamemodes/objective_items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,40 @@
targetitem = /obj/item/clothing/shoes/clown_shoes
excludefromjob = list(JOB_CLOWN, JOB_CARGO_TECHNICIAN, JOB_QUARTERMASTER)
item_owner = list(JOB_CLOWN)
exists_on_map = TRUE

/obj/item/clothing/shoes/clown_shoes/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/clothing/shoes/clown_shoes)

/datum/objective_item/steal/traitor/mime_mask
name = "the mime's mask"
targetitem = /obj/item/clothing/mask/gas/mime
excludefromjob = list(JOB_MIME, JOB_CARGO_TECHNICIAN, JOB_QUARTERMASTER)
item_owner = list(JOB_MIME)
exists_on_map = TRUE

/obj/item/clothing/mask/gas/mime/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/clothing/mask/gas/mime)

/datum/objective_item/steal/traitor/pka
name = "a protokinetic accelerator"
targetitem = /obj/item/gun/energy/recharge/kinetic_accelerator
excludefromjob = list(JOB_SHAFT_MINER, JOB_CARGO_TECHNICIAN, JOB_QUARTERMASTER)
item_owner = list(JOB_SHAFT_MINER)
exists_on_map = TRUE

/obj/item/gun/energy/recharge/kinetic_accelerator/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/gun/energy/recharge/kinetic_accelerator)

/datum/objective_item/steal/traitor/chef_moustache
name = "a fancy fake moustache"
targetitem = /obj/item/clothing/mask/fakemoustache/italian
excludefromjob = list(JOB_COOK, JOB_HEAD_OF_PERSONNEL, JOB_CARGO_TECHNICIAN, JOB_QUARTERMASTER)
item_owner = list(JOB_COOK)
exists_on_map = TRUE

/obj/item/clothing/mask/fakemoustache/italian/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/clothing/mask/fakemoustache/italian)

/datum/objective_item/steal/traitor/det_revolver
name = "detective's revolver"
Expand All @@ -134,6 +168,16 @@
/obj/item/gun/ballistic/revolver/c38/detective/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/gun/ballistic/revolver/c38/detective)

/datum/objective_item/steal/traitor/lawyers_badge
name = "the lawyer's badge"
targetitem = /obj/item/clothing/accessory/lawyers_badge
excludefromjob = list(JOB_LAWYER)
item_owner = list(JOB_LAWYER)
exists_on_map = TRUE

/obj/item/clothing/accessory/lawyers_badge/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/clothing/accessory/lawyers_badge)

/datum/objective_item/steal/traitor/chief_engineer_belt
name = "the chief engineer's belt"
targetitem = /obj/item/storage/belt/utility/chief
Expand Down Expand Up @@ -401,3 +445,79 @@

/obj/item/blackbox/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/blackbox)


// A number of special early-game steal objectives intended to be used with the steal-and-destroy objective.
// They're basically items of utility or emotional value that may be found on many players or lying around the station.
/datum/objective_item/steal/traitor/insuls
name = "insulated gloves"
targetitem = /obj/item/clothing/gloves/color/yellow
excludefromjob = list(JOB_CARGO_TECHNICIAN, JOB_QUARTERMASTER, JOB_ATMOSPHERIC_TECHNICIAN, JOB_STATION_ENGINEER, JOB_CHIEF_ENGINEER)
item_owner = list(JOB_STATION_ENGINEER, JOB_CHIEF_ENGINEER)
exists_on_map = TRUE

/obj/item/clothing/gloves/color/yellow/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/clothing/gloves/color/yellow)

/datum/objective_item/steal/traitor/moth_plush
name = "cute moth plush toy"
targetitem = /obj/item/toy/plush/moth
excludefromjob = list(JOB_PSYCHOLOGIST, JOB_PARAMEDIC, JOB_CHEMIST, JOB_MEDICAL_DOCTOR, JOB_VIROLOGIST, JOB_CHIEF_MEDICAL_OFFICER, JOB_CORONER)
exists_on_map = TRUE

/obj/item/toy/plush/moth/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/toy/plush/moth)

/datum/objective_item/steal/traitor/lizard_plush
name = "cute lizard plush toy"
targetitem = /obj/item/toy/plush/lizard_plushie
exists_on_map = TRUE

/obj/item/toy/plush/lizard_plushie/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/toy/plush/lizard_plushie)

/datum/objective_item/steal/traitor/denied_stamp
name = "cargo's denied stamp"
targetitem = /obj/item/stamp/denied
excludefromjob = list(JOB_CARGO_TECHNICIAN, JOB_QUARTERMASTER, JOB_SHAFT_MINER)
exists_on_map = TRUE

/obj/item/stamp/denied/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/stamp/denied)

/datum/objective_item/steal/traitor/granted_stamp
name = "cargo's granted stamp"
targetitem = /obj/item/stamp/granted
excludefromjob = list(JOB_CARGO_TECHNICIAN, JOB_QUARTERMASTER, JOB_SHAFT_MINER)
exists_on_map = TRUE

/obj/item/stamp/granted/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/stamp/granted)

/datum/objective_item/steal/traitor/space_law
name = "a book on space law"
targetitem = /obj/item/book/manual/wiki/security_space_law
excludefromjob = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_HEAD_OF_SECURITY, JOB_LAWYER, JOB_DETECTIVE)
exists_on_map = TRUE

/obj/item/book/manual/wiki/security_space_law/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/book/manual/wiki/security_space_law)

/datum/objective_item/steal/traitor/rpd
name = "rapid pipe dispenser"
targetitem = /obj/item/pipe_dispenser
excludefromjob = list(JOB_ATMOSPHERIC_TECHNICIAN, JOB_STATION_ENGINEER, JOB_CHIEF_ENGINEER, JOB_SCIENTIST, JOB_RESEARCH_DIRECTOR, JOB_GENETICIST, JOB_ROBOTICIST)
item_owner = list(JOB_CHIEF_ENGINEER)
exists_on_map = TRUE

/obj/item/pipe_dispenser/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/pipe_dispenser)

/datum/objective_item/steal/traitor/donut_box
name = "a box of prized donuts"
targetitem = /obj/item/storage/fancy/donut_box
excludefromjob = list(JOB_CAPTAIN, JOB_CHIEF_ENGINEER, JOB_HEAD_OF_PERSONNEL, JOB_HEAD_OF_SECURITY, JOB_QUARTERMASTER, JOB_CHIEF_MEDICAL_OFFICER, JOB_RESEARCH_DIRECTOR, JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_LAWYER, JOB_DETECTIVE)
exists_on_map = TRUE

/obj/item/storage/fancy/donut_box/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/storage/fancy/donut_box)
Original file line number Diff line number Diff line change
@@ -1,86 +1,3 @@
/datum/traitor_objective/demoralise/poster
name = "Sow doubt among the crew %VIEWS% times using Syndicate propaganda."
description = "Use the button below to materialize a pack of posters, \
which will demoralise nearby crew members (especially those in positions of authority). \
If your posters are destroyed before they are sufficiently upset, this objective will fail. \
Try hiding some broken glass behind your poster before you hang it to give \
do-gooders who try to take it down a hard time!"

progression_minimum = 0 MINUTES
progression_maximum = 30 MINUTES
progression_reward = list(4 MINUTES, 8 MINUTES)
telecrystal_reward = list(0, 1)

duplicate_type = /datum/traitor_objective/demoralise/poster
/// Have we handed out a box of stuff yet?
var/granted_posters = FALSE
/// All of the posters the traitor gets, if this list is empty they've failed
var/list/obj/structure/sign/poster/traitor/posters = list()

/datum/traitor_objective/demoralise/poster/generate_ui_buttons(mob/user)
var/list/buttons = list()
if (!granted_posters)
buttons += add_ui_button("", "Pressing this will materialize a box of posters in your hand.", "wifi", "summon_gear")
else
buttons += add_ui_button("[length(posters)] posters remaining", "This many propaganda posters remain active somewhere on the station.", "box", "none")
buttons += add_ui_button("[demoralised_crew_events] / [demoralised_crew_required] propagandised", "This many crew have been exposed to propaganda, out of a required [demoralised_crew_required].", "wifi", "none")
return buttons

#define POSTERS_PROVIDED 3

/datum/traitor_objective/demoralise/poster/ui_perform_action(mob/living/user, action)
. = ..()
switch(action)
if ("summon_gear")
if (granted_posters)
return

granted_posters = TRUE
var/obj/item/storage/box/syndie_kit/posterbox = new(user.drop_location())
for(var/i in 1 to POSTERS_PROVIDED)
var/obj/item/poster/traitor/added_poster = new /obj/item/poster/traitor(posterbox)
var/obj/structure/sign/poster/traitor/poster_when_placed = added_poster.poster_structure
posters += poster_when_placed
RegisterSignal(poster_when_placed, COMSIG_DEMORALISING_EVENT, PROC_REF(on_mood_event))
RegisterSignal(poster_when_placed, COMSIG_POSTER_TRAP_SUCCEED, PROC_REF(on_triggered_trap))
RegisterSignal(poster_when_placed, COMSIG_QDELETING, PROC_REF(on_poster_destroy))

user.put_in_hands(posterbox)
posterbox.balloon_alert(user, "the box materializes in your hand")

#undef POSTERS_PROVIDED

/datum/traitor_objective/demoralise/poster/ungenerate_objective()
for (var/poster in posters)
UnregisterSignal(poster, COMSIG_DEMORALISING_EVENT)
UnregisterSignal(poster, COMSIG_QDELETING)
posters.Cut()
return ..()

/**
* Called if someone gets glass stuck in their hand from one of your posters.
*
* Arguments
* * victim - A mob who just got something stuck in their hand.
*/
/datum/traitor_objective/demoralise/poster/proc/on_triggered_trap(datum/source, mob/victim)
SIGNAL_HANDLER
on_mood_event(victim.mind)

/**
* Handles a poster being destroyed, increasing your progress towards failure.
*
* Arguments
* * poster - A poster which someone just ripped up.
*/
/datum/traitor_objective/demoralise/poster/proc/on_poster_destroy(obj/structure/sign/poster/traitor/poster)
SIGNAL_HANDLER
posters.Remove(poster)
UnregisterSignal(poster, COMSIG_DEMORALISING_EVENT)
if (length(posters) <= 0)
to_chat(handler.owner, span_warning("The trackers on your propaganda posters have stopped responding."))
fail_objective(penalty_cost = telecrystal_penalty)

/obj/item/poster/traitor
name = "random traitor poster"
poster_type = /obj/structure/sign/poster/traitor/random
Expand Down
11 changes: 11 additions & 0 deletions code/game/objects/items/storage/uplink_kits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,17 @@
to_chat(target, span_userdanger("You're no longer identified as a nuclear operative! You are free to follow any valid goals you wish, even continuing to secure the disk. Just make sure neither any turrets nor operatives kill you on sight."))
return TRUE

/obj/item/storage/box/syndie_kit/poster_box
name = "syndicate poster pack"
desc = "Contains a variety of demotivational posters to ensure minimum productivity for the crew of any Nanotrasen station."

/// Number of posters this box contains when spawning.
var/poster_count = 3

/obj/item/storage/box/syndie_kit/poster_box/PopulateContents()
for(var/i in 1 to poster_count)
new /obj/item/poster/traitor(src)

#undef KIT_RECON
#undef KIT_BLOODY_SPAI
#undef KIT_STEALTHY
Expand Down
Loading

0 comments on commit 2d4d23d

Please sign in to comment.