@@ -8,17 +8,22 @@
|
||||
#define DM_UNABSORB "Un-absorb"
|
||||
|
||||
#define DIGESTABLE (1<<0)
|
||||
#define SHOW_VORE_PREFS (1<<1)
|
||||
#define DEVOURABLE (1<<2)
|
||||
#define FEEDING (1<<3)
|
||||
#define NO_VORE (1<<4)
|
||||
#define OPEN_PANEL (1<<5)
|
||||
#define ABSORBED (1<<6)
|
||||
#define VORE_INIT (1<<7)
|
||||
#define VOREPREF_INIT (1<<8)
|
||||
#define LICKABLE (1<<9)
|
||||
#define DEVOURABLE (1<<1)
|
||||
#define FEEDING (1<<2)
|
||||
#define NO_VORE (1<<3)
|
||||
#define ABSORBED (1<<4)
|
||||
#define VORE_INIT (1<<5)
|
||||
#define VOREPREF_INIT (1<<6)
|
||||
#define LICKABLE (1<<7)
|
||||
/// Can be smelled?
|
||||
#define SMELLABLE (1<<8)
|
||||
/// Can get absorbed?
|
||||
#define ABSORBABLE (1<<9)
|
||||
/// Can get simplemob vored?
|
||||
#define MOBVORE (1<<10)
|
||||
|
||||
#define MAX_VORE_FLAG (1<<10)-1 // change this whenever you add a vore flag, must be largest vore flag*2-1
|
||||
/// Change this whenever you add a vore flag, must be largest vore flag*2-1
|
||||
#define MAX_VORE_FLAG (1<<11)-1
|
||||
|
||||
#define isbelly(A) istype(A, /obj/belly)
|
||||
|
||||
|
||||
@@ -187,6 +187,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/vore_flags = 0
|
||||
var/list/belly_prefs = list()
|
||||
var/vore_taste = "nothing in particular"
|
||||
var/vore_smell = null
|
||||
var/toggleeatingnoise = TRUE
|
||||
var/toggledigestionnoise = TRUE
|
||||
var/hound_sleeper = TRUE
|
||||
|
||||
@@ -821,6 +821,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
S["vore_flags"] >> vore_flags
|
||||
S["vore_taste"] >> vore_taste
|
||||
S["vore_smell"] >> vore_smell
|
||||
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
|
||||
if(fexists(char_vr_path))
|
||||
var/list/json_from_file = json_decode(file2text(char_vr_path))
|
||||
@@ -994,6 +995,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
vore_flags = sanitize_integer(vore_flags, 0, MAX_VORE_FLAG, 0)
|
||||
vore_taste = copytext(vore_taste, 1, MAX_TASTE_LEN)
|
||||
vore_smell = copytext(vore_smell, 1, MAX_TASTE_LEN)
|
||||
belly_prefs = SANITIZE_LIST(belly_prefs)
|
||||
|
||||
cit_character_pref_load(S)
|
||||
@@ -1147,6 +1149,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
WRITE_FILE(S["vore_flags"] , vore_flags)
|
||||
WRITE_FILE(S["vore_taste"] , vore_taste)
|
||||
WRITE_FILE(S["vore_smell"] , vore_smell)
|
||||
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
|
||||
var/belly_prefs_json = safe_json_encode(list("belly_prefs" = belly_prefs))
|
||||
if(fexists(char_vr_path))
|
||||
|
||||
@@ -364,11 +364,10 @@
|
||||
/mob/living/simple_animal/hostile/proc/AttackingTarget()
|
||||
SEND_SIGNAL(src, COMSIG_HOSTILE_ATTACKINGTARGET, target)
|
||||
in_melee = TRUE
|
||||
/* sorry for the simplemob vore fans
|
||||
if(vore_active)
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
if(!client && L.Adjacent(src) && CHECK_BITFIELD(L.vore_flags,DEVOURABLE)) // aggressive check to ensure vore attacks can be made
|
||||
if(!client && L.Adjacent(src) && CHECK_BITFIELD(L.vore_flags, DEVOURABLE) && CHECK_BITFIELD(L.vore_flags, MOBVORE)) // aggressive check to ensure vore attacks can be made
|
||||
if(prob(voracious_chance))
|
||||
vore_attack(src,L,src)
|
||||
else
|
||||
@@ -379,7 +378,6 @@
|
||||
return target.attack_animal(src)
|
||||
else
|
||||
return target.attack_animal(src)
|
||||
*/
|
||||
return target.attack_animal(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/proc/Aggro()
|
||||
|
||||
18
code/modules/tgui/states/vorepanel.dm
Normal file
18
code/modules/tgui/states/vorepanel.dm
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* tgui state: vorepanel_state
|
||||
*
|
||||
* Only checks that the user and src_object are the same.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(ui_vorepanel_state, /datum/ui_state/vorepanel_state, new)
|
||||
|
||||
/datum/ui_state/vorepanel_state/can_use_topic(src_object, mob/user)
|
||||
if(src_object != user)
|
||||
// Note, in order to allow others to look at others vore panels, change this to
|
||||
// UI_UPDATE
|
||||
return UI_CLOSE
|
||||
if(!user.client)
|
||||
return UI_CLOSE
|
||||
if(user.stat == DEAD)
|
||||
return UI_DISABLED
|
||||
return UI_INTERACTIVE
|
||||
@@ -9,7 +9,7 @@
|
||||
* * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
|
||||
* * timeout - The timeout of the alert, after which the modal will close and qdel itself. Set to zero for no timeout.
|
||||
*/
|
||||
/proc/tgui_alert(mob/user, message, title, list/buttons, timeout = 60 SECONDS)
|
||||
/proc/tgui_alert(mob/user, message = null, title = null, list/buttons = list("Ok"), timeout = 0)
|
||||
if (!user)
|
||||
user = usr
|
||||
if (!istype(user))
|
||||
@@ -35,9 +35,9 @@
|
||||
* * title - The of the alert modal, shown on the top of the TGUI window.
|
||||
* * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
|
||||
* * callback - The callback to be invoked when a choice is made.
|
||||
* * timeout - The timeout of the alert, after which the modal will close and qdel itself. Set to zero for no timeout.
|
||||
* * timeout - The timeout of the alert, after which the modal will close and qdel itself. Disabled by default, can be set to seconds otherwise.
|
||||
*/
|
||||
/proc/tgui_alert_async(mob/user, message, title, list/buttons, datum/callback/callback, timeout = 60 SECONDS)
|
||||
/proc/tgui_alert_async(mob/user, message = null, title = null, list/buttons = list("Ok"), datum/callback/callback, timeout = 0)
|
||||
if (!user)
|
||||
user = usr
|
||||
if (!istype(user))
|
||||
@@ -90,7 +90,7 @@
|
||||
* the window was closed by the user.
|
||||
*/
|
||||
/datum/tgui_modal/proc/wait()
|
||||
while (!choice && !closed)
|
||||
while (!choice && !closed && !QDELETED(src))
|
||||
stoplag(1)
|
||||
|
||||
/datum/tgui_modal/ui_interact(mob/user, datum/tgui/ui)
|
||||
@@ -124,10 +124,13 @@
|
||||
if("choose")
|
||||
if (!(params["choice"] in buttons))
|
||||
return
|
||||
choice = params["choice"]
|
||||
set_choice(params["choice"])
|
||||
SStgui.close_uis(src)
|
||||
return TRUE
|
||||
|
||||
/datum/tgui_modal/proc/set_choice(choice)
|
||||
src.choice = choice
|
||||
|
||||
/**
|
||||
* # async tgui_modal
|
||||
*
|
||||
@@ -138,23 +141,17 @@
|
||||
var/datum/callback/callback
|
||||
|
||||
/datum/tgui_modal/async/New(mob/user, message, title, list/buttons, callback, timeout)
|
||||
..(user, title, message, buttons, timeout)
|
||||
..(user, message, title, buttons, timeout)
|
||||
src.callback = callback
|
||||
|
||||
/datum/tgui_modal/async/Destroy(force, ...)
|
||||
QDEL_NULL(callback)
|
||||
. = ..()
|
||||
|
||||
/datum/tgui_modal/async/ui_close(mob/user)
|
||||
/datum/tgui_modal/async/set_choice(choice)
|
||||
. = ..()
|
||||
qdel(src)
|
||||
|
||||
/datum/tgui_modal/async/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if (!. || choice == null)
|
||||
return
|
||||
callback.InvokeAsync(choice)
|
||||
qdel(src)
|
||||
if(!isnull(src.choice))
|
||||
callback?.InvokeAsync(src.choice)
|
||||
|
||||
/datum/tgui_modal/async/wait()
|
||||
return
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
SEND_SOUND(M,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
if(M.vore_flags & ABSORBED)
|
||||
if(M.vore_flags & ABSORBED || !(M.vore_flags & ABSORBABLE)) //Negative.
|
||||
continue
|
||||
|
||||
if(M.nutrition >= 100) //Drain them until there's no nutrients left. Slowly "absorb" them.
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
///////////////////// Mob Living /////////////////////
|
||||
/mob/living
|
||||
var/vore_flags = 0
|
||||
var/showvoreprefs = TRUE // Determines if the mechanical vore preferences button will be displayed on the mob or not.
|
||||
var/obj/belly/vore_selected // Default to no vore capability.
|
||||
var/list/vore_organs = list() // List of vore containers inside a mob
|
||||
var/vore_taste = null // What the character tastes like
|
||||
// Determines if the mechanical vore preferences button will be displayed on the mob or not.
|
||||
var/showvoreprefs = TRUE
|
||||
/// Default to no vore capability.
|
||||
var/obj/belly/vore_selected
|
||||
/// List of vore containers inside a mob
|
||||
var/list/vore_organs = list()
|
||||
/// What the character tastes like
|
||||
var/vore_taste = null
|
||||
/// What the character smells like
|
||||
var/vore_smell = null
|
||||
/// Next time vore sounds get played for the prey, do not change manually as it is intended to be set automatically
|
||||
var/next_preyloop
|
||||
|
||||
//
|
||||
// Hook for generic creation of stuff on new creatures
|
||||
//
|
||||
/hook/living_new/proc/vore_setup(mob/living/M)
|
||||
add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/escapeOOC))
|
||||
add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/smell, /mob/living/proc/escapeOOC))
|
||||
|
||||
if(M.vore_flags & NO_VORE) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach.
|
||||
return TRUE
|
||||
@@ -256,6 +263,7 @@
|
||||
|
||||
client.prefs.vore_flags = vore_flags // there's garbage data in here, but it doesn't matter
|
||||
client.prefs.vore_taste = vore_taste
|
||||
client.prefs.vore_smell = vore_smell
|
||||
|
||||
var/list/serialized = list()
|
||||
for(var/belly in vore_organs)
|
||||
@@ -264,6 +272,8 @@
|
||||
|
||||
client.prefs.belly_prefs = serialized
|
||||
|
||||
client.prefs.save_character()
|
||||
|
||||
return TRUE
|
||||
|
||||
//
|
||||
@@ -274,8 +284,9 @@
|
||||
to_chat(src,"<span class='warning'>You attempted to apply your vore prefs but somehow you're in this character without a client.prefs variable. Tell a dev.</span>")
|
||||
return FALSE
|
||||
ENABLE_BITFIELD(vore_flags,VOREPREF_INIT)
|
||||
COPY_SPECIFIC_BITFIELDS(vore_flags,client.prefs.vore_flags,DIGESTABLE | DEVOURABLE | FEEDING | LICKABLE)
|
||||
COPY_SPECIFIC_BITFIELDS(vore_flags, client.prefs.vore_flags, DIGESTABLE | DEVOURABLE | FEEDING | LICKABLE | SMELLABLE | ABSORBABLE | MOBVORE)
|
||||
vore_taste = client.prefs.vore_taste
|
||||
vore_smell = client.prefs.vore_smell
|
||||
|
||||
release_vore_contents(silent = TRUE)
|
||||
QDEL_LIST(vore_organs)
|
||||
@@ -379,6 +390,56 @@
|
||||
else
|
||||
taste_message += "a plain old normal [src]"
|
||||
return taste_message
|
||||
|
||||
//
|
||||
// Equally important as the above
|
||||
//
|
||||
/mob/living/proc/smell()
|
||||
set name = "Smell Someone"
|
||||
set category = "Vore"
|
||||
set desc = "Smell someone nearby!"
|
||||
|
||||
if(incapacitated(ignore_restraints = TRUE))
|
||||
to_chat(src, "<span class='warning'>You can't do that while incapacitated.</span>")
|
||||
return
|
||||
if(!CheckActionCooldown())
|
||||
to_chat(src, "<span class='warning'>You can't do that so fast, slow down.</span>")
|
||||
return
|
||||
|
||||
DelayNextAction(CLICK_CD_MELEE, flush = TRUE)
|
||||
|
||||
var/list/smellable = list()
|
||||
for(var/mob/living/L in view(1))
|
||||
if(L != src && (!L.ckey || L.client?.prefs.vore_flags & SMELLABLE) && Adjacent(L))
|
||||
LAZYADD(smellable, L)
|
||||
for(var/mob/living/listed in smellable)
|
||||
smellable[listed] = new /mutable_appearance(listed)
|
||||
|
||||
if(!smellable)
|
||||
return
|
||||
|
||||
var/mob/living/sniffed = show_radial_menu(src, src, smellable, radius = 40, require_near = TRUE)
|
||||
|
||||
if(QDELETED(sniffed) || (sniffed.ckey && !(sniffed.client?.prefs.vore_flags & SMELLABLE)) || !Adjacent(sniffed) || incapacitated(ignore_restraints = TRUE))
|
||||
return
|
||||
|
||||
visible_message("<span class='warning'>[src] smells [sniffed]!</span>","<span class='notice'>You smell [sniffed]. They smell like [sniffed.get_smell_message()].</span>","<b>Sniff!</b>")
|
||||
|
||||
/mob/living/proc/get_smell_message(allow_generic = TRUE, datum/species/mrace)
|
||||
if(!vore_smell && !allow_generic)
|
||||
return FALSE
|
||||
|
||||
var/smell_message = ""
|
||||
if(vore_smell && (vore_smell != ""))
|
||||
smell_message += "[vore_smell]"
|
||||
else
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/H = src
|
||||
smell_message += "a normal [H.custom_species ? H.custom_species : H.dna.species]"
|
||||
else
|
||||
smell_message += "a plain old normal [src]"
|
||||
return smell_message
|
||||
|
||||
// Check if an object is capable of eating things, based on vore_organs
|
||||
//
|
||||
/proc/has_vore_belly(var/mob/living/O)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3593,6 +3593,7 @@
|
||||
#include "code\modules\tgui\states\observer.dm"
|
||||
#include "code\modules\tgui\states\physical.dm"
|
||||
#include "code\modules\tgui\states\self.dm"
|
||||
#include "code\modules\tgui\states\vorepanel.dm"
|
||||
#include "code\modules\tgui\states\zlevel.dm"
|
||||
#include "code\modules\tgui_panel\audio.dm"
|
||||
#include "code\modules\tgui_panel\external.dm"
|
||||
|
||||
591
tgui/packages/tgui/interfaces/VorePanel.js
Normal file
591
tgui/packages/tgui/interfaces/VorePanel.js
Normal file
@@ -0,0 +1,591 @@
|
||||
/* eslint-disable max-len */
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend, useLocalState } from "../backend";
|
||||
import { Box, Button, Flex, Collapsible, Icon, LabeledList, NoticeBox, Section, Tabs } from "../components";
|
||||
import { Window } from "../layouts";
|
||||
|
||||
const stats = [
|
||||
null,
|
||||
'average',
|
||||
'bad',
|
||||
];
|
||||
|
||||
const digestModeToColor = {
|
||||
"Hold": null,
|
||||
"Dragon": "blue",
|
||||
"Digest": "red",
|
||||
"Absorb": "purple",
|
||||
"Unabsorb": "purple",
|
||||
};
|
||||
|
||||
const digestModeToPreyMode = {
|
||||
"Hold": "being held.",
|
||||
"Digest": "being digested.",
|
||||
"Absorb": "being absorbed.",
|
||||
"Unabsorb": "being unabsorbed.",
|
||||
"Dragon": "being digested by a powerful creature.",
|
||||
};
|
||||
|
||||
/**
|
||||
* There are three main sections to this UI.
|
||||
* - The Inside Panel, where all relevant data for interacting with a belly you're in is located.
|
||||
* - The Belly Selection Panel, where you can select what belly people will go into and customize the active one.
|
||||
* - User Preferences, where you can adjust all of your vore preferences on the fly.
|
||||
*/
|
||||
export const VorePanel = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
return (
|
||||
<Window width={700} height={660} theme="abstract" resizable>
|
||||
<Window.Content scrollable>
|
||||
{data.unsaved_changes && (
|
||||
<NoticeBox danger>
|
||||
<Flex>
|
||||
<Flex.Item basis="90%">
|
||||
Warning: Unsaved Changes!
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
content="Save Prefs"
|
||||
icon="save"
|
||||
onClick={() => act("saveprefs")} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</NoticeBox>
|
||||
) || null}
|
||||
<VoreInsidePanel />
|
||||
<VoreBellySelectionAndCustomization />
|
||||
<VoreUserPreferences />
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const VoreInsidePanel = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
absorbed,
|
||||
belly_name,
|
||||
belly_mode,
|
||||
desc,
|
||||
pred,
|
||||
contents,
|
||||
ref,
|
||||
} = data.inside;
|
||||
|
||||
if (!belly_name) {
|
||||
return (
|
||||
<Section title="Inside">
|
||||
You aren't inside anyone.
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Section title="Inside">
|
||||
<Box color="green" inline>You are currently {absorbed ? "absorbed into" : "inside"}</Box>
|
||||
<Box color="yellow" inline>{pred}'s</Box>
|
||||
<Box color="red" inline>{belly_name}</Box>
|
||||
<Box color="yellow" inline>and you are</Box>
|
||||
<Box color={digestModeToColor[belly_mode]} inline>{digestModeToPreyMode[belly_mode]}</Box>
|
||||
<Box color="label">
|
||||
{desc}
|
||||
</Box>
|
||||
{contents.length && (
|
||||
<Collapsible title="Belly Contents">
|
||||
<VoreContentsPanel contents={contents} belly={ref} />
|
||||
</Collapsible>
|
||||
) || "There is nothing else around you."}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const VoreBellySelectionAndCustomization = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
our_bellies,
|
||||
selected,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Section title="My Bellies">
|
||||
<Tabs>
|
||||
{our_bellies.map(belly => (
|
||||
<Tabs.Tab
|
||||
key={belly.name}
|
||||
selected={belly.selected}
|
||||
textColor={digestModeToColor[belly.digest_mode]}
|
||||
onClick={() => act("bellypick", { bellypick: belly.ref })}>
|
||||
<Box inline textColor={belly.selected && digestModeToColor[belly.digest_mode] || null}>
|
||||
{belly.name} ({belly.contents})
|
||||
</Box>
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
<Tabs.Tab onClick={() => act("newbelly")}>
|
||||
New
|
||||
<Icon name="plus" ml={0.5} />
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
{selected && <VoreSelectedBelly belly={selected} />}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtemplate of VoreBellySelectionAndCustomization
|
||||
*/
|
||||
const VoreSelectedBelly = (props, context) => {
|
||||
const { act } = useBackend(context);
|
||||
|
||||
const { belly } = props;
|
||||
const {
|
||||
belly_name,
|
||||
is_wet,
|
||||
wet_loop,
|
||||
mode,
|
||||
verb,
|
||||
desc,
|
||||
sound,
|
||||
release_sound,
|
||||
can_taste,
|
||||
bulge_size,
|
||||
escapable,
|
||||
interacts,
|
||||
contents,
|
||||
} = belly;
|
||||
|
||||
const [tabIndex, setTabIndex] = useLocalState(context, 'tabIndex', 0);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Tabs>
|
||||
<Tabs.Tab selected={tabIndex === 0} onClick={() => setTabIndex(0)}>
|
||||
Controls
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab selected={tabIndex === 1} onClick={() => setTabIndex(1)}>
|
||||
Options
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab selected={tabIndex === 2} onClick={() => setTabIndex(2)}>
|
||||
Contents ({contents.length})
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab selected={tabIndex === 3} onClick={() => setTabIndex(3)}>
|
||||
Interactions
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
{tabIndex === 0 && (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Name" buttons={
|
||||
<Fragment>
|
||||
<Button
|
||||
icon="arrow-left"
|
||||
tooltipPosition="left"
|
||||
tooltip="Move this belly tab left."
|
||||
onClick={() => act("move_belly", { dir: -1 })} />
|
||||
<Button
|
||||
icon="arrow-right"
|
||||
tooltipPosition="left"
|
||||
tooltip="Move this belly tab right."
|
||||
onClick={() => act("move_belly", { dir: 1 })} />
|
||||
</Fragment>
|
||||
}>
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_name" })}
|
||||
content={belly_name} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Mode">
|
||||
<Button
|
||||
color={digestModeToColor[mode]}
|
||||
onClick={() => act("set_attribute", { attribute: "b_mode" })}
|
||||
content={mode} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Flavor Text" buttons={
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_desc" })}
|
||||
icon="pen" />
|
||||
}>
|
||||
{desc}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Vore Verb">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_verb" })}
|
||||
content={verb} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Belly Messages">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "dmp" })}
|
||||
content="Digest Message (to prey)" />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "dmo" })}
|
||||
content="Digest Message (to you)" />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "smo" })}
|
||||
content="Struggle Message (outside)" />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "smi" })}
|
||||
content="Struggle Message (inside)" />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "em" })}
|
||||
content="Examine Message (when full)" />
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "reset" })}
|
||||
content="Reset Messages" />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) || tabIndex === 1 && (
|
||||
<Flex wrap="wrap">
|
||||
<Flex.Item basis="49%" grow={1}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Can Taste">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_tastes" })}
|
||||
icon={can_taste ? "toggle-on" : "toggle-off"}
|
||||
selected={can_taste}
|
||||
content={can_taste ? "Yes" : "No"} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Fleshy Belly">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_wetness" })}
|
||||
icon={is_wet ? "toggle-on" : "toggle-off"}
|
||||
selected={is_wet}
|
||||
content={is_wet ? "Yes" : "No"} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Internal Loop">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_wetloop" })}
|
||||
icon={wet_loop ? "toggle-on" : "toggle-off"}
|
||||
selected={wet_loop}
|
||||
content={wet_loop ? "Yes" : "No"} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="49%" grow={1}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Vore Sound">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_sound" })}
|
||||
content={sound} />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_soundtest" })}
|
||||
icon="volume-up" />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Release Sound">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_release" })}
|
||||
content={release_sound} />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_releasesoundtest" })}
|
||||
icon="volume-up" />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Required Examine Size">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_bulge_size" })}
|
||||
content={bulge_size * 100 + "%"} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="100%" mt={1}>
|
||||
<Button.Confirm
|
||||
fluid
|
||||
icon="exclamation-triangle"
|
||||
confirmIcon="trash"
|
||||
color="red"
|
||||
content="Delete Belly"
|
||||
confirmContent="This is irreversable!"
|
||||
onClick={() => act("set_attribute", { attribute: "b_del" })} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
) || tabIndex === 2 && (
|
||||
<VoreContentsPanel outside contents={contents} />
|
||||
) || tabIndex === 3 && (
|
||||
<Section title="Belly Interactions" buttons={
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_escapable" })}
|
||||
icon={escapable ? "toggle-on" : "toggle-off"}
|
||||
selected={escapable}
|
||||
content={escapable ? "Interactions On" : "Interactions Off"} />
|
||||
}>
|
||||
{escapable ? (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Escape Chance">
|
||||
<Button
|
||||
content={interacts.escapechance + "%"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_escapechance" })} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Escape Time">
|
||||
<Button
|
||||
content={interacts.escapetime / 10 + "s"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_escapetime" })} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Divider />
|
||||
<LabeledList.Item label="Transfer Chance">
|
||||
<Button
|
||||
content={interacts.transferchance + "%"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_transferchance" })} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Transfer Location">
|
||||
<Button
|
||||
content={interacts.transferlocation ? interacts.transferlocation : "Disabled"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_transferlocation" })} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Divider />
|
||||
<LabeledList.Item label="Absorb Chance">
|
||||
<Button
|
||||
content={interacts.absorbchance + "%"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_absorbchance" })} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Digest Chance">
|
||||
<Button
|
||||
content={interacts.digestchance + "%"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_digestchance" })} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) : "These options only display while interactions are turned on."}
|
||||
</Section>
|
||||
) || "Error"}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const VoreContentsPanel = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
show_pictures,
|
||||
} = data;
|
||||
const {
|
||||
contents,
|
||||
belly,
|
||||
outside = false,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{outside && (
|
||||
<Button
|
||||
textAlign="center"
|
||||
fluid
|
||||
mb={1}
|
||||
onClick={() => act("pick_from_outside", { "pickall": true })}>
|
||||
All
|
||||
</Button>
|
||||
) || null}
|
||||
{show_pictures && (
|
||||
<Flex wrap="wrap" justify="center" align="center">
|
||||
{contents.map(thing => (
|
||||
<Flex.Item key={thing.name} basis="33%">
|
||||
<Button
|
||||
width="64px"
|
||||
color={thing.absorbed ? "purple" : stats[thing.stat]}
|
||||
style={{
|
||||
'vertical-align': 'middle',
|
||||
'margin-right': '5px',
|
||||
'border-radius': '20px',
|
||||
}}
|
||||
onClick={() => act(thing.outside ? "pick_from_outside" : "pick_from_inside", {
|
||||
"pick": thing.ref,
|
||||
"belly": belly,
|
||||
})}>
|
||||
<img
|
||||
src={"data:image/jpeg;base64, " + thing.icon}
|
||||
width="64px"
|
||||
height="64px"
|
||||
style={{
|
||||
'-ms-interpolation-mode': 'nearest-neighbor',
|
||||
'margin-left': '-5px',
|
||||
}} />
|
||||
</Button>
|
||||
{thing.name}
|
||||
</Flex.Item>
|
||||
))}
|
||||
</Flex>
|
||||
) || (
|
||||
<LabeledList>
|
||||
{contents.map(thing => (
|
||||
<LabeledList.Item key={thing.ref} label={thing.name}>
|
||||
<Button
|
||||
fluid
|
||||
mt={-1}
|
||||
mb={-1}
|
||||
color={thing.absorbed ? "purple" : stats[thing.stat]}
|
||||
onClick={() => act(thing.outside ? "pick_from_outside" : "pick_from_inside", {
|
||||
"pick": thing.ref,
|
||||
"belly": belly,
|
||||
})}>
|
||||
Interact
|
||||
</Button>
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const VoreUserPreferences = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
digestable,
|
||||
devourable,
|
||||
feeding,
|
||||
absorbable,
|
||||
allowmobvore,
|
||||
vore_sounds,
|
||||
digestion_sounds,
|
||||
lickable,
|
||||
smellable,
|
||||
} = data.prefs;
|
||||
|
||||
const {
|
||||
show_pictures,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Section title="Preferences" buttons={
|
||||
<Button icon="eye" selected={show_pictures} onClick={() => act("show_pictures")}>
|
||||
Contents Preference: {show_pictures ? "Show Pictures" : "Show List"}
|
||||
</Button>
|
||||
}>
|
||||
<Flex spacing={1} wrap="wrap" justify="center">
|
||||
<Flex.Item basis="33%">
|
||||
<Button
|
||||
onClick={() => act("toggle_devour")}
|
||||
icon={devourable ? "toggle-on" : "toggle-off"}
|
||||
selected={devourable}
|
||||
fluid
|
||||
tooltip={"This button is to toggle your ability to be devoured by others. "
|
||||
+ (devourable ? "Click here to prevent being devoured." : "Click here to allow being devoured.")}
|
||||
content={devourable ? "Devouring Allowed" : "No Devouring"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="33%">
|
||||
<Button
|
||||
onClick={() => act("toggle_mobvore")}
|
||||
icon={allowmobvore ? "toggle-on" : "toggle-off"}
|
||||
selected={allowmobvore}
|
||||
fluid
|
||||
tooltip={"This button is for those who don't like being eaten by mobs. "
|
||||
+ (allowmobvore
|
||||
? "Click here to prevent being eaten by mobs."
|
||||
: "Click here to allow being eaten by mobs.")}
|
||||
tooltipPosition="bottom-right"
|
||||
content={allowmobvore ? "Mobs eating you allowed" : "No Mobs eating you"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="33%" grow={1}>
|
||||
<Button
|
||||
onClick={() => act("toggle_feed")}
|
||||
icon={feeding ? "toggle-on" : "toggle-off"}
|
||||
selected={feeding}
|
||||
fluid
|
||||
tooltip={"This button is to toggle your ability to be fed to or by others vorishly. "
|
||||
+ (feeding
|
||||
? "Click here to prevent being fed to/by other people."
|
||||
: "Click here to allow being fed to/by other people.")}
|
||||
content={feeding ? "Feeding Allowed" : "No Feeding"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="50%">
|
||||
<Button
|
||||
onClick={() => act("toggle_digest")}
|
||||
icon={digestable ? "toggle-on" : "toggle-off"}
|
||||
selected={digestable}
|
||||
fluid
|
||||
tooltip={"This button is for those who don't like being digested. It can make you undigestable."
|
||||
+ (digestable ? " Click here to prevent digestion." : " Click here to allow digestion.")}
|
||||
tooltipPosition="bottom-right"
|
||||
content={digestable ? "Digestion Allowed" : "No Digestion"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="50%">
|
||||
<Button
|
||||
onClick={() => act("toggle_absorbable")}
|
||||
icon={absorbable ? "toggle-on" : "toggle-off"}
|
||||
selected={absorbable}
|
||||
fluid
|
||||
tooltip={"This button allows preds to know whether you prefer or don't prefer to be absorbed. "
|
||||
+ (absorbable ? "Click here to disallow being absorbed." : "Click here to allow being absorbed.")}
|
||||
content={absorbable ? "Absorption Allowed" : "No Absorption"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="50%">
|
||||
<Button
|
||||
onClick={() => act("toggle_vore_sounds")}
|
||||
icon={vore_sounds ? "volume-up" : "volume-mute"}
|
||||
selected={vore_sounds}
|
||||
fluid
|
||||
tooltip={"Be able to hear vore sounds. "
|
||||
+ (vore_sounds
|
||||
? "Click here to turn off vore sounds."
|
||||
: "Click here to turn on vore sounds.")}
|
||||
content={vore_sounds ? "Vore Sounds Enabled" : "Vore Sounds Disabled"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="50%">
|
||||
<Button
|
||||
onClick={() => act("toggle_digestion_sounds")}
|
||||
icon={digestion_sounds ? "volume-up" : "volume-mute"}
|
||||
selected={digestion_sounds}
|
||||
fluid
|
||||
tooltip={"Be able to hear digestion sounds. "
|
||||
+ (digestion_sounds
|
||||
? "Click here to turn off digestion sounds."
|
||||
: "Click here to turn on digestion sounds.")}
|
||||
content={digestion_sounds ? "Digestion Sounds Enabled" : "Digestion Sounds Disabled"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="25%">
|
||||
<Button
|
||||
onClick={() => act("toggle_lickable")}
|
||||
icon={lickable ? "toggle-on" : "toggle-off"}
|
||||
selected={lickable}
|
||||
fluid
|
||||
tooltip={"Be able to be licked by others. "
|
||||
+ (lickable
|
||||
? "Click here to turn off being able to be licked."
|
||||
: "Click here to turn on being able to be licked.")}
|
||||
tooltipPosition="bottom-right"
|
||||
content={lickable ? "Lickable" : "Unlickable"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="25%">
|
||||
<Button
|
||||
fluid
|
||||
content="Set Taste"
|
||||
icon="grin-tongue"
|
||||
onClick={() => act("setflavor")} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="25%">
|
||||
<Button
|
||||
onClick={() => act("toggle_smellable")}
|
||||
icon={smellable ? "toggle-on" : "toggle-off"}
|
||||
selected={smellable}
|
||||
fluid
|
||||
tooltip={"Be able to be smelled by others. "
|
||||
+ (smellable
|
||||
? "Click here to turn off being able to be smelled."
|
||||
: "Click here to turn on being able to be smelled.")}
|
||||
content={smellable ? "Smellable" : "Unsmellable"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="25%">
|
||||
<Button
|
||||
fluid
|
||||
content="Set Smell"
|
||||
icon="wind"
|
||||
onClick={() => act("setsmell")} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
<Section>
|
||||
<Flex spacing={1}>
|
||||
<Flex.Item basis="49%">
|
||||
<Button
|
||||
fluid
|
||||
content="Save Prefs"
|
||||
icon="save"
|
||||
onClick={() => act("saveprefs")} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="49%" grow={1}>
|
||||
<Button
|
||||
fluid
|
||||
content="Reload Prefs"
|
||||
icon="undo"
|
||||
onClick={() => act("reloadprefs")} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user