Merge remote-tracking branch 'upstream/master'

This commit is contained in:
keronshb
2021-07-19 22:14:20 -04:00
44 changed files with 130022 additions and 129616 deletions
File diff suppressed because it is too large Load Diff
+1
View File
@@ -101,6 +101,7 @@
#define NO_AUTO_WAG (1<<12)
#define GENITAL_EXAMINE (1<<13)
#define VORE_EXAMINE (1<<14)
#define TRASH_FORCEFEED (1<<15)
#define TOGGLES_CITADEL 0
//belly sound pref things
-1
View File
@@ -81,7 +81,6 @@
#define CAT_AMMO "Ammunition"
#define CAT_PARTS "Weapon Parts"
#define CAT_ROBOT "Robots"
#define CAT_MISC "Misc"
#define CAT_MISCELLANEOUS "Miscellaneous"
#define CAT_TOOL "Tools & Storage"
#define CAT_FURNITURE "Furniture"
+12
View File
@@ -159,6 +159,18 @@
#define TINT_DARKENED 2 //Threshold of tint level to apply weld mask overlay
#define TINT_BLIND 3 //Threshold of tint level to obscure vision fully
// defines for AFK theft
/// How many messages you can remember while logged out before you stop remembering new ones
#define AFK_THEFT_MAX_MESSAGES 10
/// If someone logs back in and there are entries older than this, just tell them they can't remember who it was or when
#define AFK_THEFT_FORGET_DETAILS_TIME 5 MINUTES
/// The index of the entry in 'afk_thefts' with the person's visible name at the time
#define AFK_THEFT_NAME 1
/// The index of the entry in 'afk_thefts' with the text
#define AFK_THEFT_MESSAGE 2
/// The index of the entry in 'afk_thefts' with the time it happened
#define AFK_THEFT_TIME 3
//Allowed equipment lists for security vests and hardsuits.
GLOBAL_LIST_INIT(advanced_hardsuit_allowed, typecacheof(list(
+1
View File
@@ -221,6 +221,7 @@
#define TRAIT_LIVING_NO_DENSITY "living_no_density"
/// forces us to not render our overlays
#define TRAIT_HUMAN_NO_RENDER "human_no_render"
#define TRAIT_TRASHCAN "trashcan"
// 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)
+15 -10
View File
@@ -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)
+2
View File
@@ -19,6 +19,8 @@
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= length(L) ? L[I] : null) : L[I]) : null)
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
#define LAZYLEN(L) length(L)
//Sets a list to null
#define LAZYNULL(L) L = null
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
#define reverseList(L) reverseRange(L.Copy())
@@ -112,6 +112,7 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/storage/box/marshmallow = 2,
/obj/item/clothing/gloves/tackler/offbrand = 1,
/obj/item/stack/sticky_tape = 1,
/obj/effect/spawner/lootdrop/grille_or_trash = 15,
"" = 3
))
-491
View File
@@ -1,491 +0,0 @@
/datum/component/personal_crafting/Initialize()
if(!ismob(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN, .proc/create_mob_button)
/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/CL)
var/datum/hud/H = user.hud_used
var/obj/screen/craft/C = new()
C.icon = H.ui_style
H.static_inventory += C
if(!CL.prefs.widescreenpref)
C.screen_loc = ui_boxcraft
CL.screen += C
RegisterSignal(C, COMSIG_CLICK, .proc/component_ui_interact)
/datum/component/personal_crafting
var/busy
var/viewing_category = 1
var/viewing_subcategory = 1
var/list/categories = list(
CAT_WEAPONRY = list(
CAT_WEAPON,
CAT_AMMO,
),
CAT_ROBOT = CAT_NONE,
CAT_MISC = list(
CAT_MISCELLANEOUS,
CAT_TOOL,
CAT_FURNITURE,
),
CAT_PRIMAL = CAT_NONE,
CAT_FOOD = list(
CAT_BREAD,
CAT_BURGER,
CAT_CAKE,
CAT_DONUT,
CAT_EGG,
CAT_ICE,
CAT_MEAT,
CAT_MEXICAN,
CAT_MISCFOOD,
CAT_PASTRY,
CAT_PIE,
CAT_PIZZA,
CAT_SEAFOOD,
CAT_SALAD,
CAT_SANDWICH,
CAT_SOUP,
CAT_SPAGHETTI,
),
CAT_DRINK = CAT_NONE,
CAT_CLOTHING = CAT_NONE,
)
var/cur_category = CAT_NONE
var/cur_subcategory = CAT_NONE
var/datum/action/innate/crafting/button
var/display_craftable_only = FALSE
var/display_compact = TRUE
/* This is what procs do:
get_environment - gets a list of things accessable for crafting by user
get_surroundings - takes a list of things and makes a list of key-types to values-amounts of said type in the list
check_contents - takes a recipe and a key-type list and checks if said recipe can be done with available stuff
check_tools - takes recipe, a key-type list, and a user and checks if there are enough tools to do the stuff, checks bugs one level deep
construct_item - takes a recipe and a user, call all the checking procs, calls do_after, checks all the things again, calls del_reqs, creates result, calls CheckParts of said result with argument being list returned by deel_reqs
del_reqs - takes recipe and a user, loops over the recipes reqs var and tries to find everything in the list make by get_environment and delete it/add to parts list, then returns the said list
*/
/**
* Check that the contents of the recipe meet the requirements.
*
* user: The /mob that initated the crafting.
* R: The /datum/crafting_recipe being attempted.
* contents: List of items to search for R's reqs.
*/
/datum/component/personal_crafting/proc/check_contents(mob/user, datum/crafting_recipe/R, list/contents)
var/list/item_instances = contents["instances"]
contents = contents["other"]
var/list/requirements_list = list()
// Process all requirements
for(var/requirement_path in R.reqs)
// Check we have the appropriate amount available in the contents list
var/needed_amount = R.reqs[requirement_path]
for(var/content_item_path in contents)
// Right path and not blacklisted
if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(requirement_path))
continue
needed_amount -= contents[content_item_path]
if(needed_amount <= 0)
break
if(needed_amount > 0)
return FALSE
// Store the instances of what we will use for R.check_requirements() for requirement_path
var/list/instances_list = list()
for(var/instance_path in item_instances)
if(ispath(instance_path, requirement_path))
instances_list += item_instances[instance_path]
requirements_list[requirement_path] = instances_list
for(var/requirement_path in R.chem_catalysts)
if(contents[requirement_path] < R.chem_catalysts[requirement_path])
return FALSE
return R.check_requirements(user, requirements_list)
/datum/component/personal_crafting/proc/get_environment(mob/user)
. = list()
for(var/obj/item/I in user.held_items)
. += I
if(!isturf(user.loc))
return
var/list/L = block(get_step(user, SOUTHWEST), get_step(user, NORTHEAST))
for(var/A in L)
var/turf/T = A
if(T.Adjacent(user))
for(var/B in T)
var/atom/movable/AM = B
if(AM.flags_1 & HOLOGRAM_1)
continue
. += AM
for(var/slot in list(SLOT_R_STORE, SLOT_L_STORE))
. += user.get_item_by_slot(slot)
/datum/component/personal_crafting/proc/get_surroundings(mob/user)
. = list()
.["tool_behaviour"] = list()
.["other"] = list()
.["instances"] = list()
for(var/obj/item/I in get_environment(user))
if(I.flags_1 & HOLOGRAM_1)
continue
if(.["instances"][I.type])
.["instances"][I.type] += I
else
.["instances"][I.type] = list(I)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
.["other"][I.type] += S.amount
else if(I.tool_behaviour)
.["tool_behaviour"] += I.tool_behaviour
.["other"][I.type] += 1
else
if(istype(I, /obj/item/reagent_containers))
var/obj/item/reagent_containers/RC = I
if(RC.is_drainable())
for(var/datum/reagent/A in RC.reagents.reagent_list)
.["other"][A.type] += A.volume
.["other"][I.type] += 1
/datum/component/personal_crafting/proc/check_tools(mob/user, datum/crafting_recipe/R, list/contents)
if(!R.tools.len)
return TRUE
var/list/possible_tools = list()
var/list/present_qualities = list()
present_qualities |= contents["tool_behaviour"]
for(var/obj/item/I in user.contents)
if(istype(I, /obj/item/storage))
for(var/obj/item/SI in I.contents)
possible_tools += SI.type
if(SI.tool_behaviour)
present_qualities.Add(SI.tool_behaviour)
possible_tools += I.type
if(I.tool_behaviour)
present_qualities.Add(I.tool_behaviour)
possible_tools |= contents["other"]
main_loop:
for(var/A in R.tools)
if(A in present_qualities)
continue
else
for(var/I in possible_tools)
if(ispath(I, A))
continue main_loop
return FALSE
return TRUE
/datum/component/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R)
var/list/contents = get_surroundings(user)
var/send_feedback = TRUE
if(check_contents(user, R, contents))
if(check_tools(user, R, contents))
if(do_after(user, R.time, target = user))
contents = get_surroundings(user)
if(!check_contents(user, R, contents))
return ", missing component."
if(!check_tools(user, R, contents))
return ", missing tool."
var/list/parts = del_reqs(R, user)
var/atom/movable/I = new R.result (get_turf(user.loc))
I.CheckParts(parts, R)
if(isitem(I))
if(isfood(I))
var/obj/item/reagent_containers/food/food_result = I
var/total_quality = 0
var/total_items = 0
for(var/obj/item/reagent_containers/food/ingredient in parts)
total_items += 1
total_quality += ingredient.food_quality
if(total_items == 0)
food_result.adjust_food_quality(50)
else
food_result.adjust_food_quality(total_quality / total_items)
user.put_in_hands(I)
if(send_feedback)
SSblackbox.record_feedback("tally", "object_crafted", 1, I.type)
log_craft("[I] crafted by [user] at [loc_name(I.loc)]")
return FALSE
return "."
return ", missing tool."
return ", missing component."
/*Del reqs works like this:
Loop over reqs var of the recipe
Set var amt to the value current cycle req is pointing to, its amount of type we need to delete
Get var/surroundings list of things accessable to crafting by get_environment()
Check the type of the current cycle req
If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isnt remove thing from surroundings
If there is enough reagent in the search result then delete the needed amount, create the same type of reagent with the same data var and put it into deletion list
If there isnt enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching
While doing above stuff check deletion list if it already has such reagnet, if yes merge instead of adding second one
If its stack check if it has enough amount
If yes create new stack with the needed amount and put in into deletion list, substract taken amount from the stack
If no put all of the stack in the deletion list, substract its amount from amt and keep searching
While doing above stuff check deletion list if it already has such stack type, if yes try to merge them instead of adding new one
If its anything else just locate() in in the list in a while loop, each find --s the amt var and puts the found stuff in deletion loop
Then do a loop over parts var of the recipe
Do similar stuff to what we have done above, but now in deletion list, until the parts conditions are satisfied keep taking from the deletion list and putting it into parts list for return
After its done loop over deletion list and delete all the shit that wasnt taken by parts loop
del_reqs return the list of parts resulting object will receive as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already
*/
/datum/component/personal_crafting/proc/del_reqs(datum/crafting_recipe/R, mob/user)
var/list/surroundings
var/list/Deletion = list()
. = list()
var/data
var/amt
main_loop:
for(var/A in R.reqs)
amt = R.reqs[A]
surroundings = get_environment(user)
surroundings -= Deletion
if(ispath(A, /datum/reagent))
var/datum/reagent/RG = new A
var/datum/reagent/RGNT
while(amt > 0)
var/obj/item/reagent_containers/RC = locate() in surroundings
RG = RC.reagents.get_reagent(A)
if(RG)
if(!locate(RG.type) in Deletion)
Deletion += new RG.type()
if(RG.volume > amt)
RG.volume -= amt
data = RG.data
RC.reagents.conditional_update(RC)
RG = locate(RG.type) in Deletion
RG.volume = amt
RG.data += data
continue main_loop
else
surroundings -= RC
amt -= RG.volume
RC.reagents.reagent_list -= RG
RC.reagents.conditional_update(RC)
RGNT = locate(RG.type) in Deletion
RGNT.volume += RG.volume
RGNT.data += RG.data
qdel(RG)
RC.on_reagent_change()
else
surroundings -= RC
else if(ispath(A, /obj/item/stack))
var/obj/item/stack/S
var/obj/item/stack/SD
while(amt > 0)
S = locate(A) in surroundings
if(S.amount >= amt)
if(!locate(S.type) in Deletion)
SD = new S.type()
Deletion += SD
S.use(amt)
SD = locate(S.type) in Deletion
SD.amount += amt
continue main_loop
else
amt -= S.amount
if(!locate(S.type) in Deletion)
Deletion += S
else
data = S.amount
S = locate(S.type) in Deletion
S.add(data)
surroundings -= S
else
var/atom/movable/I
while(amt > 0)
I = locate(A) in surroundings
Deletion += I
surroundings -= I
amt--
var/list/partlist = list(R.parts.len)
for(var/M in R.parts)
partlist[M] = R.parts[M]
for(var/A in R.parts)
if(istype(A, /datum/reagent))
var/datum/reagent/RG = locate(A) in Deletion
if(RG.volume > partlist[A])
RG.volume = partlist[A]
. += RG
Deletion -= RG
continue
else if(istype(A, /obj/item/stack))
var/obj/item/stack/ST = locate(A) in Deletion
if(ST.amount > partlist[A])
ST.amount = partlist[A]
. += ST
Deletion -= ST
continue
else
while(partlist[A] > 0)
var/atom/movable/AM = locate(A) in Deletion
. += AM
Deletion -= AM
partlist[A] -= 1
while(Deletion.len)
var/DL = Deletion[Deletion.len]
Deletion.Cut(Deletion.len)
qdel(DL)
/datum/component/personal_crafting/proc/component_ui_interact(obj/screen/craft/image, location, control, params, user)
if(user == parent)
ui_interact(user)
/datum/component/personal_crafting/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_turf_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
cur_category = categories[1]
if(islist(categories[cur_category]))
var/list/subcats = categories[cur_category]
cur_subcategory = subcats[1]
else
cur_subcategory = CAT_NONE
ui = new(user, src, ui_key, "personal_crafting", "Crafting Menu", 700, 800, master_ui, state)
ui.open()
/datum/component/personal_crafting/ui_data(mob/user)
var/list/data = list()
data["busy"] = busy
data["category"] = cur_category
data["subcategory"] = cur_subcategory
data["display_craftable_only"] = display_craftable_only
data["display_compact"] = display_compact
var/list/surroundings = get_surroundings(user)
var/list/craftability = list()
for(var/rec in GLOB.crafting_recipes)
var/datum/crafting_recipe/R = rec
if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
continue
if((R.category != cur_category) || (R.subcategory != cur_subcategory))
continue
craftability["[REF(R)]"] = check_contents(user, R, surroundings)
data["craftability"] = craftability
return data
/datum/component/personal_crafting/ui_static_data(mob/user)
var/list/data = list()
var/list/crafting_recipes = list()
for(var/rec in GLOB.crafting_recipes)
var/datum/crafting_recipe/R = rec
if(R.name == "") //This is one of the invalid parents that sneaks in
continue
if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
continue
if(isnull(crafting_recipes[R.category]))
crafting_recipes[R.category] = list()
if(R.subcategory == CAT_NONE)
crafting_recipes[R.category] += list(build_recipe_data(R))
else
if(isnull(crafting_recipes[R.category][R.subcategory]))
crafting_recipes[R.category][R.subcategory] = list()
crafting_recipes[R.category]["has_subcats"] = TRUE
crafting_recipes[R.category][R.subcategory] += list(build_recipe_data(R))
data["crafting_recipes"] = crafting_recipes
return data
/datum/component/personal_crafting/ui_act(action, params)
if(..())
return
switch(action)
if("make")
var/datum/crafting_recipe/TR = locate(params["recipe"]) in GLOB.crafting_recipes
ui_interact(usr)
if(busy)
to_chat(usr, "<span class='warning'>You are already making something!</span>")
return
busy = TRUE
var/fail_msg = construct_item(usr, TR)
if(!fail_msg)
to_chat(usr, "<span class='notice'>[TR.name] constructed.</span>")
else
to_chat(usr, "<span class='warning'>Construction failed[fail_msg]</span>")
busy = FALSE
if("toggle_recipes")
display_craftable_only = !display_craftable_only
. = TRUE
if("toggle_compact")
display_compact = !display_compact
. = TRUE
if("set_category")
if(!isnull(params["category"]))
cur_category = params["category"]
if(!isnull(params["subcategory"]))
if(params["subcategory"] == "0")
cur_subcategory = ""
else
cur_subcategory = params["subcategory"]
. = TRUE
/datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R)
var/list/data = list()
data["name"] = R.name
data["ref"] = "[REF(R)]"
var/req_text = ""
var/tool_text = ""
var/catalyst_text = ""
for(var/a in R.reqs)
//We just need the name, so cheat-typecast to /atom for speed (even tho Reagents are /datum they DO have a "name" var)
//Also these are typepaths so sadly we can't just do "[a]"
var/atom/A = a
req_text += " [R.reqs[A]] [initial(A.name)],"
req_text = replacetext(req_text,",","",-1)
data["req_text"] = req_text
for(var/a in R.chem_catalysts)
var/atom/A = a //cheat-typecast
catalyst_text += " [R.chem_catalysts[A]] [initial(A.name)],"
catalyst_text = replacetext(catalyst_text,",","",-1)
data["catalyst_text"] = catalyst_text
for(var/a in R.tools)
if(ispath(a, /obj/item))
var/obj/item/b = a
tool_text += " [initial(b.name)],"
else
tool_text += " [a],"
tool_text = replacetext(tool_text,",","",-1)
data["tool_text"] = tool_text
return data
//Mind helpers
/datum/mind/proc/teach_crafting_recipe(R)
if(!learned_recipes)
learned_recipes = list()
learned_recipes |= R
+5 -1
View File
@@ -4,6 +4,10 @@
/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/CL)
var/datum/hud/H = user.hud_used
for(var/huds in H.static_inventory)
if(istype(huds, /obj/screen/craft))
return
//We don't want to be stacking multiple crafting huds on relogs
var/obj/screen/craft/C = new()
C.icon = H.ui_style
H.static_inventory += C
@@ -20,7 +24,7 @@
CAT_AMMO,
),
CAT_ROBOT = CAT_NONE,
CAT_MISC = list(
CAT_MISCELLANEOUS = list(
CAT_MISCELLANEOUS,
CAT_TOOL,
CAT_FURNITURE,
@@ -8,7 +8,7 @@
time = 1
reqs = list(/obj/item/stack/sheet/plastic = 1,
/obj/item/stack/sheet/mineral/wood = 1)
category = CAT_MISC
category = CAT_MISCELLANEOUS
subcategory = CAT_TOOL
/datum/crafting_recipe/showercurtain
@@ -18,7 +18,7 @@
/obj/item/stack/rods = 1)
result = /obj/structure/curtain
subcategory = CAT_FURNITURE
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/guillotine
name = "Guillotine"
@@ -29,7 +29,7 @@
/obj/item/stack/cable_coil = 10)
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/femur_breaker
name = "Femur Breaker"
@@ -39,7 +39,7 @@
/obj/item/stack/cable_coil = 30)
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
// Blood Sucker stuff //
/datum/crafting_recipe/bloodsucker/blackcoffin
@@ -54,7 +54,7 @@
///obj/item/pipe = 2)
time = 150
subcategory = CAT_FURNITURE
category = CAT_MISC
category = CAT_MISCELLANEOUS
always_availible = TRUE
/datum/crafting_recipe/bloodsucker/meatcoffin
@@ -66,7 +66,7 @@
/obj/item/restraints/handcuffs/cable = 1)
time = 150
subcategory = CAT_FURNITURE
category = CAT_MISC
category = CAT_MISCELLANEOUS
always_availible = TRUE
/datum/crafting_recipe/bloodsucker/metalcoffin
@@ -77,7 +77,7 @@
reqs = list(/obj/item/stack/sheet/metal = 5)
time = 100
subcategory = CAT_FURNITURE
category = CAT_MISC
category = CAT_MISCELLANEOUS
always_availible = TRUE
/datum/crafting_recipe/bloodsucker/vassalrack
@@ -100,7 +100,7 @@
// )
time = 150
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
always_availible = FALSE // Disabled until learned
@@ -117,7 +117,7 @@
)
time = 100
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
always_availible = FALSE // Disabled til learned
/datum/crafting_recipe/furnace
@@ -129,7 +129,7 @@
/obj/item/stack/rods = 2)
tools = list(TOOL_CROWBAR)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/tableanvil
name = "Table Anvil"
@@ -139,7 +139,7 @@
/obj/item/stack/rods = 2)
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/sandvil
name = "Sandstone Anvil"
@@ -148,7 +148,7 @@
reqs = list(/obj/item/stack/sheet/mineral/sandstone = 24)
tools = list(TOOL_CROWBAR)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/basaltblock
name = "Sintered Basalt Block"
@@ -157,7 +157,7 @@
reqs = list(/obj/item/stack/ore/glass/basalt = 50)
tools = list(TOOL_WELDER)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/basaltanvil
name = "Basalt Anvil"
@@ -166,7 +166,7 @@
reqs = list(/obj/item/basaltblock = 5)
tools = list(TOOL_CROWBAR)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
///////////////////
//Tools & Storage//
///////////////////
@@ -177,7 +177,7 @@
time = 1
reqs = list(/obj/item/stack/medical/gauze = 1,
/datum/reagent/space_cleaner/sterilizine = 5)
category = CAT_MISC
category = CAT_MISCELLANEOUS
subcategory = CAT_TOOL
/datum/crafting_recipe/brute_pack
@@ -186,7 +186,7 @@
time = 1
reqs = list(/obj/item/stack/medical/gauze/adv = 1,
/datum/reagent/medicine/styptic_powder = 10)
category = CAT_MISC
category = CAT_MISCELLANEOUS
subcategory = CAT_TOOL
/datum/crafting_recipe/burn_pack
@@ -195,7 +195,7 @@
time = 1
reqs = list(/obj/item/stack/medical/gauze/adv = 1,
/datum/reagent/medicine/silver_sulfadiazine = 10)
category = CAT_MISC
category = CAT_MISCELLANEOUS
subcategory = CAT_TOOL
/datum/crafting_recipe/ghettojetpack
@@ -206,7 +206,7 @@
/obj/item/extinguisher = 1,
/obj/item/pipe = 3,
/obj/item/stack/cable_coil = 30)
category = CAT_MISC
category = CAT_MISCELLANEOUS
subcategory = CAT_TOOL
tools = list(TOOL_WRENCH, TOOL_WELDER, TOOL_WIRECUTTER)
@@ -220,7 +220,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/toolboxhammer
name = "Toolbox Hammer"
@@ -231,7 +231,7 @@
/obj/item/stack/rods = 2)
time = 40
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/papersack
name = "Paper Sack"
@@ -239,7 +239,7 @@
time = 10
reqs = list(/obj/item/paper = 5)
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/smallcarton
name = "Small Carton"
@@ -247,7 +247,7 @@
time = 10
reqs = list(/obj/item/stack/sheet/cardboard = 1)
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bronze_driver
name = "Bronze Plated Screwdriver"
@@ -259,7 +259,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bronze_welder
name = "Bronze Plated Welding Tool"
@@ -271,7 +271,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bronze_wirecutters
name = "Bronze Plated Wirecutters"
@@ -283,7 +283,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bronze_crowbar
name = "Bronze Plated Crowbar"
@@ -295,7 +295,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bronze_wrench
name = "Bronze Plated Wrench"
@@ -307,7 +307,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/rcl
name = "Makeshift Rapid Cable Layer"
@@ -316,7 +316,7 @@
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WRENCH)
reqs = list(/obj/item/stack/sheet/metal = 15)
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/picket_sign
name = "Picket Sign"
@@ -325,7 +325,7 @@
/obj/item/stack/sheet/cardboard = 2)
time = 80
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/electrochromatic_kit
name = "Electrochromatic Kit"
@@ -334,7 +334,7 @@
/obj/item/stack/cable_coil = 1)
time = 5
subcategory = CAT_TOOL
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/blackmarket_uplink
name = "Black Market Uplink"
@@ -346,7 +346,7 @@
/obj/item/radio = 1,
/obj/item/analyzer = 1)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/heretic/codex
name = "Codex Cicatrix"
@@ -358,7 +358,7 @@
/obj/item/stack/sheet/animalhide/human = 1)
time = 150
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
always_availible = FALSE
////////////
@@ -372,7 +372,7 @@
/obj/item/stack/rods = 8)
time = 100
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/motorized_wheelchair
name = "Hoverchair"
@@ -386,7 +386,7 @@
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WRENCH)
time = 200
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/skateboard
name = "Skateboard"
@@ -395,7 +395,7 @@
reqs = list(/obj/item/stack/sheet/metal = 5,
/obj/item/stack/rods = 10)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/scooter
name = "Scooter"
@@ -404,7 +404,7 @@
reqs = list(/obj/item/stack/sheet/metal = 5,
/obj/item/stack/rods = 12)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/////////
//Toys///
@@ -415,28 +415,28 @@
reqs = list(/obj/item/light/bulb = 1, /obj/item/stack/cable_coil = 1, /obj/item/stack/sheet/plastic = 4)
result = /obj/item/toy/sword
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/extendohand
name = "Extendo-Hand"
reqs = list(/obj/item/bodypart/r_arm/robot = 1, /obj/item/clothing/gloves/boxing = 1)
result = /obj/item/extendohand
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/toyneb
name = "Non-Euplastic Blade"
reqs = list(/obj/item/light/tube = 1, /obj/item/stack/cable_coil = 1, /obj/item/stack/sheet/plastic = 4)
result = /obj/item/toy/sword/cx
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/catgirlplushie
name = "Catgirl Plushie"
reqs = list(/obj/item/toy/plush/hairball = 3)
result = /obj/item/toy/plush/catgirl
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
////////////
//Unsorted//
@@ -450,7 +450,7 @@
reqs = list(/obj/item/stack/sheet/mineral/wood = 1)
result = /obj/item/stick
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/swordhilt
@@ -459,14 +459,14 @@
reqs = list(/obj/item/stack/sheet/mineral/wood = 2)
result = /obj/item/swordhandle
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/blackcarpet
name = "Black Carpet"
reqs = list(/obj/item/stack/tile/carpet = 50, /obj/item/toy/crayon/black = 1)
result = /obj/item/stack/tile/carpet/black/fifty
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/paperframes
name = "Paper Frames"
@@ -474,7 +474,7 @@
time = 10
reqs = list(/obj/item/stack/sheet/mineral/wood = 5, /obj/item/paper = 20)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/naturalpaper
name = "Hand-Pressed Paper"
@@ -483,7 +483,7 @@
tools = list(/obj/item/hatchet)
result = /obj/item/paper_bin/bundlenatural
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bluespacehonker
name = "Bluespace Bike horn"
@@ -493,7 +493,7 @@
/obj/item/toy/crayon/blue = 1,
/obj/item/bikehorn = 1)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/mousetrap
name = "Mouse Trap"
@@ -502,7 +502,7 @@
reqs = list(/obj/item/stack/sheet/cardboard = 1,
/obj/item/stack/rods = 1)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/flashlight_eyes
name = "Flashlight Eyes"
@@ -513,7 +513,7 @@
/obj/item/restraints/handcuffs/cable = 1
)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/pressureplate
name = "Pressure Plate"
@@ -524,7 +524,7 @@
/obj/item/stack/cable_coil = 2,
/obj/item/assembly/igniter = 1)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/gold_horn
name = "Golden Bike Horn"
@@ -533,7 +533,7 @@
reqs = list(/obj/item/stack/sheet/mineral/bananium = 5,
/obj/item/bikehorn = 1)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/spooky_camera
name = "Camera Obscura"
@@ -543,7 +543,7 @@
/datum/reagent/water/holywater = 10)
parts = list(/obj/item/camera = 1)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/coconut_bong
name = "Coconut Bong"
@@ -552,7 +552,7 @@
/obj/item/reagent_containers/food/snacks/grown/coconut = 1)
time = 70
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
category = CAT_MISCELLANEOUS
//////////////
//Banners/////
@@ -565,7 +565,7 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/captain/parade = 1)
subcategory = CAT_FURNITURE
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/engineering_banner
name = "Engitopia Banner"
@@ -574,7 +574,7 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/engineering/engineer = 1)
subcategory = CAT_FURNITURE
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/cargo_banner
name = "Cargonia Banner"
@@ -583,7 +583,7 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/cargo/tech = 1)
subcategory = CAT_FURNITURE
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/science_banner
name = "Sciencia Banner"
@@ -592,7 +592,7 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/rnd/scientist = 1)
subcategory = CAT_FURNITURE
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/medical_banner
name = "Meditopia Banner"
@@ -601,7 +601,7 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/medical/doctor = 1)
subcategory = CAT_FURNITURE
category = CAT_MISC
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/security_banner
name = "Securistan Banner"
@@ -610,4 +610,4 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/security/officer = 1)
subcategory = CAT_FURNITURE
category = CAT_MISC
category = CAT_MISCELLANEOUS
+1 -1
View File
@@ -59,7 +59,7 @@
var/mob/living/L = AM
if(L.stat == DEAD)
continue
if(light_nutrition_gain)
if(light_nutrition_gain && L.nutrition < NUTRITION_LEVEL_WELL_FED)
L.adjust_nutrition(light_amount * light_nutrition_gain * attached_atoms[AM], NUTRITION_LEVEL_WELL_FED)
if(light_amount > bonus_lum || light_amount < malus_lum)
var/mult = ((light_amount > bonus_lum) ? 1 : -1) * attached_atoms[AM]
+19
View File
@@ -0,0 +1,19 @@
/datum/element/trash
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
/datum/element/trash/Attach(datum/target)
. = ..()
RegisterSignal(target, COMSIG_ITEM_ATTACK, .proc/UseFromHand)
/datum/element/trash/proc/UseFromHand(obj/item/source, mob/living/M, mob/living/user)
if((M == user || user.vore_flags & TRASH_FORCEFEED) && ishuman(user))
var/mob/living/carbon/human/H = user
if(HAS_TRAIT(H, TRAIT_TRASHCAN))
playsound(H.loc,'sound/items/eatfood.ogg', rand(10,50), 1)
if(H.vore_selected)
H.visible_message("<span class='notice'>[H] [H.vore_selected.vore_verb]s the [source] into their [H.vore_selected]</span>",
"<span class='notice'>You [H.vore_selected.vore_verb]s the [source] into your [H.vore_selected]</span>")
source.forceMove(H.vore_selected)
else
H.visible_message("<span class='notice'>[H] consumes the [source].")
qdel(source)
+8
View File
@@ -154,3 +154,11 @@
/datum/quirk/longtimer/on_spawn()
var/mob/living/carbon/C = quirk_holder
C.generate_fake_scars(rand(min_scars, max_scars))
/datum/quirk/trashcan
name = "Trashcan"
desc = "You are able to consume and digest trash."
value = 0
gain_text = "<span class='notice'>You feel like munching on a can of soda.</span>"
lose_text = "<span class='notice'>You no longer feel like you should be eating trash.</span>"
mob_trait = TRAIT_TRASHCAN
@@ -17,7 +17,7 @@
line = null
if(qdel_in)
QDEL_IN(PB, qdel_in)
d
/obj/effect/projectile/tracer
name = "beam"
icon = 'icons/obj/projectiles_tracer.dmi'
+4
View File
@@ -387,6 +387,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
throwforce = 0
grind_results = list(/datum/reagent/carbon = 2)
/obj/item/cigbutt/Initialize()
. = ..()
AddElement(/datum/element/trash)
/obj/item/cigbutt/cigarbutt
name = "cigar butt"
desc = "A manky old cigar butt."
@@ -13,6 +13,7 @@
GLOBAL_LIST_INIT(human_recipes, list( \
new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/hooded/bloated_human, 5), \
new/datum/stack_recipe("human skin hat", /obj/item/clothing/head/human_leather, 1), \
))
/obj/item/stack/sheet/animalhide/human/get_main_recipes()
@@ -179,6 +179,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
GLOBAL_LIST_INIT(plasteel_recipes, list ( \
new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = TRUE), \
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \
new/datum/stack_recipe("plasteel keg", /obj/structure/custom_keg, 10, time = 50), \
new/datum/stack_recipe("micro powered fan assembly", /obj/machinery/fan_assembly, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
new /datum/stack_recipe_list("crates", list( \
new /datum/stack_recipe("gray crate", /obj/structure/closet/crate, 5, time = 50, one_per_turf = 1, on_floor = 1), \
+4 -3
View File
@@ -7,6 +7,10 @@
w_class = WEIGHT_CLASS_TINY
resistance_flags = FLAMMABLE
/obj/item/trash/Initialize()
. = ..()
AddElement(/datum/element/trash)
/obj/item/trash/raisins
name = "\improper 4no raisins"
icon_state= "4no_raisins"
@@ -80,6 +84,3 @@
name = "boritos bag"
icon_state = "boritos"
grind_results = list(/datum/reagent/aluminium = 1) //from the mylar bag
/obj/item/trash/attack(mob/M, mob/living/user)
return
+27 -7
View File
@@ -48,14 +48,34 @@
return // no message spam
..()
/obj/structure/mirror/attacked_by(obj/item/I, mob/living/user)
if(broken || !istype(user) || !I.force)
return ..()
. = ..()
if(broken) // breaking a mirror truly gets you bad luck!
to_chat(user, "<span class='warning'>A chill runs down your spine as [src] shatters...</span>")
user.AddComponent(/datum/component/omen, silent=TRUE) // we have our own message
/obj/structure/mirror/bullet_act(obj/item/projectile/P)
if(broken || !isliving(P.firer) || !P.damage)
return ..()
. = ..()
if(broken) // breaking a mirror truly gets you bad luck!
var/mob/living/unlucky_dude = P.firer
to_chat(unlucky_dude, "<span class='warning'>A chill runs down your spine as [src] shatters...</span>")
unlucky_dude.AddComponent(/datum/component/omen, silent=TRUE) // we have our own message
/obj/structure/mirror/obj_break(damage_flag, mapload)
if(!broken && !(flags_1 & NODECONSTRUCT_1))
icon_state = "mirror_broke"
if(!mapload)
playsound(src, "shatter", 70, 1)
if(desc == initial(desc))
desc = "Oh no, seven years of bad luck!"
broken = TRUE
if(broken || (flags_1 & NODECONSTRUCT_1))
return
icon_state = "mirror_broke"
if(!mapload)
playsound(src, "shatter", 70, TRUE)
if(desc == initial(desc))
desc = "Oh no, seven years of bad luck!"
broken = TRUE
/obj/structure/mirror/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
+1 -1
View File
@@ -72,7 +72,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
// basic doesn't initialize and this will cause issues
// no warning though because this can happen naturaly as a result of it being built on top of
path = /turf/open/space
if(!GLOB.use_preloader && path == type && !(flags & CHANGETURF_FORCEOP)) // Don't no-op if the map loader requires it to be reconstructed
if(!GLOB.use_preloader && path == type && !(flags & CHANGETURF_FORCEOP) && (baseturfs == new_baseturfs)) // Don't no-op if the map loader requires it to be reconstructed, or if this is a new set of baseturfs
return src
if(flags & CHANGETURF_SKIP)
return new path(src)
+5
View File
@@ -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
@@ -1068,6 +1069,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Voracious MediHound sleepers:</b> <a href='?_src_=prefs;preference=hound_sleeper'>[(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]</a><br>"
dat += "<b>Hear Vore Sounds:</b> <a href='?_src_=prefs;preference=toggleeatingnoise'>[(cit_toggles & EATING_NOISES) ? "Yes" : "No"]</a><br>"
dat += "<b>Hear Vore Digestion Sounds:</b> <a href='?_src_=prefs;preference=toggledigestionnoise'>[(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]</a><br>"
dat += "<b>Allow trash forcefeeding (requires Trashcan quirk)</b> <a href='?_src_=prefs;preference=toggleforcefeedtrash'>[(cit_toggles & TRASH_FORCEFEED) ? "Yes" : "No"]</a><br>"
dat += "<b>Forced Feminization:</b> <a href='?_src_=prefs;preference=feminization'>[(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"]</a><br>"
dat += "<b>Forced Masculinization:</b> <a href='?_src_=prefs;preference=masculinization'>[(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"]</a><br>"
dat += "<b>Lewd Hypno:</b> <a href='?_src_=prefs;preference=hypno'>[(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"]</a><br>"
@@ -2800,6 +2802,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("toggledigestionnoise")
cit_toggles ^= DIGESTION_NOISES
if("toggleforcefeedtrash")
cit_toggles ^= TRASH_FORCEFEED
if("breast_enlargement")
cit_toggles ^= BREAST_ENLARGEMENT
@@ -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))
+6
View File
@@ -482,3 +482,9 @@
icon_state = "kabuto"
item_state = "kabuto"
flags_inv = HIDEHAIR|HIDEEARS
/obj/item/clothing/head/human_leather
name = "human skin hat"
desc = "This will scare them. All will know my power."
icon_state = "human_leather"
item_state = "human_leather"
+1 -1
View File
@@ -5,7 +5,7 @@
weight = 8
/datum/round_event/cat_surgeon/announce(fake)
priority_announce("One of our... ahem... 'special' cases has escaped. Our sensors now show their tracker implant on your station. On an unrelated note, has anyone seen our cats?",
priority_announce("One of our... ahem... 'special' cases has escaped. As it happens their last known location before their tracker went dead is your station so keep an eye out for them. On an unrelated note, has anyone seen our cats?",
sender_override = "Nanotrasen Psych Ward")
/datum/round_event/cat_surgeon/start()
@@ -73,3 +73,40 @@
icon_state = "barrel_open"
else
icon_state = "barrel"
/obj/structure/custom_keg
name = "Plasteel Keg"
desc = "A large plasteel keg. You can use it to hold liquids. You may wanna label this, too."
icon = 'icons/obj/objects.dmi'
icon_state = "keg"
density = TRUE
anchored = FALSE
pressure_resistance = 2 * ONE_ATMOSPHERE
max_integrity = 300
var/open = FALSE
/obj/structure/custom_keg/Initialize()
create_reagents(1000, DRAINABLE | AMOUNT_VISIBLE)
. = ..()
/obj/structure/custom_keg/examine(mob/user)
. = ..()
. += "<span class='notice'>It is currently [open?"open, letting you pour liquids in.":"closed, letting you draw liquids from the tap."]</span>"
/obj/structure/custom_keg/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
open = !open
if(open)
DISABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
ENABLE_BITFIELD(reagents.reagents_holder_flags, REFILLABLE)
to_chat(user, "<span class='notice'>You open [src], letting you fill it.</span>")
else
DISABLE_BITFIELD(reagents.reagents_holder_flags, REFILLABLE)
ENABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
to_chat(user, "<span class='notice'>You close [src], letting you draw from its tap.</span>")
update_icon()
/obj/structure/custom_keg/update_icon_state()
if(open)
icon_state = "keg_open"
else
icon_state = "keg"
@@ -679,7 +679,7 @@
icon_state = "crow"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tail/cow
/datum/sprite_accessory/tails/mam_tails/cow
name = "Cow"
icon_state = "cow"
matrixed_sections = MATRIX_RED
@@ -51,6 +51,9 @@
var/obj/item/l_store = null
var/obj/item/s_store = null
/// When an braindead player has their equipment fiddled with, we log that info here for when they come back so they know who took their ID while they were DC'd for 30 seconds
var/list/afk_thefts
var/special_voice = "" // For changing our voice. Used by a symptom.
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
@@ -2,3 +2,33 @@
..()
if(dna?.species?.has_field_of_vision && CONFIG_GET(flag/use_field_of_vision))
LoadComponent(/datum/component/field_of_vision, field_of_vision_type)
if(!LAZYLEN(afk_thefts))
return
var/list/print_msg = list()
print_msg += "<span class='info'>*---------*</span>"
print_msg += "<span class='userdanger'>As you snap back to consciousness, you recall people messing with your stuff...</span>"
afk_thefts = reverseRange(afk_thefts)
for(var/list/iter_theft as anything in afk_thefts)
if(!islist(iter_theft) || LAZYLEN(iter_theft) != AFK_THEFT_TIME)
stack_trace("[src] ([ckey]) returned to their body and had a null/malformed afk_theft entry. Contents: [json_encode(iter_theft)]")
continue
var/thief_name = iter_theft[AFK_THEFT_NAME]
var/theft_message = iter_theft[AFK_THEFT_MESSAGE]
var/time_since = world.time - iter_theft[AFK_THEFT_TIME]
if(time_since > AFK_THEFT_FORGET_DETAILS_TIME)
print_msg += "\t<span class='danger'><b>Someone [theft_message], but it was at least [DisplayTimeText(AFK_THEFT_FORGET_DETAILS_TIME)] ago.</b></span>"
else
print_msg += "\t<span class='danger'><b>[thief_name] [theft_message] roughly [DisplayTimeText(time_since, 10)] ago.</b></span>"
if(LAZYLEN(afk_thefts) >= AFK_THEFT_MAX_MESSAGES)
print_msg += "<span class='warning'>There may have been more, but that's all you can remember...</span>"
print_msg += "<span class='info'>*---------*</span>"
to_chat(src, print_msg.Join("\n"))
LAZYNULL(afk_thefts)
+13
View File
@@ -911,6 +911,12 @@
"<span class='userdanger'>[src] tries to remove your [what.name].</span>", target = src,
target_message = "<span class='danger'>You try to remove [who]'s [what.name].</span>")
what.add_fingerprint(src)
if(ishuman(who))
var/mob/living/carbon/human/victim_human = who
if(victim_human.key && !victim_human.client) // AKA braindead
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
var/list/new_entry = list(list(src.name, "tried unequipping your [what]", world.time))
LAZYADD(victim_human.afk_thefts, new_entry)
else
to_chat(src,"<span class='notice'>You try to remove [who]'s [what.name].</span>")
what.add_fingerprint(src)
@@ -957,6 +963,13 @@
to_chat(src, "<span class='warning'>\The [what.name] doesn't fit in that place!</span>")
return
if(ishuman(who))
var/mob/living/carbon/human/victim_human = who
if(victim_human.key && !victim_human.client) // AKA braindead
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
var/list/new_entry = list(list(src.name, "tried equipping you with [what]", world.time))
LAZYADD(victim_human.afk_thefts, new_entry)
who.visible_message("<span class='notice'>[src] tries to put [what] on [who].</span>",
"<span class='notice'>[src] tries to put [what] on you.</span>", target = src,
target_message = "<span class='notice'>You try to put [what] on [who].</span>")
@@ -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
View 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
+12 -15
View File
@@ -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
+1 -1
View File
@@ -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.
+67 -6
View File
@@ -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
+50 -20
View File
@@ -50,6 +50,56 @@
-->
<div class="commit sansserif">
<h2 class="date">19 July 2021</h2>
<h3 class="author">Arturlang updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">The crafting button should no longer silently make more copies of itself on reconects</li>
<li class="code_imp">There are no longer two copies of the crafting component.</li>
<li class="code_imp">There is no longer a rogue d in tracer.dm tweak: Everything in Misc was moved to Miscelanious in the crafting menu, and Misc was nuked from orbit. Nobody will miss you.</li>
</ul>
<h3 class="author">MrJWhit updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Fixes a memory leak, there's a good chance that it's the same one that killed kilo.</li>
</ul>
<h3 class="author">SandPoot updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Put back mob vore with a pref.</li>
<li class="code_imp">Taken some stuff from tg for tgui_alert.</li>
<li class="refactor">Refactored a lot of code on vore panel.</li>
</ul>
<h3 class="author">WanderingFox95 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">custom plasteel kegs</li>
</ul>
<h3 class="author">YakumoChen updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">You can now wear the suffering of others on your head with just a sheet of human skin!</li>
<li class="imageadd">Human skin hats</li>
</ul>
<h3 class="author">keronshb updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Stripping/equipping things to a conscious braindead person (AKA a human owned by a disconnected player) will now give them a message with your visible name and roughly how long ago you touched their stuff when they login again. Touching someone's pockets or adjusting their gear other than equipping/unequipping is not logged. After 5 minutes, you'll have forgotten both their name and exactly how long ago past those 5 minutes it happened. (Credit to Ryll-Ryll)</li>
<li class="rscadd">LAZYNULL</li>
<li class="rscadd">Breaking mirrors now gives you a bad omen</li>
</ul>
<h3 class="author">timothyteakettle updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">anthros can now select the cow tail</li>
<li class="rscadd">new quirk that allows you to eat trash</li>
</ul>
<h2 class="date">18 July 2021</h2>
<h3 class="author">timothyteakettle updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">fixes photosynthesis stopping nutrition going past well fed from non-photosynthesis means</li>
</ul>
<h2 class="date">17 July 2021</h2>
<h3 class="author">cadyn updated:</h3>
<ul class="changes bgimages16">
<li class="server">precompile.sh updated</li>
</ul>
<h2 class="date">15 July 2021</h2>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
@@ -559,26 +609,6 @@
<li class="rscadd">more drink mixture flavortext</li>
<li class="soundadd">you're going to Baystation</li>
</ul>
<h2 class="date">15 May 2021</h2>
<h3 class="author">bunny232 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Corrects the bot pathing by engineering on meta station</li>
</ul>
<h3 class="author">timothyteakettle updated:</h3>
<ul class="changes bgimages16">
<li class="balance">borg spraycans have a five second delay before being able to knock someone down again</li>
</ul>
<h2 class="date">14 May 2021</h2>
<h3 class="author">keronshb updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Removes VOG sleep command since it was an undocumented readd.</li>
</ul>
<h3 class="author">zeroisthebiggay updated:</h3>
<ul class="changes bgimages16">
<li class="spellcheck">consealed</li>
</ul>
</div>
<b>GoonStation 13 Development Team</b>
+40
View File
@@ -29662,3 +29662,43 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
2021-07-15:
Putnam3145:
- bugfix: fixes a major source of lag
2021-07-17:
cadyn:
- server: precompile.sh updated
2021-07-18:
timothyteakettle:
- bugfix: fixes photosynthesis stopping nutrition going past well fed from non-photosynthesis
means
2021-07-19:
Arturlang:
- bugfix: The crafting button should no longer silently make more copies of itself
on reconects
- code_imp: There are no longer two copies of the crafting component.
- code_imp: 'There is no longer a rogue d in tracer.dm tweak: Everything in Misc
was moved to Miscelanious in the crafting menu, and Misc was nuked from orbit.
Nobody will miss you.'
MrJWhit:
- bugfix: Fixes a memory leak, there's a good chance that it's the same one that
killed kilo.
SandPoot:
- rscadd: Put back mob vore with a pref.
- code_imp: Taken some stuff from tg for tgui_alert.
- refactor: Refactored a lot of code on vore panel.
WanderingFox95:
- rscadd: custom plasteel kegs
YakumoChen:
- rscadd: You can now wear the suffering of others on your head with just a sheet
of human skin!
- imageadd: Human skin hats
keronshb:
- rscadd: Stripping/equipping things to a conscious braindead person (AKA a human
owned by a disconnected player) will now give them a message with your visible
name and roughly how long ago you touched their stuff when they login again.
Touching someone's pockets or adjusting their gear other than equipping/unequipping
is not logged. After 5 minutes, you'll have forgotten both their name and exactly
how long ago past those 5 minutes it happened. (Credit to Ryll-Ryll)
- rscadd: LAZYNULL
- rscadd: Breaking mirrors now gives you a bad omen
timothyteakettle:
- bugfix: anthros can now select the cow tail
- rscadd: new quirk that allows you to eat trash
Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 105 KiB

