Merge pull request #20 from sheepishgoat/tf-mechanics

Object TF mechanics
This commit is contained in:
sheepishgoat
2024-11-15 01:22:07 -05:00
committed by GitHub
14 changed files with 365 additions and 1 deletions
@@ -0,0 +1,16 @@
/obj/item/reagent_containers/food/snacks/proc/handle_tf(mob/living/eater)
var/datum/component/transformation_item/transformation_component = GetComponent(/datum/component/transformation_item)
if(!istype(transformation_component) || transformation_component.transfer_to_vore || (transformation_component.transformed_mob != src))
return FALSE
var/mob/living/food_mob = transformation_component.transformed_mob
if(!istype(food_mob) || !(food_mob?.vore_flags & DEVOURABLE) || (eater?.vore_flags & NO_VORE) || !istype(eater.vore_selected))
return FALSE
qdel(transformation_component)
var/obj/belly/vore_belly = eater.vore_selected
if(!vore_belly.nom_mob(food_mob,eater))
return FALSE
return TRUE
@@ -0,0 +1,36 @@
/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
if(!transformation_component.able_to_struggle_out)
to_chat(src, span_warning("You are unable to struggle out."))
return FALSE
to_chat(src, span_notice("You attempt to escape your transformation."))
if(!do_after(src, 60 SECONDS))
to_chat(src, span_warning("You fail to escape."))
return FALSE
qdel(transformation_component)
return TRUE
@@ -0,0 +1,105 @@
/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
/// Transfer to vore belly when eaten
var/transfer_to_vore = 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,116 @@
/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.
if(!target_mob?.client?.prefs?.object_tf)
to_chat(user, span_warning("It seems like [target_mob] does not want to be transformed."))
return FALSE
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()
@@ -31,6 +31,8 @@
var/fatness_vulnerable = FALSE
/// Similar to fatness_vulnerable, but with more extreme effects such as transformation/hypno.
var/extreme_fatness_vulnerable = FALSE
/// Can the person be transformed into an object?
var/object_tf
// Helplessness, a set of prefs that make things extra tough at higher weights. If set to FALSE, they won't do anything.
///What fatness level disables movement?
+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)
+5
View File
@@ -1409,6 +1409,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "This preference functions similar to the one before but allows for items with more drastic effects. <b>Do not enable this if you aren't okay with more drastic things happening to your character.</b><BR>"
dat += "<b>Extreme Fatness Vulnerability:</b><a href='?_src_=prefs;preference=extreme_fatness_vulnerable'>[extreme_fatness_vulnerable == TRUE ? "Enabled" : "Disabled"]</a><BR>"
dat += "<br></br>"
dat += "<b>Object TF:</b><a href='?_src_=prefs;preference=object_tf'>[object_tf == TRUE ? "Enabled" : "Disabled"]</a><BR>"
dat += "<br></br>"
dat += "<b>Extreme Weight Gain (Sprite Size scales with weight):</b><a href='?_src_=prefs;preference=weight_gain_extreme'>[weight_gain_extreme == TRUE ? "Enabled" : "Disabled"]</a><BR>"
dat += "<b>Persistent Fat (endround/cryo weight becomes your new start weight):</b><a href='?_src_=prefs;preference=weight_gain_persistent'>[weight_gain_persistent == TRUE ? "Enabled" : "Disabled"]</a><BR>"
dat += "<b>Permanent Weight (hard to remove and persistent weight):</b><a href='?_src_=prefs;preference=weight_gain_permanent'>[weight_gain_permanent == TRUE ? "Enabled" : "Disabled"]</a><BR>"
@@ -3422,6 +3424,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("extreme_fatness_vulnerable")
extreme_fatness_vulnerable = !extreme_fatness_vulnerable
if("object_tf")
object_tf = !object_tf
if("blueberry_inflation")
blueberry_inflation = !blueberry_inflation
if("max_fatness")
@@ -951,6 +951,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["chair_breakage"] >> chair_breakage
S["fatness_vulnerable"] >> fatness_vulnerable
S["extreme_fatness_vulnerable"] >> extreme_fatness_vulnerable
S["object_tf"] >> object_tf
S["blueberry_inflation"] >> blueberry_inflation
S["feature_breasts_fluid"] >> features["breasts_fluid"]
@@ -1236,6 +1237,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["chair_breakage"], chair_breakage)
WRITE_FILE(S["fatness_vulnerable"], fatness_vulnerable)
WRITE_FILE(S["extreme_fatness_vulnerable"], extreme_fatness_vulnerable)
WRITE_FILE(S["object_tf"], object_tf)
WRITE_FILE(S["blueberry_inflation"], blueberry_inflation)
WRITE_FILE(S["feature_breasts_fluid"], features["breasts_fluid"])
@@ -89,6 +89,7 @@ All foods are distributed among various categories. Use common sense.
if(!reagents.total_volume)
var/mob/living/location = loc
var/obj/item/trash_item = generate_trash(location)
handle_tf()//GS13 EDIT
qdel(src)
if(istype(location))
location.put_in_hands(trash_item)
+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
+1
View File
@@ -22,6 +22,7 @@
/obj/item/clothing/under/misc/gear_harness = 10,
/obj/item/dildo/custom = 5,
/obj/item/electropack/shockcollar = 3,
/obj/item/transformation_item = 3, // GS13 EDIT
/obj/item/assembly/signaler = 3,
/obj/item/clothing/under/shorts/polychromic/pantsu = 3,
/obj/item/clothing/under/misc/poly_bottomless = 3,
+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))
+4
View File
@@ -3972,6 +3972,10 @@
#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\food.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>
);
};