allows soulcatcher import and export (#17391)

* allows soulcatcher import and export

* .

* vore pref transfer to define

* order them

* fix button issue on tgpanel

* Update vore_prefs.dm

* Update VorePanelExportSoulcatcherString.tsx
This commit is contained in:
Kashargul
2025-03-22 17:10:02 -04:00
committed by GitHub
parent eda524a0e8
commit 2a83d9da7f
14 changed files with 262 additions and 163 deletions
+60
View File
@@ -0,0 +1,60 @@
#define VORE_PREF_TRANSFER(target, source) \
target.digestable = source.digestable; \
target.devourable = source.devourable; \
target.feeding = source.feeding; \
target.absorbable = source.absorbable; \
target.allowmobvore = source.allowmobvore; \
target.permit_healbelly = source.permit_healbelly; \
\
target.vore_taste = source.vore_taste; \
target.vore_smell = source.vore_smell; \
target.noisy = source.noisy; \
target.show_vore_fx = source.show_vore_fx; \
target.selective_preference = source.selective_preference; \
target.digest_leave_remains = source.digest_leave_remains; \
target.digest_pain = source.digest_pain; \
target.noisy_full = source.noisy_full; \
target.eating_privacy_global = source.eating_privacy_global; \
\
target.can_be_drop_prey = source.can_be_drop_prey; \
target.can_be_drop_pred = source.can_be_drop_pred; \
target.throw_vore = source.throw_vore; \
target.food_vore = source.food_vore; \
target.drop_vore = source.drop_vore; \
target.slip_vore = source.slip_vore; \
target.stumble_vore = source.stumble_vore; \
target.phase_vore = source.phase_vore; \
\
target.resizable = source.resizable; \
target.step_mechanics_pref = source.step_mechanics_pref; \
target.pickup_pref = source.pickup_pref; \
target.allow_spontaneous_tf = source.allow_spontaneous_tf; \
target.allow_mind_transfer = source.allow_mind_transfer; \
target.allow_mimicry = source.allow_mimicry; \
\
target.consume_liquid_belly = source.consume_liquid_belly; \
target.receive_reagents = source.receive_reagents; \
target.apply_reagents = source.apply_reagents; \
target.give_reagents = source.give_reagents; \
\
target.nutrition_messages = source.nutrition_messages; \
target.nutrition_message_visible = source.nutrition_message_visible; \
target.weight_message_visible = source.weight_message_visible; \
target.weight_messages = source.weight_messages; \
\
target.latejoin_vore = source.latejoin_vore; \
target.latejoin_prey = source.latejoin_prey; \
target.no_latejoin_vore_warning = source.no_latejoin_vore_warning; \
target.no_latejoin_prey_warning = source.no_latejoin_prey_warning; \
target.no_latejoin_vore_warning_time = source.no_latejoin_vore_warning_time; \
target.no_latejoin_prey_warning_time = source.no_latejoin_prey_warning_time; \
target.no_latejoin_vore_warning_persists = source.no_latejoin_vore_warning_persists;\
target.no_latejoin_prey_warning_persists = source.no_latejoin_prey_warning_persists;\
\
target.autotransferable = source.autotransferable; \
target.strip_pref = source.strip_pref; \
target.vore_sprite_multiply = source.vore_sprite_multiply; \
target.vore_sprite_color = source.vore_sprite_color; \
target.belly_rub_target = source.belly_rub_target; \
\
target.soulcatcher_pref_flags = source.soulcatcher_pref_flags;
+1 -1
View File
@@ -211,7 +211,7 @@ var/list/runechat_image_cache = list()
// When choosing to update the remaining time we have to be careful not to update the
// scheduled time once the EOL has been executed.
var/continuing = 0
var/continuing = NONE
if (time_spent >= time_before_fade)
if(m.message.pixel_y < starting_height)
var/max_height = m.message.pixel_y + m.approx_lines * CHAT_MESSAGE_APPROX_LHEIGHT - starting_height
+26 -2
View File
@@ -1,8 +1,13 @@
#define IMPORT_ALL_BELLIES "Import all bellies from VRDB"
#define IMPORT_ONE_BELLY "Import one belly from VRDB"
#define IMPORT_SOULCATCHER "Import Soulcatcher from VRDB"
/datum/vore_look/proc/import_belly(mob/host)
var/panel_choice = tgui_input_list(host, "Belly Import", "Pick an option", list("Import all bellies from VRDB","Import one belly from VRDB"))
var/panel_choice = tgui_input_list(host, "Belly Import", "Pick an option", list(IMPORT_ALL_BELLIES, IMPORT_ONE_BELLY, IMPORT_SOULCATCHER))
if(!panel_choice) return
var/pickOne = FALSE
if(panel_choice == "Import one belly from VRDB")
if(panel_choice == IMPORT_ONE_BELLY)
pickOne = TRUE
var/input_file = input(host,"Please choose a valid VRDB file to import from.","Belly Import") as file
var/input_data
@@ -12,6 +17,21 @@
tgui_alert_async(host, "The supplied file contains errors: [e]", "Error!")
return FALSE
if(panel_choice == IMPORT_SOULCATCHER)
if(!islist(input_data["soulcatcher"]))
tgui_alert_async(host, "The supplied file was not a valid VRDB >= v0.2 file.", "Error!")
return FALSE
var/list/soulcatcher_data = input_data["soulcatcher"]
var/return_val = import_soulcatcher(host, soulcatcher_data)
if(return_val)
host.updateVRPanel()
unsaved_changes = TRUE
return return_val
if(islist(input_data["bellies"]))
input_data = input_data["bellies"]
if(!islist(input_data))
tgui_alert_async(host, "The supplied file was not a valid VRDB file.", "Error!")
return FALSE
@@ -1155,3 +1175,7 @@
host.handle_belly_update()
host.updateVRPanel()
unsaved_changes = TRUE
#undef IMPORT_ALL_BELLIES
#undef IMPORT_ONE_BELLY
#undef IMPORT_SOULCATCHER
+17 -1
View File
@@ -27,7 +27,7 @@
var/list/data = list()
var/mob/living/host = user
data["db_version"] = "0.1"
data["db_version"] = "0.2"
data["db_repo"] = "vorestation"
data["mob_name"] = host.real_name
@@ -481,4 +481,20 @@
for(var/msg in B.fullness5_messages)
belly_data["fullness5_messages"] += msg
// Soulcatcher export
if(user.soulgem)
var/obj/soulgem/gem = user.soulgem
var/list/soulcatcher_data = list()
soulcatcher_data["name"] = gem.name
soulcatcher_data["setting_flags"] = gem.setting_flags
soulcatcher_data["inside_flavor"] = gem.inside_flavor
soulcatcher_data["capture_message"] = gem.capture_message
soulcatcher_data["transit_message"] = gem.transit_message
soulcatcher_data["release_message"] = gem.release_message
soulcatcher_data["transfer_message"] = gem.transfer_message
soulcatcher_data["delete_message"] = gem.delete_message
soulcatcher_data["linked_belly"] = gem.linked_belly
data["soulcatcher"] = soulcatcher_data
return data
+2 -106
View File
@@ -250,59 +250,7 @@
var/datum/vore_preferences/P = client.prefs_vr
P.digestable = src.digestable
P.devourable = src.devourable
P.feeding = src.feeding
P.absorbable = src.absorbable
P.resizable = src.resizable
P.digest_leave_remains = src.digest_leave_remains
P.allowmobvore = src.allowmobvore
P.vore_taste = src.vore_taste
P.vore_smell = src.vore_smell
P.permit_healbelly = src.permit_healbelly
P.noisy = src.noisy
P.selective_preference = src.selective_preference
P.show_vore_fx = src.show_vore_fx
P.can_be_drop_prey = src.can_be_drop_prey
P.can_be_drop_pred = src.can_be_drop_pred
P.allow_spontaneous_tf = src.allow_spontaneous_tf
P.step_mechanics_pref = src.step_mechanics_pref
P.pickup_pref = src.pickup_pref
P.drop_vore = src.drop_vore
P.slip_vore = src.slip_vore
P.throw_vore = src.throw_vore
P.food_vore = src.food_vore
P.consume_liquid_belly = src.consume_liquid_belly
P.digest_pain = src.digest_pain
P.stumble_vore = src.stumble_vore
P.eating_privacy_global = src.eating_privacy_global
P.allow_mimicry = src.allow_mimicry
P.nutrition_message_visible = src.nutrition_message_visible
P.nutrition_messages = src.nutrition_messages
P.weight_message_visible = src.weight_message_visible
P.weight_messages = src.weight_messages
P.vore_sprite_color = src.vore_sprite_color
P.allow_mind_transfer = src.allow_mind_transfer
P.phase_vore = src.phase_vore
P.noisy_full = src.noisy_full
P.latejoin_vore = src.latejoin_vore
P.latejoin_prey = src.latejoin_prey
P.receive_reagents = src.receive_reagents
P.give_reagents = src.give_reagents
P.apply_reagents = src.apply_reagents
P.autotransferable = src.autotransferable
P.strip_pref = src.strip_pref
P.vore_sprite_multiply = src.vore_sprite_multiply
P.no_latejoin_vore_warning = src.no_latejoin_vore_warning
P.no_latejoin_prey_warning = src.no_latejoin_prey_warning
P.no_latejoin_vore_warning_time = src.no_latejoin_vore_warning_time
P.no_latejoin_prey_warning_time = src.no_latejoin_prey_warning_time
P.no_latejoin_vore_warning_persists = src.no_latejoin_vore_warning_persists
P.no_latejoin_prey_warning_persists = src.no_latejoin_prey_warning_persists
P.belly_rub_target = src.belly_rub_target
P.soulcatcher_pref_flags = src.soulcatcher_pref_flags
VORE_PREF_TRANSFER(P, src)
var/list/serialized = list()
for(var/obj/belly/B as anything in src.vore_organs)
@@ -323,59 +271,7 @@
var/datum/vore_preferences/P = client.prefs_vr
digestable = P.digestable
devourable = P.devourable
feeding = P.feeding
absorbable = P.absorbable
resizable = P.resizable
digest_leave_remains = P.digest_leave_remains
allowmobvore = P.allowmobvore
vore_taste = P.vore_taste
vore_smell = P.vore_smell
permit_healbelly = P.permit_healbelly
selective_preference = P.selective_preference
noisy = P.noisy
show_vore_fx = P.show_vore_fx
can_be_drop_prey = P.can_be_drop_prey
can_be_drop_pred = P.can_be_drop_pred
allow_spontaneous_tf = P.allow_spontaneous_tf
step_mechanics_pref = P.step_mechanics_pref
pickup_pref = P.pickup_pref
drop_vore = P.drop_vore
slip_vore = P.slip_vore
throw_vore = P.throw_vore
stumble_vore = P.stumble_vore
food_vore = P.food_vore
consume_liquid_belly = P.consume_liquid_belly
digest_pain = P.digest_pain
eating_privacy_global = P.eating_privacy_global
allow_mimicry = P.allow_mimicry
nutrition_message_visible = P.nutrition_message_visible
nutrition_messages = P.nutrition_messages
weight_message_visible = P.weight_message_visible
weight_messages = P.weight_messages
vore_sprite_color = P.vore_sprite_color
allow_mind_transfer = P.allow_mind_transfer
phase_vore = P.phase_vore
noisy_full = P.noisy_full
latejoin_vore = P.latejoin_vore
latejoin_prey = P.latejoin_prey
receive_reagents = P.receive_reagents
give_reagents = P.give_reagents
apply_reagents = P.apply_reagents
autotransferable = P.autotransferable
strip_pref = P.strip_pref
vore_sprite_multiply = P.vore_sprite_multiply
no_latejoin_vore_warning = P.no_latejoin_vore_warning
no_latejoin_prey_warning = P.no_latejoin_prey_warning
no_latejoin_vore_warning_time = P.no_latejoin_vore_warning_time
no_latejoin_prey_warning_time = P.no_latejoin_prey_warning_time
no_latejoin_vore_warning_persists = P.no_latejoin_vore_warning_persists
no_latejoin_prey_warning_persists = P.no_latejoin_prey_warning_persists
belly_rub_target = P.belly_rub_target
soulcatcher_pref_flags = P.soulcatcher_pref_flags
VORE_PREF_TRANSFER(src, P)
if(bellies)
if(isliving(src))
+9 -4
View File
@@ -40,12 +40,17 @@
// Store the vars_to_save into the save file
/obj/soulgem/deserialize(list/data)
. = ..()
for(var/obj/belly in owner.vore_organs)
if(belly.name == data["linked_belly"])
update_linked_belly(belly, TRUE)
return
if(apply_stored_belly(data["linked_belly"], TRUE))
return
linked_belly = null
/obj/soulgem/proc/apply_stored_belly(var/belly_string, var/skip_unreg = FALSE)
for(var/obj/belly in owner.vore_organs)
if(belly.name == belly_string)
update_linked_belly(belly, TRUE)
return TRUE
return FALSE
// Allows to transfer the soulgem to the given mob
/obj/soulgem/proc/transfer_self(var/mob/target)
QDEL_NULL(target.soulgem)
@@ -0,0 +1,47 @@
/datum/vore_look/proc/import_soulcatcher(mob/host, var/list/soulcatcher_data)
if(!host.soulgem)
return FALSE
if(!islist(soulcatcher_data))
tgui_alert_async(host, "The supplied file was not a valid VRDB file.", "Error!")
return FALSE
if(LAZYLEN(soulcatcher_data) == 0)
return FALSE
var/confirm = tgui_alert(host, "WARNING: This will override your current soulcatcher settings!","Import soulcatcher?",list("Yes","Cancel"))
if(confirm != "Yes")
return FALSE
var/obj/soulgem/gem = host.soulgem
if(istext(soulcatcher_data["name"]))
gem.rename(soulcatcher_data["name"])
if(istext(soulcatcher_data["inside_flavor"]))
gem.adjust_interior(soulcatcher_data["inside_flavor"])
if(istext(soulcatcher_data["capture_message"]))
gem.set_custom_message("capture", soulcatcher_data["capture_message"])
if(istext(soulcatcher_data["transit_message"]))
gem.set_custom_message("transit", soulcatcher_data["transit_message"])
if(istext(soulcatcher_data["release_message"]))
gem.set_custom_message("release", soulcatcher_data["release_message"])
if(istext(soulcatcher_data["transfer_message"]))
gem.set_custom_message("transfer", soulcatcher_data["transfer_message"])
if(istext(soulcatcher_data["delete_message"]))
gem.set_custom_message("delete", soulcatcher_data["delete_message"])
if(istext(soulcatcher_data["linked_belly"]))
gem.apply_stored_belly(soulcatcher_data["linked_belly"])
if(isnum(soulcatcher_data["setting_flags"]))
gem.setting_flags = NONE
gem.toggle_setting(soulcatcher_data["setting_flags"])
return TRUE
+2 -47
View File
@@ -148,60 +148,15 @@
/mob/living/proc/copy_vore_prefs_to_mob(var/mob/living/new_mob)
//For primarily copying vore preference settings from a carbon mob to a simplemob
//It can be used for other things, but be advised, if you're using it to put a simplemob into a carbon mob, you're gonna be overriding a bunch of prefs
new_mob.ooc_notes = ooc_notes
new_mob.ooc_notes_likes = ooc_notes_likes
new_mob.ooc_notes_dislikes = ooc_notes_dislikes
new_mob.digestable = digestable
new_mob.devourable = devourable
new_mob.absorbable = absorbable
new_mob.feeding = feeding
new_mob.can_be_drop_prey = can_be_drop_prey
new_mob.can_be_drop_pred = can_be_drop_pred
new_mob.digest_leave_remains = digest_leave_remains
new_mob.allowmobvore = allowmobvore
new_mob.permit_healbelly = permit_healbelly
new_mob.noisy = noisy
new_mob.selective_preference = selective_preference
new_mob.appendage_color = appendage_color
new_mob.appendage_alt_setting = appendage_alt_setting
new_mob.drop_vore = drop_vore
new_mob.stumble_vore = stumble_vore
new_mob.slip_vore = slip_vore
new_mob.throw_vore = throw_vore
new_mob.food_vore = food_vore
new_mob.consume_liquid_belly = consume_liquid_belly
new_mob.resizable = resizable
new_mob.show_vore_fx = show_vore_fx
new_mob.step_mechanics_pref = step_mechanics_pref
new_mob.pickup_pref = pickup_pref
new_mob.vore_taste = vore_taste
new_mob.vore_smell = vore_smell
new_mob.nutrition_message_visible = nutrition_message_visible
new_mob.allow_spontaneous_tf = allow_spontaneous_tf
new_mob.eating_privacy_global = eating_privacy_global
new_mob.allow_mimicry = allow_mimicry
new_mob.text_warnings = text_warnings
new_mob.allow_mind_transfer = allow_mind_transfer
new_mob.phase_vore = phase_vore
new_mob.latejoin_vore = latejoin_vore
new_mob.latejoin_prey = latejoin_prey
new_mob.receive_reagents = receive_reagents
new_mob.give_reagents = give_reagents
new_mob.apply_reagents = apply_reagents
new_mob.autotransferable = autotransferable
new_mob.strip_pref = strip_pref
new_mob.vore_sprite_color = vore_sprite_color
new_mob.vore_sprite_multiply = vore_sprite_multiply
new_mob.noisy_full = noisy_full
new_mob.no_latejoin_vore_warning = no_latejoin_vore_warning
new_mob.no_latejoin_prey_warning = no_latejoin_prey_warning
new_mob.no_latejoin_vore_warning_time = no_latejoin_vore_warning_time
new_mob.no_latejoin_prey_warning_time = no_latejoin_prey_warning_time
new_mob.no_latejoin_vore_warning_persists = no_latejoin_vore_warning_persists
new_mob.no_latejoin_prey_warning_persists = no_latejoin_prey_warning_persists
new_mob.belly_rub_target = belly_rub_target
new_mob.soulcatcher_pref_flags = soulcatcher_pref_flags
VORE_PREF_TRANSFER(new_mob, src)
// Requires a /mob/living type path for transformation. Returns the new mob on success, null in all other cases.
// Just handles mob TF right now, but maybe we'll want to do something similar for items in the future.
+3
View File
@@ -33,6 +33,9 @@ export const setupPanelFocusHacks = () => {
if (dist >= MIN_SELECTION_DISTANCE) {
focusStolen = true;
}
if (document.activeElement?.className.includes('Button')) {
focusStolen = true;
}
}
if (!focusStolen) {
deferredFocusMap();
@@ -2,12 +2,13 @@ import { useBackend } from 'tgui/backend';
import { Data } from './types';
import { generateBellyString } from './VorePanelExportBellyString';
import { generateSoulcatcherString } from './VorePanelExportSoulcatcherString';
import { getCurrentTimestamp } from './VorePanelExportTimestamp';
export const downloadPrefs = (extension: string) => {
const { data } = useBackend<Data>();
const { db_version, db_repo, mob_name, bellies } = data;
const { db_version, db_repo, mob_name, bellies, soulcatcher } = data;
if (!bellies) {
return;
@@ -51,6 +52,11 @@ export const downloadPrefs = (extension: string) => {
type: 'text/html',
});
});
if (soulcatcher) {
blob = new Blob([blob, generateSoulcatcherString(soulcatcher)], {
type: 'text/html',
});
}
blob = new Blob(
[
blob,
@@ -63,7 +69,12 @@ export const downloadPrefs = (extension: string) => {
}
if (extension === '.vrdb') {
blob = new Blob([JSON.stringify(bellies)], { type: 'application/json' });
blob = new Blob(
[JSON.stringify({ bellies: bellies, soulcatcher: soulcatcher })],
{
type: 'application/json',
},
);
}
Byond.saveBlob(blob, filename, extension);
@@ -0,0 +1,53 @@
import { SoulcatcherSettingsFlag } from './constants';
import type { Soulcatcher } from './types';
// prettier-ignore
export const generateSoulcatcherString = (soulcatcher: Soulcatcher) => {
const { name, inside_flavor, capture_message, transit_message, release_message, transfer_message, delete_message, linked_belly, setting_flags } = soulcatcher;
const index = "sc_1";
let result = '';
result += '<div class="accordion-item"><h2 class="accordion-header" id="heading' + index + '">';
result += '<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse' + index + '" aria-expanded="false" aria-controls="collapse' + index + '">';
result += name + " (Soulcatcher)";
result += '</button></h2>';
result += '<div id="collapse' + index + '" class="accordion-collapse collapse" aria-labelledby="heading' + index + '" data-bs-parent="#accordionBellies">';
result += '<div class="accordion-body">';
result += '<b>== Settings ==</b><br>';
const arr = new Array();
let parsedFlag = setting_flags;
while(parsedFlag !== 0) {
arr.push(String(parsedFlag));
parsedFlag = Math.floor(parsedFlag / 2);
}
for(const flag in SoulcatcherSettingsFlag) {
if(arr.includes(flag)) {
result += '<span class="badge text-bg-success">' + SoulcatcherSettingsFlag[flag] + '</span>';
} else {
result += '<span class="badge text-bg-danger">' + SoulcatcherSettingsFlag[flag] + '</span>';
}
}
result += '<br><hr>';
result += '<b>== Descriptions ==</b><br>';
result += 'Inside Flavor:<br>' + inside_flavor + '<br><br>';
result += 'Capture Message:<br>' + capture_message + '<br><br>';
result += 'Transit Message:<br>' + transit_message + '<br><br>';
result += 'Release Message:<br>' + release_message + '<br><br>';
result += 'Transfer Message:<br>' + transfer_message + '<br><br>';
result += 'Delete Message:<br>' + delete_message + '<br><br>';
result += 'Linked Belly:<br>' + linked_belly + '<br><br>';
result += '</div></div>';
result += '</div>'; // End Div messagesTabpanel
result += '</div></div></div>';
return result;
};
@@ -60,3 +60,17 @@ export const AutotransferFlagIcon = {
'Clothes and Bags': '',
Food: '',
};
export const SoulcatcherSettingsFlag = {
'1': 'Catch User',
'2': 'Catch Prey',
'4': 'Ext. hearing',
'8': 'Ext. Vision',
'16': 'Mind Backup',
'32': 'SR Projecting',
'64': 'Catch Ghost',
'128': 'Soulcatcher On',
'256': 'Show SFX',
'512': 'Catch Drain',
'1024': 'SR Vision',
};
@@ -5,6 +5,7 @@ export type Data = {
db_repo: string;
mob_name: string;
bellies?: Belly[];
soulcatcher?: Soulcatcher;
};
export type Belly = {
@@ -218,3 +219,15 @@ export type Belly = {
fullness4_messages: string[];
fullness5_messages: string[];
};
export type Soulcatcher = {
name: string;
inside_flavor: string;
capture_message: string;
transit_message: string;
release_message: string;
transfer_message: string;
delete_message: string;
linked_belly: string;
setting_flags: number;
};
+2
View File
@@ -167,6 +167,7 @@
#include "code\__defines\verb_manager.dm"
#include "code\__defines\visualnet.dm"
#include "code\__defines\vore.dm"
#include "code\__defines\vore_prefs.dm"
#include "code\__defines\vote.dm"
#include "code\__defines\vv.dm"
#include "code\__defines\webhooks.dm"
@@ -4374,6 +4375,7 @@
#include "code\modules\vore\eating\simple_animal_vr.dm"
#include "code\modules\vore\eating\slipvore_vr.dm"
#include "code\modules\vore\eating\soulcatcher.dm"
#include "code\modules\vore\eating\soulcatcher_import.dm"
#include "code\modules\vore\eating\soulcatcher_mob.dm"
#include "code\modules\vore\eating\soulcatcher_observer.dm"
#include "code\modules\vore\eating\stumblevore_vr.dm"