This commit is contained in:
Metis
2024-11-15 00:21:13 -05:00
parent 73023562d6
commit 22ec293d45
8 changed files with 320 additions and 1 deletions
@@ -0,0 +1,24 @@
/mob/living/proc/get_tf_component()
var/obj/item/item_loc = loc
if(!istype(item_loc))
return FALSE
var/datum/component/transformation_item/transformation_component = item_loc.GetComponent(/datum/component/transformation_item)
if(!istype(transformation_component) || (transformation_component.transformed_mob != src))
return FALSE
return transformation_component
/mob/living/proc/handle_transformation_ooc_escape()
var/datum/component/transformation_item/transformation_component = get_tf_component()
if(!transformation_component)
return FALSE
qdel(transformation_component)
return TRUE
/mob/living/proc/attempt_to_escape_tf()
var/datum/component/transformation_item/transformation_component = get_tf_component()
if(!transformation_component)
return FALSE
@@ -0,0 +1,103 @@
/datum/component/transformation_item
/// What mob do we currently have stuck in us?
var/mob/living/transformed_mob
/// Do we release the mob when the parent item is destroyed?
var/release_mob = TRUE
/// Is the mob able to speak as the item?
var/able_to_speak = FALSE
/// Is the mob able to emote as the item?
var/able_to_emote = FALSE
/// Does the object scale with the sprite size of the mob inside of it?
var/scale_object = TRUE
/// Show custom description.
var/show_that_object_is_tf = TRUE
/// Stored real name
var/stored_real_name = ""
/// Stored name
var/stored_name = ""
/// Is the component able to be removed?
var/stuck_on_item = FALSE
/// Is the person able to struggle out?
var/able_to_struggle_out = TRUE
/datum/component/transformation_item/Initialize()
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(examine))
RegisterSignal(parent, COMSIG_PARENT_QDELETING, PROC_REF(remove_mob))
/datum/component/transformation_item/Destroy(force, silent)
remove_mob()
return ..()
/datum/component/transformation_item/proc/examine(datum/source, mob/user, list/examine_list)
if(show_that_object_is_tf)
examine_list += span_notice("Something about [source] seems lifelike.")
/datum/component/transformation_item/proc/register_mob(mob/living/mob_to_register)
var/atom/parent_atom = parent
if(!istype(mob_to_register))
return FALSE
transformed_mob = mob_to_register
stored_real_name = mob_to_register.real_name
stored_name = mob_to_register.name
// This is really dumb, but if it works, then maybe it is not dumb.
mob_to_register.real_name = parent_atom.name
mob_to_register.name = parent_atom.name
ADD_TRAIT(mob_to_register, TRAIT_TRANSFORMED, src)
ADD_TRAIT(mob_to_register, TRAIT_RESISTCOLD, src)
ADD_TRAIT(mob_to_register, TRAIT_RESISTLOWPRESSURE, src)
ADD_TRAIT(mob_to_register, TRAIT_LOWPRESSURECOOLING, src)
if(!able_to_speak)
ADD_TRAIT(mob_to_register, TRAIT_MUTE, src)
if(!able_to_emote)
ADD_TRAIT(mob_to_register, TRAIT_EMOTEMUTE, src)
// need to stop them from using radio headsets.
var/mob/living/carbon/human/human_mob = mob_to_register
if(istype(human_mob))
ADD_TRAIT(mob_to_register, TRAIT_PARALYSIS_L_ARM, src)
ADD_TRAIT(mob_to_register, TRAIT_PARALYSIS_R_ARM, src)
human_mob.update_disabled_bodyparts()
mob_to_register.forceMove(parent_atom)
if(scale_object)
var/target_size = mob_to_register.size_multiplier
var/matrix/new_matrix = new
new_matrix.Scale(target_size)
new_matrix.Translate(0,16 * (target_size-1))
parent_atom.transform = new_matrix
/datum/component/transformation_item/proc/remove_mob()
if(!release_mob || !transformed_mob)
return FALSE
transformed_mob.real_name = stored_real_name
transformed_mob.name = stored_name
if(!able_to_speak)
REMOVE_TRAIT(transformed_mob, TRAIT_MUTE, src)
if(!able_to_emote)
REMOVE_TRAIT(transformed_mob, TRAIT_EMOTEMUTE, src)
REMOVE_TRAIT(transformed_mob, TRAIT_TRANSFORMED, src)
REMOVE_TRAIT(transformed_mob, TRAIT_RESISTCOLD, src)
REMOVE_TRAIT(transformed_mob, TRAIT_RESISTLOWPRESSURE, src)
REMOVE_TRAIT(transformed_mob, TRAIT_LOWPRESSURECOOLING, src)
var/mob/living/carbon/human/human_mob = transformed_mob
if(istype(human_mob))
REMOVE_TRAIT(human_mob, TRAIT_PARALYSIS_L_ARM, src)
REMOVE_TRAIT(human_mob, TRAIT_PARALYSIS_R_ARM, src)
human_mob.update_disabled_bodyparts()
var/atom/parent_atom = parent
transformed_mob.forceMove(parent_atom.loc)
if(scale_object)
parent_atom.transform = null
@@ -0,0 +1,113 @@
/obj/item/transformation_item
name = "Handheld Transmogrifier"
desc = "a handheld device that is mysteriously able to turn people into objects. It can also be used to remove said transformations."
icon = 'icons/obj/abductor.dmi'
icon_state = "gizmo_scan"
item_state = "silencer"
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
/// What item are we wanting to TF people into?
var/obj/item/target_item
/// Do we want our transformed person to be able to speak as the object?
var/able_to_speak = TRUE
/// Do we want our transformed person to be able to emote as the object?
var/able_to_emote = TRUE
/// Do we want the item to scale?
var/scale_object = FALSE
/// Do we want to show that the object was once a person?
var/show_that_object_is_tf = TRUE
/// Is our captured person able to struggle out?
var/able_to_struggle_out = TRUE
/// Do we have any items we can't turn people into?
var/list/object_blacklist = list()
/obj/item/transformation_item/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
var/obj/item/attacked_item = target
if(!proximity_flag || !istype(attacked_item))
return FALSE
var/datum/component/transformation_item/transformation_component = attacked_item.GetComponent(/datum/component/transformation_item)
if(istype(transformation_component) && !transformation_component.stuck_on_item)
qdel(transformation_component)
to_chat(user, span_notice("You dispel the current transformation for [attacked_item]."))
return
target_item = attacked_item
to_chat(user, span_notice("The next time someone is transformed, they will be transformed into [attacked_item]."))
return
/obj/item/transformation_item/attack(mob/living/M, mob/living/user)
if(!target_item)
to_chat(user, span_warning("You need to have an item linked to transform someone."))
return
perform_transfomration(M, user)
return
/obj/item/transformation_item/proc/perform_transfomration(mob/living/target_mob, mob/living/user)
if(!istype(target_mob))
return FALSE
if(!target_item.Adjacent(target_mob))
to_chat(user, span_warning("The [target_item] isn't close enough to [target_mob]"))
return FALSE
if(target_item in target_mob.get_contents())
return FALSE // Don't TF someone into something they are holding.
// You'll want to check prefs here.
var/datum/component/transformation_item/transformation_component = target_item.AddComponent(/datum/component/transformation_item)
// Make sure that we apply our variables before we actually put the mob in the item.
transformation_component.able_to_speak = able_to_speak
transformation_component.able_to_emote = able_to_emote
transformation_component.scale_object = scale_object
transformation_component.show_that_object_is_tf = show_that_object_is_tf
transformation_component.able_to_struggle_out = able_to_struggle_out
transformation_component.register_mob(target_mob)
target_item = null
return TRUE
/obj/item/transformation_item/ui_data(mob/user)
var/list/data = list()
data["able_to_speak"] = able_to_speak
data["able_to_emote"] = able_to_emote
data["scale_object"] = scale_object
data["show_that_object_is_tf"] = show_that_object_is_tf
data["linked_item_name"] = target_item
data["able_to_struggle_out"] = able_to_struggle_out
return data
/obj/item/transformation_item/ui_act(action, params)
if(..())
return
switch(action)
if("set_speaking")
able_to_speak = !able_to_speak
. = TRUE
if("set_emote")
able_to_emote = !able_to_emote
. = TRUE
if("set_scale")
scale_object = !scale_object
. = TRUE
if("toggle_struggle")
able_to_struggle_out = !able_to_struggle_out
. = TRUE
if("set_show_desc")
show_that_object_is_tf = !show_that_object_is_tf
. = TRUE
/obj/item/transformation_item/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TransformTool", name)
ui.open()
+1
View File
@@ -295,6 +295,7 @@
#define TRAIT_HEAT "heat"
#define TRAIT_DISTANT "headpat_hater"
#define TRAIT_CUM_PLUS "cum_plus"
#define TRAIT_TRANSFORMED "transformed"
// mobility flag traits
// IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it)
+4
View File
@@ -820,6 +820,10 @@
//Sure, give clickdelay for anti spam. shouldn't be combat voring anyways.
return TRUE
// GS13 Escape Transformation
if(attempt_to_escape_tf())
return TRUE
//Breaking out of a container (Locker, sleeper, cryo...)
if(isobj(loc))
var/obj/C = loc
+6 -1
View File
@@ -221,7 +221,12 @@
//
/mob/living/proc/escapeOOC()
set name = "OOC Escape"
set category = "Vore"
set category = "ERP" // GS13 Change
//GS13 EDIT START
handle_transformation_ooc_escape()
//GS13 EDIT END
//You're in a belly!
if(isbelly(loc))
+3
View File
@@ -3972,6 +3972,9 @@
#include "GainStation13\code\mechanics\web_weaving.dm"
#include "GainStation13\code\mechanics\den abductors\console.dm"
#include "GainStation13\code\mechanics\den abductors\purchaseble_goodies.dm"
#include "GainStation13\code\mechanics\transformation\mob_procs.dm"
#include "GainStation13\code\mechanics\transformation\transformation_component.dm"
#include "GainStation13\code\mechanics\transformation\transformation_item.dm"
#include "GainStation13\code\mobs\cakegolem.dm"
#include "GainStation13\code\mobs\chocoslime.dm"
#include "GainStation13\code\mobs\eat_trash.dm"
@@ -0,0 +1,66 @@
import { useBackend } from '../backend';
import { Box, Button, LabeledList, NumberInput, Section } from '../components';
import { Window } from '../layouts';
export const TransformTool = (props, context) => {
const { act, data } = useBackend(context);
const {
able_to_speak,
able_to_emote,
scale_object,
show_that_object_is_tf,
linked_item_name,
able_to_struggle_out,
} = data;
return (
<Window
width={340}
height={280}>
<Window.Content>
<Section>
<Box textAlign="center" fontSize="16px">
<b>Current item:</b> {linked_item_name ? linked_item_name : "None"}
</Box>
<br />
<Button
fluid
color={able_to_speak ? 'green' : 'red'}
onClick={() => act('set_speaking', {})}>
Able to Speak: {able_to_speak ? "True" : "False"}
</Button>
<Button
fluid
color={able_to_emote ? 'green' : 'red'}
onClick={() => act('set_emote', {})}>
Able to Emote: {able_to_emote ? "True" : "False"}
</Button>
<Button
fluid
color={scale_object ? 'green' : 'red'}
onClick={() => act('set_scale', {})}>
Resize: {scale_object ? "True" : "False"}
</Button>
<Button
fluid
color={scale_object ? 'green' : 'red'}
onClick={() => act('toggle_struggle', {})}>
Able to struggle out: {able_to_struggle_out ? "True" : "False"}
</Button>
<Button
fluid
color={show_that_object_is_tf ? 'green' : 'red'}
onClick={() => act('set_show_desc', {})}>
Show examine text: {show_that_object_is_tf ? "True" : "False"}
</Button>
</Section>
</Window.Content>
</Window>
);
};