Merge pull request #20 from sheepishgoat/tf-mechanics
Object TF mechanics
This commit is contained in:
@@ -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?
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user