Files
Bubberstation/code/modules/admin/verbs/ert.dm
SkyratBot d086ca70e5 [MIRROR] Items in your hands can catch fire (#28247)
* Items in your hands can catch fire (#83867)

## About The Pull Request

Recently we allowed items held in your hands to catch fire if you catch
fire.
This makes sense but the code had a few oversights, then we reverted it.

This PR reintroduces the feature, but with a few refinements.
The basic feature is simple: If you are on fire then items you are
holding will also catch fire, in the same vein as items you are wearing
on your head or hands.

There are also a few caveats we forgot about the first time we added
this:

- If your gloves cannot catch fire, your held items will not catch fire
(because your hands aren't on fire).
- If you are extinguished, your held items will also be extinguished.
- Stopping, Dropping, and Rolling on top of any items will also
extinguish those items.

As part of this change, after an argument about whether or not this is
an oversight in coding-general, I've made the proc `get_equipped_items`
take a bitflag instead of a series of booleans as an argument and added
a new one for "include held items", so that we need no longer argue
about whether holding something counts as "equipping" it (in all other
parts of the game than this proc, it does). This is what gives the PR
most of its code footprint, don't be scared.

## Why It's Good For The Game

Items you are holding in your hands _should_ catch fire if everything
else on your person is on fire, and taking an item off of your body to
put it in your hands shouldn't protect it from fire, because those
things don't make intuitive sense.
If we want an item to be able to catch fire when worn, then it should do
so.

This might expose some issues where we were improperly setting the
flammability flags on items, but any weapon which will burn in your
hands now would also have burned if you were wearing it on your belt or
back, so making those issues more visible should be a bonus (we'll also
stop them from burning on your back or belt).

If you see someone holding a piece of paper that you really don't want
them to read you can now set them on fire to stop them from reading it,
whereas previously they would deftly hold the very flammable object out
of reach of their flaming body.

## Changelog

🆑
balance: Items held in your hands can catch fire.
balance: Items you are holding won't catch fire if your hands cannot
catch fire.
balance: When you stop being on fire so will items you are holding.
balance: If you roll around on your burning items they will stop being
on fire.
/🆑

* Items in your hands can catch fire

---------

Co-authored-by: Jacquerel <hnevard@gmail.com>
2024-06-19 10:03:45 +05:30

283 lines
12 KiB
Plaintext

/// If we spawn an ERT with the "choose experienced leader" option, select the leader from the top X playtimes
#define ERT_EXPERIENCED_LEADER_CHOOSE_TOP 3
///Dummy mob reserve slot for admin use
#define DUMMY_HUMAN_SLOT_ADMIN "admintools"
// CENTCOM RESPONSE TEAM
/datum/admins/proc/makeERTTemplateModified(list/settings)
. = settings
var/datum/ert/newtemplate = settings["mainsettings"]["template"]["value"]
if (isnull(newtemplate))
return
if (!ispath(newtemplate))
newtemplate = text2path(newtemplate)
newtemplate = new newtemplate
.["mainsettings"]["teamsize"]["value"] = newtemplate.teamsize
.["mainsettings"]["mission"]["value"] = newtemplate.mission
.["mainsettings"]["polldesc"]["value"] = newtemplate.polldesc
.["mainsettings"]["open_armory"]["value"] = newtemplate.opendoors ? "Yes" : "No"
.["mainsettings"]["leader_experience"]["value"] = newtemplate.leader_experience ? "Yes" : "No"
.["mainsettings"]["random_names"]["value"] = newtemplate.random_names ? "Yes" : "No"
.["mainsettings"]["spawn_admin"]["value"] = newtemplate.spawn_admin ? "Yes" : "No"
.["mainsettings"]["use_custom_shuttle"]["value"] = newtemplate.use_custom_shuttle ? "Yes" : "No"
/datum/admins/proc/equipAntagOnDummy(mob/living/carbon/human/dummy/mannequin, datum/antagonist/antag)
for(var/I in mannequin.get_equipped_items(INCLUDE_POCKETS))
qdel(I)
if (ispath(antag, /datum/antagonist/ert))
var/datum/antagonist/ert/ert = antag
mannequin.equipOutfit(initial(ert.outfit), TRUE)
/datum/admins/proc/makeERTPreviewIcon(list/settings)
// Set up the dummy for its photoshoot
var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy(DUMMY_HUMAN_SLOT_ADMIN)
var/prefs = settings["mainsettings"]
var/datum/ert/template = prefs["template"]["value"]
if (isnull(template))
return null
if (!ispath(template))
template = text2path(prefs["template"]["value"]) // new text2path ... doesn't compile in 511
template = new template
var/datum/antagonist/ert/ert = template.leader_role
equipAntagOnDummy(mannequin, ert)
CHECK_TICK
var/icon/preview_icon = icon('icons/effects/effects.dmi', "nothing")
preview_icon.Scale(48+32, 16+32)
CHECK_TICK
mannequin.setDir(NORTH)
var/icon/stamp = getFlatIcon(mannequin)
CHECK_TICK
preview_icon.Blend(stamp, ICON_OVERLAY, 25, 17)
CHECK_TICK
mannequin.setDir(WEST)
stamp = getFlatIcon(mannequin)
CHECK_TICK
preview_icon.Blend(stamp, ICON_OVERLAY, 1, 9)
CHECK_TICK
mannequin.setDir(SOUTH)
stamp = getFlatIcon(mannequin)
CHECK_TICK
preview_icon.Blend(stamp, ICON_OVERLAY, 49, 1)
CHECK_TICK
preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
CHECK_TICK
unset_busy_human_dummy(DUMMY_HUMAN_SLOT_ADMIN)
return preview_icon
/datum/admins/proc/makeEmergencyresponseteam(datum/ert/ertemplate = null)
if (ertemplate)
ertemplate = new ertemplate
else
ertemplate = new /datum/ert/centcom_official
var/list/settings = list(
"preview_callback" = CALLBACK(src, PROC_REF(makeERTPreviewIcon)),
"mainsettings" = list(
"template" = list("desc" = "Template", "callback" = CALLBACK(src, PROC_REF(makeERTTemplateModified)), "type" = "datum", "path" = "/datum/ert", "subtypesonly" = TRUE, "value" = ertemplate.type),
"teamsize" = list("desc" = "Team Size", "type" = "number", "value" = ertemplate.teamsize),
"mission" = list("desc" = "Mission", "type" = "string", "value" = ertemplate.mission),
"polldesc" = list("desc" = "Ghost poll description", "type" = "string", "value" = ertemplate.polldesc),
"enforce_human" = list("desc" = "Enforce human authority", "type" = "boolean", "value" = "[(CONFIG_GET(flag/enforce_human_authority) ? "Yes" : "No")]"),
"open_armory" = list("desc" = "Open armory doors", "type" = "boolean", "value" = "[(ertemplate.opendoors ? "Yes" : "No")]"),
"leader_experience" = list("desc" = "Pick an experienced leader", "type" = "boolean", "value" = "[(ertemplate.leader_experience ? "Yes" : "No")]"),
"random_names" = list("desc" = "Randomize names", "type" = "boolean", "value" = "[(ertemplate.random_names ? "Yes" : "No")]"),
"spawn_admin" = list("desc" = "Spawn yourself as briefing officer", "type" = "boolean", "value" = "[(ertemplate.spawn_admin ? "Yes" : "No")]"),
"notify_players" = list("desc" = "Notify players that you have sent an ERT", "type" = "boolean", "value" = "[(ertemplate.notify_players ? "Yes" : "No")]"), //SKYRAT EDIT ADDITION
"use_custom_shuttle" = list("desc" = "Use the ERT's custom shuttle (if it has one)", "type" = "boolean", "value" = "[(ertemplate.use_custom_shuttle ? "Yes" : "No")]"),
)
)
var/list/prefreturn = presentpreflikepicker(usr, "Customize ERT", "Customize ERT", Button1="Ok", width = 600, StealFocus = 1,Timeout = 0, settings=settings)
if (isnull(prefreturn))
return FALSE
if (prefreturn["button"] == 1)
var/list/prefs = settings["mainsettings"]
var/templtype = prefs["template"]["value"]
if (!ispath(prefs["template"]["value"]))
templtype = text2path(prefs["template"]["value"]) // new text2path ... doesn't compile in 511
if (ertemplate.type != templtype)
ertemplate = new templtype
ertemplate.teamsize = prefs["teamsize"]["value"]
ertemplate.mission = prefs["mission"]["value"]
ertemplate.polldesc = prefs["polldesc"]["value"]
ertemplate.enforce_human = prefs["enforce_human"]["value"] == "Yes" // these next 6 are effectively toggles
ertemplate.opendoors = prefs["open_armory"]["value"] == "Yes"
ertemplate.leader_experience = prefs["leader_experience"]["value"] == "Yes"
ertemplate.random_names = prefs["random_names"]["value"] == "Yes"
ertemplate.spawn_admin = prefs["spawn_admin"]["value"] == "Yes"
ertemplate.notify_players = prefs["notify_players"]["value"] == "Yes" //SKYRAT EDIT ADDITION
ertemplate.use_custom_shuttle = prefs["use_custom_shuttle"]["value"] == "Yes"
var/list/spawnpoints = GLOB.emergencyresponseteamspawn
var/index = 0
var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for [span_notice(ertemplate.polldesc)]?", check_jobban = "deathsquad", alert_pic = /obj/item/card/id/advanced/centcom/ert, role_name_text = "emergency response team")
var/teamSpawned = FALSE
// This list will take priority over spawnpoints if not empty
var/list/spawn_turfs = list()
// Takes precedence over spawnpoints[1] if not null
var/turf/brief_spawn
if(!length(candidates))
return FALSE
if(ertemplate.use_custom_shuttle && ertemplate.ert_template)
to_chat(usr, span_boldnotice("Attempting to spawn ERT custom shuttle, this may take a few seconds..."))
var/datum/map_template/shuttle/ship = new ertemplate.ert_template
var/x = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE - ship.width)
var/y = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE - ship.height)
var/z = SSmapping.empty_space.z_value
var/turf/located_turf = locate(x, y, z)
if(!located_turf)
CRASH("ERT shuttle found no place to load in")
if(!ship.load(located_turf))
CRASH("Loading ERT shuttle failed!")
var/list/shuttle_turfs = ship.get_affected_turfs(located_turf)
for(var/turf/affected_turf as anything in shuttle_turfs)
for(var/obj/effect/landmark/ert_shuttle_spawn/spawner in affected_turf)
spawn_turfs += get_turf(spawner)
if(!brief_spawn)
brief_spawn = locate(/obj/effect/landmark/ert_shuttle_brief_spawn) in affected_turf
if(!length(spawn_turfs))
stack_trace("ERT shuttle loaded but found no spawnpoints, placing the ERT at wherever inside the shuttle instead.")
for(var/turf/open/floor/open_turf in shuttle_turfs)
if(!is_safe_turf(open_turf))
continue
spawn_turfs += open_turf
if(ertemplate.spawn_admin)
if(isobserver(usr))
var/mob/living/carbon/human/admin_officer = new (brief_spawn || spawnpoints[1])
var/chosen_outfit = usr.client?.prefs?.read_preference(/datum/preference/choiced/brief_outfit)
usr.client.prefs.safe_transfer_prefs_to(admin_officer, is_antag = TRUE)
admin_officer.equipOutfit(chosen_outfit)
admin_officer.key = usr.key
else
to_chat(usr, span_warning("Could not spawn you in as briefing officer as you are not a ghost!"))
//Pick the (un)lucky players
var/numagents = min(ertemplate.teamsize, length(candidates))
//Create team
var/datum/team/ert/ert_team = new ertemplate.team()
if(ertemplate.rename_team)
ert_team.name = ertemplate.rename_team
//Assign team objective
var/datum/objective/missionobj = new ()
missionobj.team = ert_team
missionobj.explanation_text = ertemplate.mission
missionobj.completed = TRUE
ert_team.objectives += missionobj
ert_team.mission = missionobj
var/mob/dead/observer/earmarked_leader
var/leader_spawned = FALSE // just in case the earmarked leader disconnects or becomes unavailable, we can try giving leader to the last guy to get chosen
if(ertemplate.leader_experience)
var/list/candidate_living_exps = list()
for(var/i in candidates)
var/mob/dead/observer/potential_leader = i
candidate_living_exps[potential_leader] = potential_leader.client?.get_exp_living(TRUE)
candidate_living_exps = sort_list(candidate_living_exps, cmp=/proc/cmp_numeric_dsc)
if(candidate_living_exps.len > ERT_EXPERIENCED_LEADER_CHOOSE_TOP)
candidate_living_exps = candidate_living_exps.Cut(ERT_EXPERIENCED_LEADER_CHOOSE_TOP+1) // pick from the top ERT_EXPERIENCED_LEADER_CHOOSE_TOP contenders in playtime
earmarked_leader = pick(candidate_living_exps)
else
earmarked_leader = pick(candidates)
while(numagents && candidates.len)
var/turf/spawnloc
if(length(spawn_turfs))
spawnloc = pick(spawn_turfs)
else
spawnloc = spawnpoints[index+1]
//loop through spawnpoints one at a time
index = (index + 1) % spawnpoints.len
var/mob/dead/observer/chosen_candidate = earmarked_leader || pick(candidates) // this way we make sure that our leader gets chosen
candidates -= chosen_candidate
if(!chosen_candidate?.key)
continue
//Spawn the body
var/mob/living/carbon/human/ert_operative = new ertemplate.mobtype(spawnloc)
chosen_candidate.client.prefs.safe_transfer_prefs_to(ert_operative, is_antag = TRUE)
ert_operative.key = chosen_candidate.key
if(ertemplate.enforce_human || !(ert_operative.dna.species.changesource_flags & ERT_SPAWN)) // Don't want any exploding plasmemes
ert_operative.set_species(/datum/species/human)
//Give antag datum
var/datum/antagonist/ert/ert_antag
if((chosen_candidate == earmarked_leader) || (numagents == 1 && !leader_spawned))
ert_antag = new ertemplate.leader_role ()
earmarked_leader = null
leader_spawned = TRUE
else
ert_antag = ertemplate.roles[WRAP(numagents,1,length(ertemplate.roles) + 1)]
ert_antag = new ert_antag ()
ert_antag.random_names = ertemplate.random_names
ert_operative.mind.add_antag_datum(ert_antag,ert_team)
ert_operative.mind.set_assigned_role(SSjob.GetJobType(ert_antag.ert_job_path))
//Logging and cleanup
ert_operative.log_message("has been selected as \a [ert_antag.name].", LOG_GAME)
numagents--
teamSpawned++
if (teamSpawned)
message_admins("[ertemplate.polldesc] has spawned with the mission: [ertemplate.mission]")
//SKYRAT EDIT ADDITION BEGIN
if(ertemplate.notify_players)
priority_announce("Central command has responded to your request for a CODE [uppertext(ertemplate.code)] Emergency Response Team and have confirmed one to be enroute.", "ERT Request", ANNOUNCER_ERTYES)
// shitcode begin!
if(istype(ertemplate, /datum/ert/deathsquad))
SSsecurity_level.set_level(SEC_LEVEL_EPSILON)
//SKYRAT EDIT END
//Open the Armory doors
if(ertemplate.opendoors)
for(var/obj/machinery/door/poddoor/ert/door as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/poddoor/ert))
door.open()
CHECK_TICK
return TRUE
return
ADMIN_VERB(summon_ert, R_FUN, "Summon ERT", "Summons an emergency response team.", ADMIN_CATEGORY_FUN)
message_admins("[key_name_admin(user)] is creating a CentCom response team...")
if(user.holder?.makeEmergencyresponseteam())
message_admins("[key_name_admin(user)] created a CentCom response team.")
log_admin("[key_name(user)] created a CentCom response team.")
else
message_admins("[key_name_admin(user)] tried to create a CentCom response team. Unfortunately, there were not enough candidates available.")
log_admin("[key_name(user)] failed to create a CentCom response team.")
#undef ERT_EXPERIENCED_LEADER_CHOOSE_TOP
#undef DUMMY_HUMAN_SLOT_ADMIN