+2
View File
@@ -639,6 +639,7 @@
#include "code\datums\elements\swimming.dm"
#include "code\datums\elements\sword_point.dm"
#include "code\datums\elements\tactical.dm"
#include "code\datums\elements\trash.dm"
#include "code\datums\elements\turf_transparency.dm"
#include "code\datums\elements\update_icon_blocker.dm"
#include "code\datums\elements\update_icon_updates_onmob.dm"
@@ -3593,6 +3594,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
View 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&apos;t inside anyone.
</Section>
);
}
return (
<Section title="Inside">
<Box color="green" inline>You are currently {absorbed ? "absorbed into" : "inside"}</Box>&nbsp;
<Box color="yellow" inline>{pred}&apos;s</Box>&nbsp;
<Box color="red" inline>{belly_name}</Box>&nbsp;
<Box color="yellow" inline>and you are</Box>&nbsp;
<Box color={digestModeToColor[belly_mode]} inline>{digestModeToPreyMode[belly_mode]}</Box>&nbsp;
<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>
);
};
+1 -1
View File
@@ -67,7 +67,7 @@ mv target/i686-unknown-linux-gnu/release/librust_g.so "$1/librust_g.so"
cd ..
# Auxtools dependencies
apt-get install build-essential g++-multilib libc6-i386 libstdc++6:i386
apt-get install -y build-essential g++-multilib libc6-i386 libstdc++6:i386
# Update auxmos
if [ ! -d "auxmos" ]; then