Merge branch 'master' into Ghommie-cit629

This commit is contained in:
Ghom
2020-03-19 17:15:26 +01:00
committed by GitHub
118 changed files with 9283 additions and 5906 deletions
+2 -1
View File
@@ -81,7 +81,8 @@
//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam
#define MAX_MESSAGE_LEN 2048 //Citadel edit: What's the WORST that could happen?
#define MAX_FAVOR_LEN 4096 //double the maximum message length.
#define MAX_FLAVOR_LEN 4096 //double the maximum message length.
#define MAX_TASTE_LEN 40 //lick... vore... ew...
#define MAX_NAME_LEN 42
#define MAX_BROADCAST_LEN 512
#define MAX_CHARTER_LEN 80
+1
View File
@@ -222,6 +222,7 @@
#define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention
#define GHOSTROLE_TRAIT "ghostrole"
#define APHRO_TRAIT "aphro"
#define BLOODSUCKER_TRAIT "bloodsucker"
// unique trait sources, still defines
#define STATUE_MUTE "statue"
+1 -1
View File
@@ -425,7 +425,7 @@
candidates -= M
/proc/pollGhostCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE)
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
var/list/candidates = eligibility.get_all_ghost_role_eligible()
return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates)
+4 -2
View File
@@ -1426,7 +1426,9 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
/proc/get_random_drink()
var/list/blocked = list(/obj/item/reagent_containers/food/drinks/soda_cans,
/obj/item/reagent_containers/food/drinks/bottle
/obj/item/reagent_containers/food/drinks/bottle,
/obj/item/reagent_containers/food/drinks/flask/russian,
/obj/item/reagent_containers/food/drinks/flask/steel
)
return pick(subtypesof(/obj/item/reagent_containers/food/drinks) - blocked)
@@ -1562,4 +1564,4 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
channels_to_use += channel
if(channels_to_use.len)
world.TgsChatBroadcast()
world.TgsChatBroadcast()
+1 -1
View File
@@ -103,7 +103,7 @@ SUBSYSTEM_DEF(jukeboxes)
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS) || !M.can_hear())
M.stop_sound_channel(jukeinfo[2])
continue
+2 -1
View File
@@ -676,7 +676,8 @@
//Preset for general and toggled actions
/datum/action/innate
check_flags = 0
check_flags = NONE
required_mobility_flags = NONE
var/active = 0
/datum/action/innate/Trigger()
+2 -1
View File
@@ -83,6 +83,7 @@
elements.Cut()
/datum/beam/Destroy()
finished = TRUE
Reset()
target = null
origin = null
@@ -100,7 +101,7 @@
var/length = round(sqrt((DX)**2+(DY)**2)) //hypotenuse of the triangle formed by target and origin's displacement
for(N in 0 to length-1 step 32)//-1 as we want < not <=, but we want the speed of X in Y to Z and step X
if(QDELETED(src) || finished)
if(finished)
break
var/obj/effect/ebeam/X = new beam_type(origin_oldloc)
X.owner = src
@@ -107,7 +107,7 @@
/obj/item/stack/cable_coil = 5)
category = CAT_CLOTHING
/datum/crafting_recipe/diagnostic_singlasses_removal
/datum/crafting_recipe/diagnostic_sunglasses_removal
name = "Diagnostic HUDsunglasses removal"
result = /obj/item/clothing/glasses/sunglasses
time = 20
@@ -126,6 +126,85 @@
/obj/item/stack/cable_coil = 5)
category = CAT_CLOTHING
*/
// Eyepatch Glasses
/datum/crafting_recipe/secpatch
name = "Security Eyepatch HUD"
result = /obj/item/clothing/glasses/hud/security/sunglasses/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
parts = list(/obj/item/clothing/glasses/hud/security/sunglasses = 1,
/obj/item/clothing/glasses/eyepatch = 1)
reqs = list(/obj/item/clothing/glasses/hud/security/sunglasses = 1,
/obj/item/clothing/glasses/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/secpatch_removal
name = "Security HUDpatch Removal"
result = /obj/item/clothing/glasses/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
reqs = list(/obj/item/clothing/glasses/hud/security/sunglasses/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/medpatch
name = "Medical Eyepatch HUD"
result = /obj/item/clothing/glasses/hud/health/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
parts = list(/obj/item/clothing/glasses/hud/health = 1,
/obj/item/clothing/glasses/eyepatch = 1)
reqs = list(/obj/item/clothing/glasses/hud/health = 1,
/obj/item/clothing/glasses/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/medpatch_removal
name = "Medical HUDpatch Removal"
result = /obj/item/clothing/glasses/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
reqs = list(/obj/item/clothing/glasses/hud/health/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/diagpatch
name = "Diagnostic Eyepatch HUD"
result = /obj/item/clothing/glasses/hud/diagnostic/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
parts = list(/obj/item/clothing/glasses/hud/diagnostic = 1,
/obj/item/clothing/glasses/eyepatch = 1)
reqs = list(/obj/item/clothing/glasses/hud/diagnostic = 1,
/obj/item/clothing/glasses/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/diagpatch_removal
name = "Diagnostic HUDpatch Removal"
result = /obj/item/clothing/glasses/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
reqs = list(/obj/item/clothing/glasses/hud/diagnostic/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/mesonpatch
name = "Meson Scanner Eyepatch"
result = /obj/item/clothing/glasses/meson/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
parts = list(/obj/item/clothing/glasses/meson = 1,
/obj/item/clothing/glasses/eyepatch = 1)
reqs = list(/obj/item/clothing/glasses/meson = 1,
/obj/item/clothing/glasses/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/mesonpatch_removal
name = "Meson Scanner patch Removal"
result = /obj/item/clothing/glasses/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
reqs = list(/obj/item/clothing/glasses/meson/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/ghostsheet
name = "Ghost Sheet"
result = /obj/item/clothing/suit/ghost_sheet
@@ -278,7 +278,7 @@
/datum/crafting_recipe/arrow
name = "Arrow"
result = /obj/item/ammo_casing/caseless/arrow
result = /obj/item/ammo_casing/caseless/arrow/wood
time = 30
reqs = list(/obj/item/stack/sheet/mineral/wood = 1,
/obj/item/stack/sheet/silk = 1,
@@ -293,17 +293,17 @@
always_availible = FALSE
reqs = list(/obj/item/stack/sheet/bone = 1,
/obj/item/stack/sheet/sinew = 1,
/obj/item/ammo_casing/caseless/arrow/ashen = 1)
/obj/item/ammo_casing/caseless/arrow/ash = 1)
category = CAT_WEAPONRY
subcategory = CAT_AMMO
/datum/crafting_recipe/ashen_arrow
name = "Fire Hardened Arrow"
result = /obj/item/ammo_casing/caseless/arrow/ashen
result = /obj/item/ammo_casing/caseless/arrow/ash
tools = list(TOOL_WELDER)
time = 30
always_availible = FALSE
reqs = list(/obj/item/ammo_casing/caseless/arrow = 1)
reqs = list(/obj/item/ammo_casing/caseless/arrow/wood = 1)
category = CAT_WEAPONRY
subcategory = CAT_AMMO
+6 -6
View File
@@ -32,16 +32,16 @@
..()
switch(stage)
if(1)
if (prob(stage_prob) && stage1)
if (prob(stage_prob) && length(stage1))
to_chat(affected_mob, pick(stage1))
if(2)
if (prob(stage_prob) && stage2)
if (prob(stage_prob) && length(stage2))
to_chat(affected_mob, pick(stage2))
if(3)
if (prob(stage_prob*2) && stage3)
if (prob(stage_prob*2) && length(stage3))
to_chat(affected_mob, pick(stage3))
if(4)
if (prob(stage_prob*2) && stage4)
if (prob(stage_prob*2) && length(stage4))
to_chat(affected_mob, pick(stage4))
if(5)
do_disease_transformation(affected_mob)
@@ -162,7 +162,7 @@
desc = "This disease, actually acute nanomachine infection, converts the victim into a cyborg."
severity = DISEASE_SEVERITY_BIOHAZARD
visibility_flags = 0
stage1 = list()
stage1 = null
stage2 = list("Your joints feel stiff.", "<span class='danger'>Beep...boop..</span>")
stage3 = list("<span class='danger'>Your joints feel very stiff.</span>", "Your skin feels loose.", "<span class='danger'>You can feel something move...inside.</span>")
stage4 = list("<span class='danger'>Your skin feels very loose.</span>", "<span class='danger'>You can feel... something...inside you.</span>")
@@ -195,7 +195,7 @@
desc = "This disease changes the victim into a xenomorph."
severity = DISEASE_SEVERITY_BIOHAZARD
visibility_flags = 0
stage1 = list()
stage1 = null
stage2 = list("Your throat feels scratchy.", "<span class='danger'>Kill...</span>")
stage3 = list("<span class='danger'>Your throat feels very scratchy.</span>", "Your skin feels tight.", "<span class='danger'>You can feel something move...inside.</span>")
stage4 = list("<span class='danger'>Your skin feels very tight.</span>", "<span class='danger'>Your blood boils!</span>", "<span class='danger'>You can feel... something...inside you.</span>")
+3 -3
View File
@@ -7,10 +7,10 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
var/list/texts_by_atom = list()
var/addendum = "This can also be used for OOC notes and preferences!"
var/always_show = FALSE
var/max_len = MAX_FAVOR_LEN
var/max_len = MAX_FLAVOR_LEN
var/can_edit = TRUE
/datum/element/flavor_text/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FAVOR_LEN, _always_show = FALSE, _edit = TRUE)
/datum/element/flavor_text/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE)
. = ..()
if(. == ELEMENT_INCOMPATIBLE || !isatom(target)) //no reason why this shouldn't work on atoms too.
@@ -115,7 +115,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
//subtypes with additional hooks for DNA and preferences.
/datum/element/flavor_text/carbon
/datum/element/flavor_text/carbon/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FAVOR_LEN, _always_show = FALSE, _edit = TRUE)
/datum/element/flavor_text/carbon/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE)
if(!iscarbon(target))
return ELEMENT_INCOMPATIBLE
. = ..()
@@ -42,7 +42,7 @@
return candidates
/mob/proc/can_reenter_round(silent = FALSE)
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
return eli.can_reenter_round(src,silent)
/datum/element/ghost_role_eligibility/proc/can_reenter_round(var/mob/M,silent = FALSE)
+1 -1
View File
@@ -15,4 +15,4 @@
/datum/element/sword_point/proc/point(datum/source, atom/target, mob/user, proximity_flag, params)
if(!proximity_flag && ismob(target))
user.visible_message("<span class='notice'>[user] points the tip of [src] at [target].</span>", "<span class='notice'>You point the tip of [src] at [target].</span>")
user.visible_message("<span class='notice'>[user] points the tip of [source] at [target].</span>", "<span class='notice'>You point the tip of [src] at [target].</span>")
+1 -1
View File
@@ -40,7 +40,7 @@
name = "Fire Breath"
desc = "You can breathe fire at a target."
school = "evocation"
charge_max = 1200
charge_max = 600
clothes_req = FALSE
range = 20
base_icon_state = "fireball"
+14
View File
@@ -480,6 +480,12 @@
admin_notes = "Comes with turrets that will target any simplemob."
credit_cost = 12500
/datum/map_template/shuttle/emergency/cog
suffix = "cog"
name = "NES Classic"
description = "A blast from the past! This recreation of the Nanotrasen Emergency Shuttle Port features the same focus on seating as the original, but on a slightly longer frame to better accommodate modern shuttle docks."
credit_cost = 750
/datum/map_template/shuttle/arrival/box
suffix = "box"
name = "arrival shuttle (Box)"
@@ -500,6 +506,10 @@
suffix = "kilo"
name = "labour shuttle (Kilo)"
/datum/map_template/shuttle/labour/cog
suffix = "cog"
name = "labour shuttle (Cog)"
/datum/map_template/shuttle/infiltrator/basic
suffix = "basic"
name = "basic syndicate infiltrator"
@@ -544,6 +554,10 @@
suffix = "omega"
name = "arrival shuttle (Omega)"
/datum/map_template/shuttle/arrival/cog
suffix = "cog"
name = "arrival shuttle (Cog)"
/datum/map_template/shuttle/aux_base/default
suffix = "default"
name = "auxilliary base (Default)"
+2 -2
View File
@@ -108,10 +108,10 @@
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/choice_beacon/music/B = new(get_turf(H))
H.put_in_hands(B)
H.equip_to_slot(B, SLOT_IN_BACKPACK)
H.equip_to_slot_if_possible(B, SLOT_IN_BACKPACK)
var/obj/item/musicaltuner/musicaltuner = new(get_turf(H))
H.put_in_hands(musicaltuner)
H.equip_to_slot(musicaltuner, SLOT_IN_BACKPACK)
H.equip_to_slot_if_possible(musicaltuner, SLOT_IN_BACKPACK)
H.regenerate_icons()
/datum/quirk/photographer
@@ -34,7 +34,7 @@
living_players = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS])
living_antags = trim_list(mode.current_players[CURRENT_LIVING_ANTAGS])
list_observers = trim_list(mode.current_players[CURRENT_OBSERVERS])
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
ghost_eligible = trim_list(eligibility.get_all_ghost_role_eligible())
/datum/dynamic_ruleset/midround/proc/trim_list(list/L = list())
@@ -677,6 +677,9 @@
message_admins("[ADMIN_LOOKUPFLW(Ninja)] has been made into a ninja by dynamic.")
log_game("[key_name(Ninja)] was spawned as a ninja by dynamic.")
return Ninja
/datum/dynamic_ruleset/midround/from_ghosts/ninja/finish_setup(mob/new_character, index)
return
#undef ABDUCTOR_MAX_TEAMS
#undef REVENANT_SPAWN_THRESHOLD
+5 -5
View File
@@ -219,7 +219,7 @@
if(!is_operational()) //Autoeject if power is lost
if(mob_occupant)
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
connected_message("Clone Ejected: Loss of power.")
else if(mob_occupant && (mob_occupant.loc == src))
@@ -229,7 +229,7 @@
SPEAK("The cloning has been \
aborted due to unrecoverable tissue failure.")
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
else if(mob_occupant.cloneloss > (100 - heal_level))
mob_occupant.Unconscious(80)
@@ -275,7 +275,7 @@
BP.attach_limb(mob_occupant)
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
else if (!mob_occupant || mob_occupant.loc != src)
occupant = null
@@ -323,7 +323,7 @@
SPEAK("An emergency ejection of the current clone has occurred. Survival not guaranteed.")
to_chat(user, "<span class='notice'>You force an emergency ejection. </span>")
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
else
return ..()
@@ -421,7 +421,7 @@
if(mob_occupant && prob(100/(severity*efficiency)))
connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of, ERROR: John Doe, prematurely." ,0))
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
go_out()
/obj/machinery/clonepod/ex_act(severity, target)
+2 -2
View File
@@ -136,7 +136,7 @@
if(connected && connected.is_operational())
if(connected.occupant) //set occupant_status message
viable_occupant = connected.occupant
if(viable_occupant.has_dna() && !HAS_TRAIT(viable_occupant, TRAIT_RADIMMUNE) && !HAS_TRAIT(viable_occupant, TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification
if(viable_occupant.has_dna() && !HAS_TRAIT_NOT_FROM(viable_occupant, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) && !HAS_TRAIT(viable_occupant, TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification
occupant_status += "[viable_occupant.name] => "
switch(viable_occupant.stat)
if(CONSCIOUS)
@@ -948,7 +948,7 @@
var/mob/living/carbon/viable_occupant = null
if(connected)
viable_occupant = connected.occupant
if(!istype(viable_occupant) || !viable_occupant.dna || HAS_TRAIT(viable_occupant, TRAIT_RADIMMUNE) || HAS_TRAIT(viable_occupant, TRAIT_NOCLONE))
if(!istype(viable_occupant) || !viable_occupant.dna || HAS_TRAIT_NOT_FROM(viable_occupant, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) || HAS_TRAIT(viable_occupant, TRAIT_NOCLONE))
viable_occupant = null
return viable_occupant
+3 -3
View File
@@ -115,10 +115,10 @@
if(src.allowed(usr))
var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs
if(can_control(usr, R))
var/choice = input("Are you certain you wish to [R.locked_down? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
var/choice = input("Are you certain you wish to [!R.locked_down ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm" && can_control(usr, R) && !..())
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [R.locked_down? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [R.locked_down? "locked down" : "released"] [key_name(R)]!")
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R)]!")
R.SetLockdown(!R.locked_down)
to_chat(R, "[!R.locked_down ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
if(R.connected_ai)
+2 -2
View File
@@ -316,7 +316,7 @@
if("togglemoving")
moving = !moving
if(moving)
spawn() MagnetMove()
INVOKE_ASYNC(src, .proc/MagnetMove)
updateUsrDialog()
@@ -325,7 +325,7 @@
if(looping)
return
while(moving && rpath.len >= 1)
while(moving && length(rpath) >= 1)
if(stat & (BROKEN|NOPOWER))
break
@@ -247,6 +247,7 @@
if(prob(70))
if(stored_gun)
stored_gun.forceMove(loc)
stored_gun = null
to_chat(user, "<span class='notice'>You remove the turret and salvage some components.</span>")
if(prob(50))
new /obj/item/stack/sheet/metal(loc, rand(1,4))
+9 -9
View File
@@ -8,7 +8,7 @@
layer = ABOVE_ALL_MOB_LAYER // Overhead
density = TRUE
circuit = /obj/item/circuitboard/machine/recycler
var/safety_mode = FALSE // Temporarily stops machine if it detects a mob
var/safety_mode = FALSE // Temporarily stops machine if it detects a mob, or upon deconstruction.
var/icon_name = "grinder-o"
var/blood = 0
var/eat_dir = WEST
@@ -24,6 +24,10 @@
update_icon()
req_one_access = get_all_accesses() + get_all_centcom_access()
/obj/machinery/recycler/deconstruct(disassembled = TRUE)
safety_mode = TRUE //to stop stock parts and circuit from being deleted.
return ..()
/obj/machinery/recycler/RefreshParts()
var/amt_made = 0
var/mat_mod = 0
@@ -97,18 +101,14 @@
. = ..()
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
if(stat & (BROKEN|NOPOWER))
return
if(safety_mode)
if(stat & (BROKEN|NOPOWER) || safety_mode)
return
var/list/to_eat
if(isitem(AM0))
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
else
to_eat = list(AM0)
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
var/items_recycled = 0
for(var/i in to_eat)
var/atom/movable/AM = i
var/obj/item/bodypart/head/as_head = AM
+10
View File
@@ -152,6 +152,16 @@
else
..()
/obj/structure/spider/spiderling/attack_hand(mob/user)
. = ..()
if(user.a_intent != INTENT_HELP)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
user.visible_message("<span class='warning'>[user] splats [src].</span>", "<span class='warning'>You splat [src].</span>", "<span class='italics'>You hear a splat...</span>")
playsound(loc, 'sound/effects/snap.ogg', 25)
qdel(src)
return TRUE
/obj/structure/spider/spiderling/process()
if(travelling_in_vent)
if(isturf(loc))
+2 -2
View File
@@ -803,7 +803,7 @@ SLIME SCANNER
/obj/item/sequence_scanner/attack(mob/living/M, mob/living/carbon/human/user)
add_fingerprint(user)
if (!HAS_TRAIT(M, TRAIT_RADIMMUNE)) //no scanning if its a husk or DNA-less Species
if (!HAS_TRAIT_NOT_FROM(M, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT)) //no scanning if its a husk or DNA-less Species
user.visible_message("<span class='notice'>[user] analyzes [M]'s genetic sequence.</span>", \
"<span class='notice'>You analyze [M]'s genetic sequence.</span>")
gene_scan(M, user)
@@ -879,4 +879,4 @@ SLIME SCANNER
if(mutation in discovered)
return "[HM.name] ([HM.alias])"
else
return HM.alias
return HM.alias
+2 -2
View File
@@ -20,7 +20,7 @@
return attack_hand(user)
/obj/item/dnainjector/proc/inject(mob/living/carbon/M, mob/user)
if(M.has_dna() && !HAS_TRAIT(M, TRAIT_RADIMMUNE) && !HAS_TRAIT(M, TRAIT_NOCLONE))
if(M.has_dna() && !HAS_TRAIT_NOT_FROM(M, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) && !HAS_TRAIT(M, TRAIT_NOCLONE))
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
for(var/HM in remove_mutations)
@@ -525,7 +525,7 @@
var/filled = FALSE
/obj/item/dnainjector/activator/inject(mob/living/carbon/M, mob/user)
if(M.has_dna() && !HAS_TRAIT(M, TRAIT_RADIMMUNE) && !HAS_TRAIT(M,TRAIT_NOCLONE))
if(M.has_dna() && !HAS_TRAIT_NOT_FROM(M, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) && !HAS_TRAIT(M,TRAIT_NOCLONE))
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
for(var/mutation in add_mutations)
@@ -173,37 +173,6 @@
R.module.basic_modules += S
R.module.add_module(S, FALSE, TRUE)
/obj/item/borg/upgrade/premiumka
name = "mining cyborg premium KA"
desc = "A premium kinetic accelerator replacement for the mining module's standard kinetic accelerator."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = list(/obj/item/robot_module/miner)
/obj/item/borg/upgrade/premiumka/action(mob/living/silicon/robot/R, user = usr)
. = ..()
if(.)
for(var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA in R.module)
for(var/obj/item/borg/upgrade/modkit/M in KA.modkits)
M.uninstall(src)
R.module.remove_module(KA, TRUE)
var/obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg/PKA = new /obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg(R.module)
R.module.basic_modules += PKA
R.module.add_module(PKA, FALSE, TRUE)
/obj/item/borg/upgrade/premiumka/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
if (.)
for(var/obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg/PKA in R.module)
for(var/obj/item/borg/upgrade/modkit/M in PKA.modkits)
M.uninstall(src)
R.module.remove_module(PKA, TRUE)
var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA = new (R.module)
R.module.basic_modules += KA
R.module.add_module(KA, FALSE, TRUE)
/obj/item/borg/upgrade/advcutter
name = "mining cyborg advanced plasma cutter"
@@ -136,6 +136,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
merge_type = /obj/item/stack/sheet/metal
grind_results = list(/datum/reagent/iron = 20)
point_value = 2
tableVariant = /obj/structure/table
material_type = /datum/material/iron
/obj/item/stack/sheet/metal/ratvar_act()
+2 -1
View File
@@ -219,8 +219,9 @@
O = new R.result_type(usr.drop_location())
if(O)
O.setDir(usr.dir)
log_craft("[O] crafted by [usr] at [loc_name(O.loc)]")
use(R.req_amount * multiplier)
log_craft("[O] crafted by [usr] at [loc_name(O.loc)]")
if(R.applies_mats && custom_materials && custom_materials.len)
var/list/used_materials = list()
+1 -1
View File
@@ -66,7 +66,7 @@
return
if(!istype(target))
return
if(target.anchored)
if(target.anchored || (user in target))
return
if(isitem(target))
+6 -1
View File
@@ -54,7 +54,12 @@
icon_state = "holdingsat"
item_state = "holdingsat"
species_exception = list(/datum/species/angel)
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
/obj/item/storage/backpack/holding/duffel
name = "duffel bag of holding"
desc = "A duffel bag that opens into a localized pocket of Blue Space."
icon_state = "holdingduffel"
item_state = "holdingduffel"
/obj/item/storage/backpack/holding/ComponentInitialize()
. = ..()
+3 -3
View File
@@ -1012,7 +1012,7 @@
/obj/item/twohanded/electrostaff
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "electrostaff_3"
icon_state = "electrostaff"
item_state = "electrostaff"
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
@@ -1116,10 +1116,10 @@
/obj/item/twohanded/electrostaff/update_icon_state()
. = ..()
if(!wielded)
icon_state = "electrostaff_3"
icon_state = "electrostaff"
item_state = "electrostaff"
else
icon_state = item_state = (on? "electrostaff_1" : "electrostaff_3")
icon_state = item_state = (on? "electrostaff_1" : "electrostaff_0")
set_light(7, on? 1 : 0, LIGHT_COLOR_CYAN)
/obj/item/twohanded/electrostaff/examine(mob/living/user)
@@ -59,6 +59,7 @@
new_spawn.real_name = random_unique_lizard_name(gender)
if(is_mining_level(z))
to_chat(new_spawn, "<b>Drag the corpses of men and beasts to your nest. It will absorb them to create more of your kind. Glory to the Necropolis!</b>")
to_chat(new_spawn, "<b>You can expand the weather proof area provided by your shelters by using the 'New Area' key near the bottom right of your HUD.</b>")
else
to_chat(new_spawn, "<span class='userdanger'>You have been born outside of your natural home! Whether you decide to return home, or make due with your new home is your own decision.</span>")
+2 -1
View File
@@ -70,7 +70,8 @@
/turf/closed/wall/proc/break_wall()
new sheet_type(src, sheet_amount)
return new girder_type(src)
if(girder_type)
return new girder_type(src)
/turf/closed/wall/proc/devastate_wall()
new sheet_type(src, sheet_amount)
+1 -3
View File
@@ -639,15 +639,13 @@
var/almcam = CONFIG_GET(flag/allow_ai_multicam)
CONFIG_SET(flag/allow_ai_multicam, !almcam)
if (almcam)
to_chat(world, "<B>The AI no longer has multicam.</B>")
for(var/i in GLOB.ai_list)
var/mob/living/silicon/ai/aiPlayer = i
if(aiPlayer.multicam_on)
aiPlayer.end_multicam()
else
to_chat(world, "<B>The AI now has multicam.</B>")
log_admin("[key_name(usr)] toggled AI multicam.")
world.update_status()
to_chat(GLOB.ai_list | GLOB.admins, "<B>The AI [almcam ? "no longer" : "now"] has multicam.</B>")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Multicam", "[!almcam ? "Disabled" : "Enabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/toggleaban()
+1 -1
View File
@@ -1732,7 +1732,7 @@
var/mob/M = locate(href_list["makeeligible"])
if(!ismob(M))
to_chat(usr, "this can only be used on instances of type /mob.")
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
if(M.ckey in eli.timeouts)
eli.timeouts -= M.ckey
+3 -3
View File
@@ -1315,15 +1315,15 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target))
creamy.splat(target)
if (ADMIN_PUNISHMENT_CUSTOM_PIE)
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new(get_turf(target))
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new()
if(!A.reagents)
var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num
var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num|null
if(amount)
A.create_reagents(amount)
if(A.reagents)
var/chosen_id = choose_reagent_id(usr)
if(chosen_id)
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num|null
if(amount)
A.reagents.add_reagent(chosen_id, amount)
A.splat(target)
@@ -185,10 +185,10 @@
BuyPower(new /datum/action/bloodsucker/veil)
// Traits
for(var/T in defaultTraits)
ADD_TRAIT(owner.current, T, "bloodsucker")
ADD_TRAIT(owner.current, T, BLOODSUCKER_TRAIT)
if(HAS_TRAIT(owner.current, TRAIT_TOXINLOVER)) //No slime bonuses here, no thank you
had_toxlover = TRUE
REMOVE_TRAIT(owner.current, TRAIT_TOXINLOVER, "species")
REMOVE_TRAIT(owner.current, TRAIT_TOXINLOVER, SPECIES_TRAIT)
// Traits: Species
if(ishuman(owner.current))
var/mob/living/carbon/human/H = owner.current
@@ -235,9 +235,9 @@
// owner.RemoveSpell(power)
// Traits
for(var/T in defaultTraits)
REMOVE_TRAIT(owner.current, T, "bloodsucker")
REMOVE_TRAIT(owner.current, T, BLOODSUCKER_TRAIT)
if(had_toxlover == TRUE)
ADD_TRAIT(owner.current, TRAIT_TOXINLOVER, "species")
ADD_TRAIT(owner.current, TRAIT_TOXINLOVER, SPECIES_TRAIT)
// Traits: Species
if(ishuman(owner.current))
@@ -387,7 +387,7 @@
add_objective(heartthief_objective)
/*
else
// Solars Objective, doesnt work due to TG updates.
var/datum/objective/bloodsucker/solars/solars_objective = new
solars_objective.owner = owner
+1 -1
View File
@@ -211,7 +211,7 @@
/datum/export/weapon/arrows
cost = 150
unit_name = "arrow"
export_types = list(/obj/item/ammo_casing/caseless/arrow, /obj/item/ammo_casing/caseless/arrow/bone, /obj/item/ammo_casing/caseless/arrow/ashen)
export_types = list(/obj/item/ammo_casing/caseless/arrow, /obj/item/ammo_casing/caseless/arrow/bone, /obj/item/ammo_casing/caseless/arrow/ash)
/datum/export/weapon/bow_teaching
cost = 500
-8
View File
@@ -223,7 +223,6 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
new /datum/admins(localhost_rank, ckey, 1, 1)
//preferences datum - also holds some persistent data for the client (because we may as well keep these datums to a minimum)
prefs = GLOB.preferences_datums[ckey]
prefs_vr = GLOB.vore_preferences_datums[ckey] //CITADEL EDIT bypassing a failing hook
if(prefs)
prefs.parent = src
@@ -231,13 +230,6 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
prefs = new /datum/preferences(src)
GLOB.preferences_datums[ckey] = prefs
if(prefs_vr) //CITADEL EDIT bypassing a failing hook START
prefs_vr.client = src
else
prefs_vr = new/datum/vore_preferences(src)
GLOB.vore_preferences_datums[ckey] = prefs_vr
//CITADEL EDIT bypassing a failing hook END
prefs.last_ip = address //these are gonna be used for banning
prefs.last_id = computer_id //these are gonna be used for banning
fps = prefs.clientfps
+9 -5
View File
@@ -205,6 +205,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/action_buttons_screen_locs = list()
//bad stuff
var/digestable = FALSE
var/devourable = FALSE
var/feeding = FALSE
var/lickable = FALSE
var/list/belly_prefs = list()
var/vore_taste = "nothing in particular"
//backgrounds
var/mutable_appearance/character_background
var/icon/bgstate = "steel"
@@ -1483,7 +1491,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN)
if("flavor_text")
var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", features["flavor_text"], MAX_FAVOR_LEN, TRUE)
var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", features["flavor_text"], MAX_FLAVOR_LEN, TRUE)
if(!isnull(msg))
features["flavor_text"] = html_decode(msg)
@@ -2301,16 +2309,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("load")
load_preferences()
load_character()
if(parent && parent.prefs_vr)
attempt_vr(parent.prefs_vr,"load_vore","")
if("changeslot")
if(!load_character(text2num(href_list["num"])))
random_character()
real_name = random_unique_name(gender)
save_character()
if(parent && parent.prefs_vr)
attempt_vr(parent.prefs_vr,"load_vore","")
if("tab")
if (href_list["tab"])
+51 -17
View File
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
#define SAVEFILE_VERSION_MAX 25
#define SAVEFILE_VERSION_MAX 26
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -115,6 +115,36 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(digi == "Digitigrade Legs")
WRITE_FILE(S["feature_lizard_legs"], "Digitigrade")
if(current_version < 26)
var/vr_path = "data/player_saves/[parent.ckey[1]]/[parent.ckey]/vore/character[default_slot].json"
if(fexists(vr_path))
var/list/json_from_file = json_decode(file2text(vr_path))
if(json_from_file)
digestable = json_from_file["digestable"]
devourable = json_from_file["devourable"]
feeding = json_from_file["feeding"]
lickable = json_from_file["lickable"]
belly_prefs = json_from_file["belly_prefs"]
vore_taste = json_from_file["vore_taste"]
for(var/V in all_quirks) // quirk migration
switch(V)
if("Acute hepatic pharmacokinesis")
DISABLE_BITFIELD(cit_toggles, PENIS_ENLARGEMENT)
DISABLE_BITFIELD(cit_toggles, BREAST_ENLARGEMENT)
ENABLE_BITFIELD(cit_toggles,FORCED_FEM)
ENABLE_BITFIELD(cit_toggles,FORCED_MASC)
all_quirks -= V
if("Crocin Immunity")
ENABLE_BITFIELD(cit_toggles,NO_APHRO)
all_quirks -= V
if("Buns of Steel")
ENABLE_BITFIELD(cit_toggles,NO_ASS_SLAP)
all_quirks -= V
if(features["meat_type"] == "Inesct")
features["meat_type"] = "Insect"
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
return
@@ -446,6 +476,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
else //We have no old flavortext, default to new
S["feature_flavor_text"] >> features["flavor_text"]
S["digestable"] >> digestable
S["devourable"] >> devourable
S["feeding"] >> feeding
S["vore_taste"] >> vore_taste
S["lickable"] >> lickable
S["belly_prefs"] >> belly_prefs
//try to fix any outdated data if necessary
if(needs_update >= 0)
@@ -515,6 +551,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
features["cock_length"] = sanitize_integer(features["cock_length"], COCK_SIZE_MIN, COCK_SIZE_MAX, COCK_SIZE_DEF)
features["balls_shape"] = sanitize_inlist(features["balls_shape"], GLOB.balls_shapes_list, DEF_BALLS_SHAPE)
features["vag_shape"] = sanitize_inlist(features["vag_shape"], GLOB.vagina_shapes_list, DEF_VAGINA_SHAPE)
features["flavor_text"] = copytext(features["flavor_text"], 1, MAX_FLAVOR_LEN)
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
//Validate job prefs
@@ -524,23 +561,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
all_quirks = SANITIZE_LIST(all_quirks)
for(var/V in all_quirks) // quirk migration
switch(V)
if("Acute hepatic pharmacokinesis")
DISABLE_BITFIELD(cit_toggles, PENIS_ENLARGEMENT)
DISABLE_BITFIELD(cit_toggles, BREAST_ENLARGEMENT)
ENABLE_BITFIELD(cit_toggles,FORCED_FEM)
ENABLE_BITFIELD(cit_toggles,FORCED_MASC)
all_quirks -= V
if("Crocin Immunity")
ENABLE_BITFIELD(cit_toggles,NO_APHRO)
all_quirks -= V
if("Buns of Steel")
ENABLE_BITFIELD(cit_toggles,NO_ASS_SLAP)
all_quirks -= V
lickable = sanitize_integer(lickable, FALSE, TRUE, initial(lickable))
devourable = sanitize_integer(devourable, FALSE, TRUE, initial(devourable))
digestable = sanitize_integer(digestable, FALSE, TRUE, initial(digestable))
feeding = sanitize_integer(feeding, FALSE, TRUE, initial(feeding))
vore_taste = copytext(vore_taste, 1, MAX_TASTE_LEN)
belly_prefs = SANITIZE_LIST(belly_prefs)
if(features["meat_type"] == "Inesct")
features["meat_type"] = "Insect"
cit_character_pref_load(S)
return 1
@@ -619,6 +646,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
//Quirks
WRITE_FILE(S["all_quirks"] , all_quirks)
WRITE_FILE(S["digestable"] , digestable)
WRITE_FILE(S["devourable"] , devourable)
WRITE_FILE(S["feeding"] , feeding)
WRITE_FILE(S["vore_taste"] , vore_taste)
WRITE_FILE(S["lickable"] , lickable)
WRITE_FILE(S["belly_prefs"] , belly_prefs)
cit_character_pref_save(S)
return 1
@@ -97,6 +97,11 @@
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
/obj/item/clothing/glasses/meson/eyepatch
name = "eyepatch mesons"
desc = "A meson system that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "mesonpatch"
/obj/item/clothing/glasses/science
name = "science goggles"
desc = "A pair of snazzy goggles used to protect against chemical spills. Fitted with an analyzer for scanning items and reagents."
+17 -6
View File
@@ -83,6 +83,11 @@
name = "prescription medical HUDSunglasses"
vision_correction = 1
/obj/item/clothing/glasses/hud/health/eyepatch
name = "eyepatch medHUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "medpatch"
///////////////////
//Diagnostic Huds//
///////////////////
@@ -97,7 +102,8 @@
/obj/item/clothing/glasses/hud/diagnostic/sunglasses
name = "diagnostic HUDSunglasses"
desc = "Sunglasses with a diagnostic HUD."
icon_state = "sunhuddiagnostic"
icon_state = "sunhuddiag"
item_state = "glasses"
darkness_view = 1
flash_protect = 1
tint = 1
@@ -123,6 +129,11 @@
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/hud/diagnostic/eyepatch
name = "eyepatch diagnostic HUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "diagpatch"
////////////
//Sec Huds//
////////////
@@ -165,11 +176,6 @@
return
chameleon_action.emp_randomise()
/obj/item/clothing/glasses/hud/security/sunglasses/eyepatch
name = "eyepatch HUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "hudpatch"
/obj/item/clothing/glasses/hud/security/sunglasses
name = "security HUDSunglasses"
desc = "Sunglasses with a security HUD."
@@ -179,6 +185,11 @@
tint = 1
glass_colour_type = /datum/client_colour/glass_colour/darkred
/obj/item/clothing/glasses/hud/security/sunglasses/eyepatch // why was this defined *before* the sunglasses it is a subtype of.
name = "eyepatch HUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "hudpatch"
/obj/item/clothing/glasses/hud/security/sunglasses/prescription
name = "prescription security HUDSunglasses"
vision_correction = 1
@@ -44,8 +44,8 @@
if(ishuman(hit_atom))
var/mob/living/carbon/human/H = hit_atom
var/mutable_appearance/creamoverlay = mutable_appearance('icons/effects/creampie.dmi')
if(H.dna.species.limbs_id == "lizard")
creamoverlay.icon_state = "creampie_lizard"
if((("mam_snouts" in H.dna.species.default_features) && H.dna.features["mam_snouts"] != "None") || (("snout" in H.dna.species.default_features) && H.dna.features["snout"] != "None"))
creamoverlay.icon_state = "creampie_snout"
else
creamoverlay.icon_state = "creampie_human"
if(stunning)
@@ -53,7 +53,7 @@
H.adjust_blurriness(1)
H.visible_message("<span class='warning'>[H] is creamed by [src]!</span>", "<span class='userdanger'>You've been creamed by [src]!</span>")
playsound(H, "desceration", 50, TRUE)
if(!H.is_mouth_covered())
if(!H.is_mouth_covered())
reagents.trans_to(H,15) //Cream pie combat
if(!H.creamed) // one layer at a time
H.add_overlay(creamoverlay)
@@ -139,6 +139,9 @@
icon = 'icons/obj/lavaland/survival_pod.dmi'
icon_state = "sleeper"
/obj/machinery/sleeper/survival_pod/update_icon_state()
return
/obj/machinery/sleeper/survival_pod/update_overlays()
. = ..()
if(!state_open)
@@ -189,7 +192,7 @@
flags_1 = NODECONSTRUCT_1
var/empty = FALSE
/obj/machinery/stasis/survival_pod/ComponentInitialize()
/obj/machinery/smartfridge/survival_pod/ComponentInitialize()
. = ..()
AddElement(/datum/element/update_icon_blocker)
+3
View File
@@ -24,6 +24,9 @@
/obj/item/mmi/update_overlays()
. = ..()
. += add_mmi_overlay()
/obj/item/mmi/proc/add_mmi_overlay()
if(brainmob && brainmob.stat != DEAD)
. += "mmi_alive"
else
@@ -193,3 +193,6 @@ GLOBAL_VAR(posibrain_notify_cooldown)
icon_state = "[initial(icon_state)]-occupied"
else
icon_state = initial(icon_state)
/obj/item/mmi/posibrain/add_mmi_overlay()
return
@@ -242,6 +242,12 @@
return
if(href_list["pockets"])
var/strip_mod = 1
var/strip_silence = FALSE
var/obj/item/clothing/gloves/g = gloves
if (istype(g))
strip_mod = g.strip_mod
strip_silence = g.strip_silence
var/pocket_side = href_list["pockets"]
var/pocket_id = (pocket_side == "right" ? SLOT_R_STORE : SLOT_L_STORE)
var/obj/item/pocket_item = (pocket_id == SLOT_R_STORE ? r_store : l_store)
@@ -258,7 +264,7 @@
else
return
if(do_mob(usr, src, POCKET_STRIP_DELAY/delay_denominator, ignorehelditem = TRUE)) //placing an item into the pocket is 4 times faster
if(do_mob(usr, src, max(round(POCKET_STRIP_DELAY/(delay_denominator*strip_mod)),1), ignorehelditem = TRUE)) //placing an item into the pocket is 4 times faster (and the strip_mod too)
if(pocket_item)
if(pocket_item == (pocket_id == SLOT_R_STORE ? r_store : l_store)) //item still in the pocket we search
dropItemToGround(pocket_item)
@@ -276,7 +282,8 @@
show_inv(usr)
else
// Display a warning if the user mocks up
to_chat(src, "<span class='warning'>You feel your [pocket_side] pocket being fumbled with!</span>")
if (!strip_silence)
to_chat(src, "<span class='warning'>You feel your [pocket_side] pocket being fumbled with!</span>")
..() //CITADEL CHANGE - removes a tab from behind this ..() so that flavortext can actually be examined
@@ -397,7 +397,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(I.flags_inv & HIDEFACIALHAIR)
facialhair_hidden = TRUE
if(H.wear_mask)
if(H.wear_mask && istype(H.wear_mask))
var/obj/item/clothing/mask/M = H.wear_mask
dynamic_fhair_suffix = M.dynamic_fhair_suffix //mask > head in terms of facial hair
if(M.flags_inv & HIDEFACIALHAIR)
@@ -451,7 +451,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(I.flags_inv & HIDEHAIR)
hair_hidden = TRUE
if(H.wear_mask)
if(H.wear_mask && istype(H.wear_mask))
var/obj/item/clothing/mask/M = H.wear_mask
if(!dynamic_hair_suffix) //head > mask in terms of head hair
dynamic_hair_suffix = M.dynamic_hair_suffix
+1 -1
View File
@@ -24,4 +24,4 @@
if(ranged_ability)
ranged_ability.add_ranged_ability(src, "<span class='notice'>You currently have <b>[ranged_ability]</b> active!</span>")
if(vore_init && !vorepref_init) //Vore's been initialized, voreprefs haven't. If this triggers then that means that voreprefs failed to load due to the client being missing.
apply_vore_prefs()
copy_from_prefs_vr()
@@ -1116,6 +1116,7 @@
desc = "Stop controlling your shell and resume normal core operations."
icon_icon = 'icons/mob/actions/actions_AI.dmi'
button_icon_state = "ai_core"
required_mobility_flags = NONE
/datum/action/innate/undeployment/Trigger()
if(!..())
@@ -821,7 +821,6 @@
/obj/item/gps/cyborg,
/obj/item/weapon/gripper/mining,
/obj/item/cyborg_clamp,
/obj/item/card/id/miningborg,
/obj/item/stack/marker_beacon,
/obj/item/destTagger,
/obj/item/stack/packageWrap)
@@ -1023,4 +1022,4 @@
/datum/robot_energy_storage/wrapping_paper
max_energy = 30
recharge_rate = 1
name = "Wrapping Paper Storage"
name = "Wrapping Paper Storage"
@@ -363,10 +363,8 @@
icon_dead = "old_corgi_dead"
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
turns_per_move = 20
var/datum/element/mob_holder/ele = SSdcs.GetElement(/datum/element/mob_holder, held_icon)
if(ele)
ele.Detach(src)
AddElement(/datum/element/mob_holder, "old_corgi")
RemoveElement(/datum/element/mob_holder, held_icon)
AddElement(/datum/element/mob_holder, "old_corgi")
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
@@ -447,7 +445,7 @@
sleep(3)
step_to(src,movement_target,1)
if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds
if(movement_target?.loc) //Not redundant due to sleeps, Item can be gone in 6 decisecomds
if (movement_target.loc.x < src.x)
setDir(WEST)
else if (movement_target.loc.x > src.x)
@@ -204,7 +204,7 @@
rapid = 2
icon_state = "syndicate_smg"
icon_living = "syndicate_smg"
casingtype = /obj/item/ammo_casing/c45/nostamina
casingtype = /obj/item/ammo_casing/c45
projectilesound = 'sound/weapons/gunshot_smg.ogg'
/mob/living/simple_animal/hostile/syndicate/ranged/smg/pilot //caravan ambush ruin
@@ -12,6 +12,10 @@
battery = new battery_type(src)
..()
/obj/item/computer_hardware/battery/Destroy()
. = ..()
QDEL_NULL(battery)
/obj/item/computer_hardware/battery/try_insert(obj/item/I, mob/living/user = null)
if(!holder)
return FALSE
+3
View File
@@ -70,6 +70,9 @@
else
. = FALSE //as to not cancel attack_hand()
/obj/item/clothing/gloves/space_ninja/dropped(mob/user)
. = ..()
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
/obj/item/clothing/gloves/space_ninja/proc/toggledrain()
var/mob/living/carbon/human/U = loc
+5 -1
View File
@@ -9,4 +9,8 @@
strip_delay = 12
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
blockTracking = 1//Roughly the only unique thing about this helmet.
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
/obj/item/clothing/head/helmet/space/space_ninja/dropped(mob/user)
. = ..()
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
+4
View File
@@ -19,6 +19,10 @@ Contents:
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
modifies_speech = TRUE
/obj/item/clothing/mask/gas/space_ninja/dropped(mob/user)
. = ..()
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
/obj/item/clothing/mask/gas/space_ninja/handle_speech(datum/source, list/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
if(message[1] != "*")
@@ -24,9 +24,6 @@
caliber = ".45"
projectile_type = /obj/item/projectile/bullet/c45
/obj/item/ammo_casing/c45/nostamina
projectile_type = /obj/item/projectile/bullet/c45_nostamina
/obj/item/ammo_casing/c45/kitchengun
desc = "A .45 bullet casing. It has a small sponge attached to it."
projectile_type = /obj/item/projectile/bullet/c45_cleaning
@@ -1,17 +1,21 @@
/obj/item/ammo_casing/caseless/arrow
name = "wooden arrow"
desc = "An arrow made of wood, typically fired from a bow."
name = "arrow of questionable material"
desc = "You shouldn't be seeing this arrow."
projectile_type = /obj/item/projectile/bullet/reusable/arrow
caliber = "arrow"
icon_state = "arrow"
throwforce = 3 //good luck hitting someone with the pointy end of the arrow
throw_speed = 3
/obj/item/ammo_casing/caseless/arrow/ashen
/obj/item/ammo_casing/caseless/arrow/wood
name = "wooden arrow"
desc = "An arrow made of wood, typically fired from a bow."
/obj/item/ammo_casing/caseless/arrow/ash
name = "ashen arrow"
desc = "An arrow made of wood, hardened by fire."
icon_state = "ashenarrow"
projectile_type = /obj/item/projectile/bullet/reusable/arrow/ashen
projectile_type = /obj/item/projectile/bullet/reusable/arrow/ash
/obj/item/ammo_casing/caseless/arrow/bone
name = "bone arrow"
+1 -1
View File
@@ -60,7 +60,7 @@
/obj/item/ammo_box/magazine/smgm45
name = "SMG magazine (.45)"
icon_state = "c20r45-24"
ammo_type = /obj/item/ammo_casing/c45/nostamina
ammo_type = /obj/item/ammo_casing/c45
caliber = ".45"
max_ammo = 24
@@ -47,7 +47,7 @@
var/mob/current_user = null
var/list/obj/effect/projectile/tracer/current_tracers
var/structure_piercing = 1
var/structure_piercing = 0
var/structure_bleed_coeff = 0.7
var/wall_pierce_amount = 0
var/wall_devastate = 0
@@ -60,7 +60,7 @@
var/impact_structure_damage = 75
var/projectile_damage = 40
var/projectile_stun = 0
var/projectile_setting_pierce = TRUE
var/projectile_setting_pierce = FALSE
var/delay = 30
var/lastfire = 0
@@ -160,6 +160,9 @@
add_overlay(drained_overlay)
/obj/item/gun/energy/beam_rifle/attack_self(mob/user)
if(!structure_piercing)
projectile_setting_pierce = FALSE
return
projectile_setting_pierce = !projectile_setting_pierce
to_chat(user, "<span class='boldnotice'>You set \the [src] to [projectile_setting_pierce? "pierce":"impact"] mode.</span>")
aiming_beam()
@@ -402,7 +405,7 @@
/obj/item/ammo_casing/energy/beam_rifle/hitscan
projectile_type = /obj/item/projectile/beam/beam_rifle/hitscan
select_name = "beam"
e_cost = 5000
e_cost = 10000
fire_sound = 'sound/weapons/beam_sniper.ogg'
/obj/item/projectile/beam/beam_rifle
@@ -557,9 +560,4 @@
hitscan_light_color_override = "#99ff99"
/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/prehit(atom/target)
qdel(src)
return FALSE
/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/on_hit()
qdel(src)
return BULLET_ACT_HIT
@@ -1,18 +1,12 @@
// .45 (M1911 & C20r)
/obj/item/projectile/bullet/c45
name = ".45 bullet"
damage = 20
stamina = 65
/obj/item/projectile/bullet/c45_nostamina
name = ".45 bullet"
damage = 30
/obj/item/projectile/bullet/c45_cleaning
name = ".45 bullet"
damage = 24
stamina = 10
damage = 40 //BANG BANG BANG
/obj/item/projectile/bullet/c45_cleaning/on_hit(atom/target, blocked = FALSE)
. = ..()
@@ -3,13 +3,13 @@
desc = "Woosh!"
damage = 15
icon_state = "arrow"
ammo_type = /obj/item/ammo_casing/caseless/arrow
ammo_type = /obj/item/ammo_casing/caseless/arrow/wood
/obj/item/projectile/bullet/reusable/arrow/ashen
/obj/item/projectile/bullet/reusable/arrow/ash
name = "ashen arrow"
desc = "Fire harderned arrow."
damage = 25
ammo_type = /obj/item/ammo_casing/caseless/arrow/ashen
ammo_type = /obj/item/ammo_casing/caseless/arrow/ash
/obj/item/projectile/bullet/reusable/arrow/bone //AP for ashwalkers
name = "bone arrow"
+3 -4
View File
@@ -43,14 +43,14 @@
set_APTFT()
return TRUE
/obj/item/reagent_containers/proc/set_APTFT(mob/user) //set amount_per_transfer_from_this
/obj/item/reagent_containers/proc/set_APTFT() //set amount_per_transfer_from_this
set name = "Set Transfer Amount"
set category = "Object"
set waitfor = FALSE
var/N = input("Amount per transfer from this:","[src]") as null|anything in possible_transfer_amounts
if(N)
amount_per_transfer_from_this = N
to_chat(user, "<span class='notice'>[src]'s transfer amount is now [amount_per_transfer_from_this] units.</span>")
to_chat(usr, "<span class='notice'>[src]'s transfer amount is now [amount_per_transfer_from_this] units.</span>")
/obj/item/reagent_containers/proc/add_initial_reagents()
if(list_reagents)
@@ -134,6 +134,7 @@
throwerstring = " THROWN BY [key_name(thrownby)] at [AT] (AREACOORD(AT)]"
log_reagent("SPLASH: [src] mob SplashReagents() onto [key_name(target)] at [TT] ([AREACOORD(TT)])[throwerstring] - [R]")
reagents.reaction(target, TOUCH)
reagents.clear_reagents()
else if(bartender_check(target) && thrown)
visible_message("<span class='notice'>[src] lands without spilling a single drop.</span>")
@@ -154,8 +155,6 @@
visible_message("<span class='notice'>[src] spills its contents all over [target].</span>")
reagents.reaction(target, TOUCH)
reagents.clear_reagents()
if(QDELETED(src))
return
//melts plastic beakers
/obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M)
@@ -35,6 +35,17 @@
dangerous_construction = TRUE
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
/datum/design/duffelbag_holding
name = "Duffel Bag of Holding"
desc = "A duffel bag that opens into a localized pocket of bluespace."
id = "duffelbag_holding"
build_type = PROTOLATHE
materials = list(/datum/material/gold = 3000, /datum/material/diamond = 1500, /datum/material/uranium = 250, /datum/material/bluespace = 2000)
build_path = /obj/item/storage/backpack/holding/duffel
category = list("Bluespace Designs")
dangerous_construction = TRUE
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
/datum/design/biobag_holding
name = "Bio Bag of Holding"
desc = "A chemical holding thingy. Mostly used for xenobiology."
@@ -633,15 +633,6 @@
construction_time = 120
category = list("Cyborg Upgrade Modules")
/datum/design/borg_upgrade_premiumka
name = "Cyborg Upgrade (Premium Kinetic Accelerator)"
id = "borg_upgrade_premiumka"
build_type = MECHFAB
build_path = /obj/item/borg/upgrade/premiumka
materials = list(/datum/material/iron=8000, /datum/material/glass=4000, /datum/material/titanium=2000)
construction_time = 120
category = list("Cyborg Upgrade Modules")
/datum/design/borg_upgrade_lavaproof
name = "Cyborg Upgrade (Lavaproof Tracks)"
id = "borg_upgrade_lavaproof"
+2 -2
View File
@@ -278,7 +278,7 @@
display_name = "Bluespace Pockets"
description = "Studies into the mysterious alternate dimension known as bluespace and how to place items in the threads of reality."
prereq_ids = list("adv_power", "adv_bluespace", "adv_biotech", "adv_plasma")
design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag")
design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag", "duffelbag_holding")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5500)
/datum/techweb_node/bluespace_portal
@@ -336,7 +336,7 @@
display_name = "Advanced Robotics Research"
description = "It can even do the dishes!"
prereq_ids = list("robotics")
design_ids = list("borg_upgrade_diamonddrill", "borg_upgrade_advancedmop", "borg_upgrade_advcutter", "borg_upgrade_premiumka")
design_ids = list("borg_upgrade_diamonddrill", "borg_upgrade_advancedmop", "borg_upgrade_advcutter")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000)
/datum/techweb_node/neural_programming
+2
View File
@@ -319,6 +319,8 @@
on_mob.forceMove(scanning)
for(var/i in 1 to light_beam_distance)
scanning = get_step(scanning, scandir)
if(!scanning)
break
if(scanning.opacity || scanning.has_opaque_atom)
stop = TRUE
var/obj/effect/abstract/eye_lighting/L = LAZYACCESS(eye_lighting, i)
@@ -159,7 +159,7 @@
/datum/uplink_item/role_restricted/kitchen_gun
name = "Kitchen Gun (TM)"
desc = "A revolutionary .45 caliber cleaning solution! Say goodbye to daily stains and dirty surfaces with Kitchen Gun (TM)! \
Just five shots from Kitchen Gun (TM), and it'll sparkle like new! Includes two extra ammunition clips!"
Just three shots from Kitchen Gun (TM), and it'll sparkle like new! Includes two extra ammunition clips!"
cost = 10
surplus = 40
restricted_roles = list("Cook", "Janitor")
+39 -49
View File
@@ -41,7 +41,7 @@
return TRUE
//We'll load our client's organs if we have one
if(client && client.prefs_vr)
if(client?.prefs)
if(!copy_from_prefs_vr())
to_chat(src,"<span class='warning'>ERROR: You seem to have saved vore prefs, but they couldn't be loaded.</span>")
return FALSE
@@ -262,47 +262,22 @@
else
to_chat(src,"<span class='alert'>You aren't inside anyone, though, is the thing.</span>")
//
// Verb for saving vore preferences to save file
//
/mob/living/proc/save_vore_prefs()
if(!client || !client.prefs_vr)
return FALSE
if(!copy_to_prefs_vr())
return FALSE
if(!client.prefs_vr.save_vore())
return FALSE
return TRUE
/mob/living/proc/apply_vore_prefs()
if(!client || !client.prefs_vr)
return FALSE
if(!client.prefs_vr.load_vore())
return FALSE
if(!copy_from_prefs_vr())
return FALSE
return TRUE
/mob/living/proc/copy_to_prefs_vr()
if(!client || !client.prefs_vr)
to_chat(src,"<span class='warning'>You attempted to save your vore prefs but somehow you're in this character without a client.prefs_vr variable. Tell a dev.</span>")
if(!client || !client.prefs)
to_chat(src,"<span class='warning'>You attempted to save your vore prefs but somehow you're in this character without a client.prefs variable. Tell a dev.</span>")
return FALSE
var/datum/vore_preferences/P = client.prefs_vr
P.digestable = src.digestable
P.devourable = src.devourable
P.feeding = src.feeding
P.vore_taste = src.vore_taste
client.prefs.digestable = digestable
client.prefs.devourable = devourable
client.prefs.feeding = feeding
client.prefs.vore_taste = vore_taste
var/list/serialized = list()
for(var/belly in src.vore_organs)
for(var/belly in vore_organs)
var/obj/belly/B = belly
serialized += list(B.serialize()) //Can't add a list as an object to another list in Byond. Thanks.
P.belly_prefs = serialized
client.prefs.belly_prefs = serialized
return TRUE
@@ -310,21 +285,20 @@
// Proc for applying vore preferences, given bellies
//
/mob/living/proc/copy_from_prefs_vr()
if(!client || !client.prefs_vr)
to_chat(src,"<span class='warning'>You attempted to apply your vore prefs but somehow you're in this character without a client.prefs_vr variable. Tell a dev.</span>")
if(!client || !client.prefs)
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
vorepref_init = TRUE
var/datum/vore_preferences/P = client.prefs_vr
digestable = P.digestable
devourable = P.devourable
feeding = P.feeding
vore_taste = P.vore_taste
digestable = client.prefs.digestable
devourable = client.prefs.devourable
feeding = client.prefs.feeding
vore_taste = client.prefs.vore_taste
release_vore_contents(silent = TRUE)
vore_organs.Cut()
for(var/entry in P.belly_prefs)
QDEL_LIST(vore_organs)
for(var/entry in client.prefs.belly_prefs)
list_to_object(entry,src)
return TRUE
@@ -376,23 +350,31 @@
//
// Clearly super important. Obviously.
//
/mob/living/proc/lick(var/mob/living/tasted in oview(1))
/mob/living/proc/lick()
set name = "Lick Someone"
set category = "Vore"
set desc = "Lick someone nearby!"
if(!istype(tasted))
if(incapacitated(ignore_restraints = TRUE))
to_chat(src, "<span class='warning'>You can't do that while incapacitated.</span>")
return
if(!tasted.client?.prefs_vr.lickable)
var/list/choices
for(var/mob/living/L in view(1))
if(L != src && (!L.ckey || L.client?.prefs.lickable) && Adjacent(L))
LAZYADD(choices, L)
if(!choices)
return
if(src == stat)
var/mob/living/tasted = input(src, "Who would you like to lick? (Excluding yourself and those with the preference disabled)", "Licking") as null|anything in choices
if(QDELETED(tasted) || (tasted.ckey && !(tasted.client?.prefs.lickable)) || !Adjacent(tasted) || incapacitated(ignore_restraints = TRUE))
return
src.setClickCooldown(100)
setClickCooldown(100)
src.visible_message("<span class='warning'>[src] licks [tasted]!</span>","<span class='notice'>You lick [tasted]. They taste rather like [tasted.get_taste_message()].</span>","<b>Slurp!</b>")
visible_message("<span class='warning'>[src] licks [tasted]!</span>","<span class='notice'>You lick [tasted]. They taste rather like [tasted.get_taste_message()].</span>","<b>Slurp!</b>")
/mob/living/proc/get_taste_message(allow_generic = TRUE, datum/species/mrace)
@@ -408,3 +390,11 @@
else
taste_message += "a plain old normal [src]"
return taste_message
// Check if an object is capable of eating things, based on vore_organs
//
/proc/is_vore_predator(var/mob/living/O)
if(istype(O))
if(O.vore_organs.len > 0)
return TRUE
return FALSE
-174
View File
@@ -1,174 +0,0 @@
/*
VVVVVVVV VVVVVVVV OOOOOOOOO RRRRRRRRRRRRRRRRR EEEEEEEEEEEEEEEEEEEEEE
V::::::V V::::::V OO:::::::::OO R::::::::::::::::R E::::::::::::::::::::E
V::::::V V::::::V OO:::::::::::::OO R::::::RRRRRR:::::R E::::::::::::::::::::E
V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEEEEE::::E
V:::::V V:::::V O::::::O O::::::O R::::R R:::::R E:::::E EEEEEE
V:::::V V:::::V O:::::O O:::::O R::::R R:::::R E:::::E
V:::::V V:::::V O:::::O O:::::O R::::RRRRRR:::::R E::::::EEEEEEEEEE
V:::::V V:::::V O:::::O O:::::O R:::::::::::::RR E:::::::::::::::E
V:::::V V:::::V O:::::O O:::::O R::::RRRRRR:::::R E:::::::::::::::E
V:::::V V:::::V O:::::O O:::::O R::::R R:::::R E::::::EEEEEEEEEE
V:::::V:::::V O:::::O O:::::O R::::R R:::::R E:::::E
V:::::::::V O::::::O O::::::O R::::R R:::::R E:::::E EEEEEE
V:::::::V O:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEEEE:::::E
V:::::V OO:::::::::::::OO R::::::R R:::::RE::::::::::::::::::::E
V:::V OO:::::::::OO R::::::R R:::::RE::::::::::::::::::::E
VVV OOOOOOOOO RRRRRRRR RRRRRRREEEEEEEEEEEEEEEEEEEEEE
-Aro <3 */
//
// Overrides/additions to stock defines go here, as well as hooks. Sort them by
// the object they are overriding. So all /mob/living together, etc.
//
//
// The datum type bolted onto normal preferences datums for storing Vore stuff
//
#define VORE_VERSION 4
GLOBAL_LIST_EMPTY(vore_preferences_datums)
/client
var/datum/vore_preferences/prefs_vr
/datum/vore_preferences
//Actual preferences
var/digestable = FALSE
var/devourable = FALSE
var/feeding = FALSE
var/lickable = FALSE
// var/allowmobvore = TRUE
var/list/belly_prefs = list()
var/vore_taste = "nothing in particular"
// var/can_be_drop_prey = FALSE
// var/can_be_drop_pred = FALSE
//Mechanically required
var/path
var/slot
var/client/client
var/client_ckey
/datum/vore_preferences/New(client/C)
if(istype(C))
client = C
client_ckey = C.ckey
load_vore()
//
// Check if an object is capable of eating things, based on vore_organs
//
/proc/is_vore_predator(var/mob/living/O)
if(istype(O,/mob/living))
if(O.vore_organs.len > 0)
return TRUE
return FALSE
//
// Belly searching for simplifying other procs
// Mostly redundant now with belly-objects and isbelly(loc)
//
/proc/check_belly(atom/movable/A)
return isbelly(A.loc)
//
// Save/Load Vore Preferences
//
/datum/vore_preferences/proc/load_path(ckey,slot,filename="character",ext="json")
if(!ckey || !slot) return
path = "data/player_saves/[ckey[1]]/[ckey]/vore/[filename][slot].[ext]"
/datum/vore_preferences/proc/load_vore()
if(!client || !client_ckey)
return FALSE //No client, how can we save?
if(!client.prefs || !client.prefs.default_slot)
return FALSE //Need to know what character to load!
slot = client.prefs.default_slot
load_path(client_ckey,slot)
if(!path) return FALSE //Path couldn't be set?
if(!fexists(path)) //Never saved before
save_vore() //Make the file first
return TRUE
var/list/json_from_file = json_decode(file2text(path))
if(!json_from_file)
return FALSE //My concern grows
var/version = json_from_file["version"]
json_from_file = patch_version(json_from_file,version)
digestable = json_from_file["digestable"]
devourable = json_from_file["devourable"]
feeding = json_from_file["feeding"]
lickable = json_from_file["lickable"]
vore_taste = json_from_file["vore_taste"]
belly_prefs = json_from_file["belly_prefs"]
//Quick sanitize
if(isnull(digestable))
digestable = FALSE
if(isnull(devourable))
devourable = FALSE
if(isnull(feeding))
feeding = FALSE
if(isnull(lickable))
lickable = FALSE
if(isnull(belly_prefs))
belly_prefs = list()
return TRUE
/datum/vore_preferences/proc/save_vore()
if(!path)
return FALSE
var/version = VORE_VERSION //For "good times" use in the future
var/list/settings_list = list(
"version" = version,
"digestable" = digestable,
"devourable" = devourable,
"feeding" = feeding,
"lickable" = lickable,
"vore_taste" = vore_taste,
"belly_prefs" = belly_prefs,
)
//List to JSON
var/json_to_file = json_encode(settings_list)
if(!json_to_file)
testing("Saving: [path] failed jsonencode")
return FALSE
//Write it out
//#ifdef RUST_G
// call(RUST_G, "file_write")(json_to_file, path)
//#else
// Fall back to using old format if we are not using rust-g
if(fexists(path))
fdel(path) //Byond only supports APPENDING to files, not replacing.
text2file(json_to_file, path)
//#endif
if(!fexists(path))
testing("Saving: [path] failed file write")
return FALSE
return TRUE
/* commented out list things
"allowmobvore" = allowmobvore,
"can_be_drop_prey" = can_be_drop_prey,
"can_be_drop_pred" = can_be_drop_pred, */
//Can do conversions here
datum/vore_preferences/proc/patch_version(var/list/json_from_file,var/version)
return json_from_file
#undef VORE_VERSION
+29 -25
View File
@@ -6,7 +6,6 @@
#define BELLIES_NAME_MIN 2
#define BELLIES_NAME_MAX 12
#define BELLIES_DESC_MAX 1024
#define FLAVOR_MAX 40
/mob/living/proc/insidePanel()
set name = "Vore Panel"
@@ -247,8 +246,8 @@
dat += "<br><a style='background:[user.digestable ? pref_on : pref_off];' href='?src=\ref[src];toggledg=1'>Toggle Digestable (Currently: [user.digestable ? "ON" : "OFF"])</a>"
dat += "<br><a style='background:[user.devourable ? pref_on : pref_off];' href='?src=\ref[src];toggledvor=1'>Toggle Devourable (Currently: [user.devourable ? "ON" : "OFF"])</a>"
dat += "<br><a style='background:[user.feeding ? pref_on : pref_off];' href='?src=\ref[src];toggledfeed=1'>Toggle Feeding (Currently: [user.feeding ? "ON" : "OFF"])</a>"
if(user.client.prefs_vr)
dat += "<br><a style='background:[user.client.prefs_vr.lickable ? pref_on : pref_off];' href='?src=\ref[src];toggledlickable=1'>Toggle Licking (Currently: [user.client.prefs_vr.lickable ? "ON" : "OFF"])</a>"
if(user.client.prefs)
dat += "<br><a style='background:[user.client.prefs.lickable ? pref_on : pref_off];' href='?src=\ref[src];toggledlickable=1'>Toggle Licking (Currently: [user.client.prefs.lickable ? "ON" : "OFF"])</a>"
//Returns the dat html to the vore_look
return dat
@@ -659,18 +658,19 @@
user.vore_selected = user.vore_organs[1]
if(href_list["saveprefs"])
if(!user.save_vore_prefs())
if(!(user.client?.prefs))
return FALSE
if(!user.client.prefs.save_character())
to_chat(user, "<span class='warning'>Belly Preferences not saved!</span>")
log_admin("Could not save vore prefs on USER: [user].")
else
to_chat(user, "<span class='notice'>Belly Preferences were saved!</span>")
log_admin("Could not save vore prefs on USER: [user].")
if(href_list["applyprefs"])
var/alert = alert("Are you sure you want to reload character slot preferences? This will remove your current vore organs and eject their contents.","Confirmation","Reload","Cancel")
var/alert = alert("Are you sure you want to reload the current slot preferences? This will remove your current vore organs and eject their contents.","Confirmation","Reload","Cancel")
if(!alert == "Reload")
return FALSE
if(!user.apply_vore_prefs())
if(!user.copy_from_prefs_vr())
alert("ERROR: Vore preferences failed to apply!","Error")
else
to_chat(user,"<span class='notice'>Vore preferences applied from active slot!</span>")
@@ -681,13 +681,15 @@
return FALSE
new_flavor = readd_quotes(new_flavor)
if(length(new_flavor) > FLAVOR_MAX)
alert("Entered flavor/taste text too long. [FLAVOR_MAX] character limit.","Error!")
if(length(new_flavor) > MAX_TASTE_LEN)
alert("Entered flavor/taste text too long. [MAX_TASTE_LEN] character limit.","Error!")
return FALSE
user.vore_taste = new_flavor
if(href_list["toggledg"])
var/choice = alert(user, "This button is for those who don't like being digested. It can make you undigestable to all mobs. Digesting you is currently: [user.digestable ? "Allowed" : "Prevented"]", "", "Allow Digestion", "Cancel", "Prevent Digestion")
if(!user || !user.client)
return
switch(choice)
if("Cancel")
return FALSE
@@ -696,11 +698,12 @@
if("Prevent Digestion")
user.digestable = FALSE
if(user.client.prefs_vr)
user.client.prefs_vr.digestable = user.digestable
user.client.prefs.digestable = user.digestable
if(href_list["toggledvor"])
var/choice = alert(user, "This button is for those who don't like vore at all. Devouring you is currently: [user.devourable ? "Allowed" : "Prevented"]", "", "Allow Devourment", "Cancel", "Prevent Devourment")
if(!user || !user.client)
return
switch(choice)
if("Cancel")
return FALSE
@@ -709,11 +712,12 @@
if("Prevent Devourment")
user.devourable = FALSE
if(user.client.prefs_vr)
user.client.prefs_vr.devourable = user.devourable
user.client.prefs.devourable = user.devourable
if(href_list["toggledfeed"])
var/choice = alert(user, "This button is to toggle your ability to be fed to others. Feeding predators is currently: [user.feeding ? "Allowed" : "Prevented"]", "", "Allow Feeding", "Cancel", "Prevent Feeding")
if(!user || !user.client)
return
switch(choice)
if("Cancel")
return FALSE
@@ -722,19 +726,19 @@
if("Prevent Feeding")
user.feeding = FALSE
if(user.client.prefs_vr)
user.client.prefs_vr.feeding = user.feeding
user.client.prefs.feeding = user.feeding
if(href_list["toggledlickable"])
if(user.client.prefs_vr)
var/choice = alert(user, "This button is to toggle your ability to be licked. Being licked is currently: [user.client.prefs_vr.lickable ? "Allowed" : "Prevented"]", "", "Allow Licking", "Cancel", "Prevent Licking")
switch(choice)
if("Cancel")
return FALSE
if("Allow Licking")
user.client.prefs_vr.lickable = TRUE
if("Prevent Licking")
user.client.prefs_vr.lickable = FALSE
var/choice = alert(user, "This button is to toggle your ability to be licked. Being licked is currently: [user.client.prefs.lickable ? "Allowed" : "Prevented"]", "", "Allow Licking", "Cancel", "Prevent Licking")
if(!user || !user.client)
return
switch(choice)
if("Cancel")
return FALSE
if("Allow Licking")
user.client.prefs.lickable = TRUE
if("Prevent Licking")
user.client.prefs.lickable = FALSE
//Refresh when interacted with, returning 1 makes vore_look.Topic update
return TRUE