From 6aa646c2d7cb345abfddc8f05474668cc983c032 Mon Sep 17 00:00:00 2001 From: Da Cool Boss <142358580+DaCoolBoss@users.noreply.github.com> Date: Fri, 5 Jul 2024 19:27:58 +0100 Subject: [PATCH] Cleans up relic code & adds new relic theme (#84511) ## About The Pull Request Cleaned up crusty old code and made it more readable, removed single letter variables, camel case, etc. Improved naming for strange objects. Unidentified objects are "Strange [thing]", activating the item replaces the word "strange" with a new prefix. Improved the list of strings. Added cosmetic themes for artefacts. All current strange objects are now "prototype" artefacts, reflecting their man-made origin in space. Artefacts with different themes pick from different sprite and name pools, reflecting who made them. New "necrotech" theme for relics. These are strange objects from lavaland. Instead of getting half-multitool-half-gun-blows-up-when-used monstrosities crafted by insane maint dwellers, you will now get strange relics that look like this. ![strange relics from boulders](https://i.imgur.com/Qr5uz6q.png) And they're called something like "ruined instrument" or "dark relic". ## Why It's Good For The Game Code needed cleaned up. It was in a bad state. Years of neglect. Themes add more flavour to these items. I really didn't like how the boulder machine looked when it produced lots of relics, so now it produces more appropriate ones. Lets admins and mappers use variable editing to decide what relics do and what cooldown they should have before they are activated. Previously, this would be overwritten when the relic was activated. ## Changelog :cl: code: Cleaned up relic code. image: Added necrotech themed relics. /:cl: --- code/modules/cargo/bounties/science.dm | 2 +- .../boulder_processing/boulder_types.dm | 2 +- code/modules/research/experimentor.dm | 153 +++++++++++------- icons/obj/devices/artefacts.dmi | Bin 0 -> 7695 bytes icons/obj/devices/artifacts.dmi | Bin 4936 -> 0 bytes 5 files changed, 97 insertions(+), 60 deletions(-) create mode 100644 icons/obj/devices/artefacts.dmi delete mode 100644 icons/obj/devices/artifacts.dmi diff --git a/code/modules/cargo/bounties/science.dm b/code/modules/cargo/bounties/science.dm index 67da7ad6b29..0206ea41967 100644 --- a/code/modules/cargo/bounties/science.dm +++ b/code/modules/cargo/bounties/science.dm @@ -9,7 +9,7 @@ if(!..()) return FALSE var/obj/item/relic/experiment = O - if(experiment.revealed) + if(experiment.activated) return TRUE return diff --git a/code/modules/mining/boulder_processing/boulder_types.dm b/code/modules/mining/boulder_processing/boulder_types.dm index 1ffce8737bd..8f6889b7c84 100644 --- a/code/modules/mining/boulder_processing/boulder_types.dm +++ b/code/modules/mining/boulder_processing/boulder_types.dm @@ -4,7 +4,7 @@ desc = "This boulder is brimming with strange energy. Cracking it open could contain something unusual for science." icon_state = "boulder_artifact" /// This is the type of item that will be inside the boulder. Default is a strange object. - var/artifact_type = /obj/item/relic + var/artifact_type = /obj/item/relic/lavaland /// References to the relic inside the boulder, if any. var/obj/item/artifact_inside diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index 4a08ae44df1..2d0ba7017d2 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -461,9 +461,9 @@ if(exp == SCANTYPE_DISCOVER) visible_message(span_notice("[src] scans the [exp_on], revealing its true nature!")) playsound(src, 'sound/effects/supermatter.ogg', 50, 3, -1) - var/obj/item/relic/R = loaded_item - R.reveal() - investigate_log("Experimentor has revealed a relic with [span_danger("[R.realProc]")] effect.", INVESTIGATE_EXPERIMENTOR) + var/obj/item/relic/loaded_artifact = loaded_item + loaded_artifact.reveal() + investigate_log("Experimentor has revealed a relic with [span_danger("[loaded_artifact.hidden_power]")] effect.", INVESTIGATE_EXPERIMENTOR) ejectItem() //Global reactions @@ -553,34 +553,74 @@ #undef FAIL -//////////////////////////////////SPECIAL ITEMS//////////////////////////////////////// +// Relic \\ /obj/item/relic name = "strange object" desc = "What mysteries could this hold? Maybe Research & Development could find out." - icon = 'icons/obj/devices/artifacts.dmi' - var/realName = "defined object" - var/revealed = FALSE - var/realProc - var/reset_timer = 60 + icon = 'icons/obj/devices/artefacts.dmi' + icon_state = "debug_artefact" + //The name this artefact will have when it's activated. + var/real_name = "artefact" + //Has this artefact been activated? + var/activated = FALSE + //What effect this artefact has when used. Randomly determined when activated. + var/hidden_power + //Minimum possible cooldown. + var/min_cooldown = 6 SECONDS + //Max possible cooldown. + var/max_cooldown = 30 SECONDS + //Cooldown length. Randomly determined at activation if it isn't determined here. + var/cooldown_timer COOLDOWN_DECLARE(cooldown) + //What visual theme this artefact has. Current possible choices: "prototype", "necrotech" + var/artifact_theme = "prototype" /obj/item/relic/Initialize(mapload) . = ..() - icon_state = pick("prototype1","prototype2","prototype3","prototype4","prototype5","prototype6","prototype7","prototype8","prototype9") - realName = "[pick("broken","twisted","spun","improved","silly","regular","badly made")] [pick("device","object","toy","illegal tech","weapon")]" + random_themed_appearance() +/obj/item/relic/proc/random_themed_appearance() + var/themed_name_prefix + var/themed_name_suffix + if(artifact_theme == "prototype") + icon_state = pick("prototype1", "prototype2", "prototype3", "prototype4", "prototype5", "prototype6", "prototype7", "prototype8","prototype9") + themed_name_prefix = pick("experimental","prototype","artificial","handcrafted","ramshackle","odd") + themed_name_suffix = pick("device","assembly","gadget","gizmo","contraption","machine","widget","object") + real_name = "[pick(themed_name_prefix)] [pick(themed_name_suffix)]" + name = "strange [pick(themed_name_suffix)]" + if(artifact_theme == "necrotech") + icon_state = pick("necrotech1", "necrotech2", "necrotech3", "necrotech4", "necrotech5", "necrotech6") + themed_name_prefix = pick("dark","bloodied","unholy","archeotechnological","dismal","ruined","thrumming") + themed_name_suffix = pick("instrument","shard","fetish","bibelot","trinket","offering","relic") + real_name = "[pick(themed_name_prefix)] [pick(themed_name_suffix)]" + name = "strange relic" + update_appearance() + +/obj/item/relic/lavaland + name = "strange relic" + artifact_theme = "necrotech" /obj/item/relic/proc/reveal() - if(revealed) //Re-rolling your relics seems a bit overpowered, yes? + if(activated) //no rerolling return - revealed = TRUE - name = realName - reset_timer = rand(reset_timer, reset_timer * 5) - realProc = pick(PROC_REF(teleport), PROC_REF(explode), PROC_REF(rapidDupe), PROC_REF(petSpray), PROC_REF(flash), PROC_REF(clean), PROC_REF(corgicannon)) + activated = TRUE + name = real_name + if(!cooldown_timer) + cooldown_timer = rand(min_cooldown, max_cooldown) + if(!hidden_power) + hidden_power = pick( + PROC_REF(corgi_cannon), + PROC_REF(cleaning_foam), + PROC_REF(flashbanger), + PROC_REF(summon_animals), + PROC_REF(uncontrolled_teleport), + PROC_REF(heat_and_explode), + PROC_REF(rapid_self_dupe), + ) /obj/item/relic/attack_self(mob/user) - if(!revealed) + if(!activated) to_chat(user, span_notice("You aren't quite sure what this is. Maybe R&D knows what to do with it?")) return if(!COOLDOWN_FINISHED(src, cooldown)) @@ -588,40 +628,39 @@ return if(loc != user) return - COOLDOWN_START(src, cooldown, reset_timer) - call(src,realProc)(user) + COOLDOWN_START(src, cooldown, cooldown_timer) + call(src, hidden_power)(user) -//////////////// RELIC PROCS ///////////////////////////// - -/obj/item/relic/proc/throwSmoke(turf/where) +/obj/item/relic/proc/throw_smoke(turf/where) var/datum/effect_system/fluid_spread/smoke/smoke = new smoke.set_up(0, holder = src, location = get_turf(where)) smoke.start() -/obj/item/relic/proc/corgicannon(mob/user) +// Artefact Powers \\ + +/obj/item/relic/proc/corgi_cannon(mob/user) playsound(src, SFX_SPARKS, rand(25,50), TRUE, SHORT_RANGE_SOUND_EXTRARANGE) var/mob/living/basic/pet/dog/corgi/sad_corgi = new(get_turf(user)) - sad_corgi.throw_at(pick(oview(10,user)), 10, rand(3,8), callback = CALLBACK(src, PROC_REF(throwSmoke), sad_corgi)) + sad_corgi.throw_at(pick(oview(10,user)), 10, rand(3,8), callback = CALLBACK(src, PROC_REF(throw_smoke), sad_corgi)) warn_admins(user, "Corgi Cannon", 0) -/obj/item/relic/proc/clean(mob/user) +/obj/item/relic/proc/cleaning_foam(mob/user) playsound(src, SFX_SPARKS, rand(25,50), TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - var/obj/item/grenade/chem_grenade/cleaner/CL = new/obj/item/grenade/chem_grenade/cleaner(get_turf(user)) - CL.detonate() - qdel(CL) + var/obj/item/grenade/chem_grenade/cleaner/spawned_foamer = new/obj/item/grenade/chem_grenade/cleaner(get_turf(user)) + spawned_foamer.detonate() + qdel(spawned_foamer) warn_admins(user, "Foam", 0) -/obj/item/relic/proc/flash(mob/user) +/obj/item/relic/proc/flashbanger(mob/user) playsound(src, SFX_SPARKS, rand(25,50), TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - var/obj/item/grenade/flashbang/CB = new/obj/item/grenade/flashbang(user.loc) - CB.detonate() + var/obj/item/grenade/flashbang/spawned_flashbang = new/obj/item/grenade/flashbang(user.loc) + spawned_flashbang.detonate() warn_admins(user, "Flash") -/obj/item/relic/proc/petSpray(mob/user) +/obj/item/relic/proc/summon_animals(mob/user) var/message = span_danger("[src] begins to shake, and in the distance the sound of rampaging animals arises!") visible_message(message) to_chat(user, message) - var/static/list/valid_animals = list( /mob/living/basic/bear, /mob/living/basic/bee, @@ -637,42 +676,40 @@ /mob/living/basic/pet/fox, ) for(var/counter in 1 to rand(1, 25)) - var/mobType = pick(valid_animals) - new mobType(get_turf(src)) - + var/animal_spawn = pick(valid_animals) + new animal_spawn(get_turf(src)) warn_admins(user, "Mass Mob Spawn") if(prob(60)) to_chat(user, span_warning("[src] falls apart!")) qdel(src) -/obj/item/relic/proc/rapidDupe(mob/user) +/obj/item/relic/proc/rapid_self_dupe(mob/user) audible_message("[src] emits a loud pop!") - var/list/dupes = list() + var/list/dummy_artifacts = list() for(var/counter in 1 to rand(5,10)) - var/obj/item/relic/R = new type(get_turf(src)) - R.name = name - R.desc = desc - R.realName = realName - R.realProc = realProc - R.revealed = TRUE - dupes += R - R.throw_at(pick(oview(7,get_turf(src))),10,1) - - QDEL_LIST_IN(dupes, rand(10, 100)) + var/obj/item/relic/duped = new type(get_turf(src)) + duped.name = name + duped.desc = desc + duped.real_name = real_name + duped.hidden_power = hidden_power + duped.activated = TRUE + dummy_artifacts += duped + duped.throw_at(pick(oview(7,get_turf(src))),10,1) + QDEL_LIST_IN(dummy_artifacts, rand(1 SECONDS, 10 SECONDS)) warn_admins(user, "Rapid duplicator", 0) -/obj/item/relic/proc/explode(mob/user) +/obj/item/relic/proc/heat_and_explode(mob/user) to_chat(user, span_danger("[src] begins to heat up!")) - addtimer(CALLBACK(src, PROC_REF(do_explode), user), rand(3.5 SECONDS, 10 SECONDS)) + addtimer(CALLBACK(src, PROC_REF(blow_up), user), rand(3.5 SECONDS, 10 SECONDS)) -/obj/item/relic/proc/do_explode(mob/user) +/obj/item/relic/proc/blow_up(mob/user) if(loc == user) visible_message(span_notice("\The [src]'s top opens, releasing a powerful blast!")) explosion(src, heavy_impact_range = rand(1,5), light_impact_range = rand(1,5), flame_range = 2, flash_range = rand(1,5), adminlog = TRUE) warn_admins(user, "Explosion") qdel(src) //Comment this line to produce a light grenade (the bomb that keeps on exploding when used)!! -/obj/item/relic/proc/teleport(mob/user) +/obj/item/relic/proc/uncontrolled_teleport(mob/user) to_chat(user, span_notice("[src] begins to vibrate!")) addtimer(CALLBACK(src, PROC_REF(do_the_teleport), user), rand(1 SECONDS, 3 SECONDS)) @@ -680,16 +717,16 @@ var/turf/userturf = get_turf(user) if(loc == user && !is_centcom_level(userturf.z)) //Because Nuke Ops bringing this back on their shuttle, then looting the ERT area is 2fun4you! visible_message(span_notice("[src] twists and bends, relocating itself!")) - throwSmoke(userturf) + throw_smoke(userturf) do_teleport(user, userturf, 8, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) - throwSmoke(get_turf(user)) + throw_smoke(get_turf(user)) warn_admins(user, "Teleport", 0) //Admin Warning proc for relics -/obj/item/relic/proc/warn_admins(mob/user, RelicType, priority = 1) - var/turf/T = get_turf(src) - var/log_msg = "[RelicType] relic used by [key_name(user)] in [AREACOORD(T)]" +/obj/item/relic/proc/warn_admins(mob/user, relic_type, priority = 1) + var/turf/location = get_turf(src) + var/log_msg = "[relic_type] relic used by [key_name(user)] in [AREACOORD(location)]" if(priority) //For truly dangerous relics that may need an admin's attention. BWOINK! - message_admins("[RelicType] relic activated by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]") + message_admins("[relic_type] relic activated by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(location)]") log_game(log_msg) investigate_log(log_msg, "experimentor") diff --git a/icons/obj/devices/artefacts.dmi b/icons/obj/devices/artefacts.dmi new file mode 100644 index 0000000000000000000000000000000000000000..75a6f754fbbeda47a669df334fc60681c9129cf5 GIT binary patch literal 7695 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 b{)M1`Tm^N};&;-oF+f{gU#&{j{^frGf-G_-