Merge remote-tracking branch 'refs/remotes/Citadel-Station-13/master' into crewobjectivesandmiscreants

This commit is contained in:
deathride58
2017-09-27 23:44:22 -04:00
619 changed files with 12516 additions and 11883 deletions
@@ -1,9 +0,0 @@
diff a/code/modules/mob/dead/new_player/login.dm b/code/modules/mob/dead/new_player/login.dm (rejected hunks)
@@ -1,5 +1,6 @@
/mob/dead/new_player/Login()
- client.update_exp_client(0, 0)
+ if(config.use_exp_tracking)
+ client.update_exp_client(0, 0)
if(!mind)
mind = new /datum/mind(key)
mind.active = 1
@@ -329,6 +329,9 @@
if(SSshuttle.arrivals.damaged && config.arrivals_shuttle_require_safe_latejoin)
src << alert("The arrivals shuttle is currently malfunctioning! You cannot join.")
return FALSE
if(config.arrivals_shuttle_require_undocked)
SSshuttle.arrivals.RequireUndocked(src)
arrivals_docked = SSshuttle.arrivals.mode != SHUTTLE_CALL
//Remove the player from the join queue if he was in one and reset the timer
@@ -394,12 +397,7 @@
/mob/dead/new_player/proc/LateChoices()
var/mills = world.time - SSticker.round_start_time // 1/10 of a second, not real milliseconds but whatever
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
var/mins = (mills % 36000) / 600
var/hours = mills / 36000
var/dat = "<div class='notice'>Round Duration: [round(hours)]h [round(mins)]m</div>"
var/dat = "<div class='notice'>Round Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]</div>"
if(SSshuttle.emergency)
switch(SSshuttle.emergency.mode)
+1 -1
View File
@@ -417,7 +417,7 @@
to_chat(src, "<span class='danger'>Invalid vote data</span>")
return 0
//lets add the vote, first we generate a insert statement.
//lets add the vote, first we generate an insert statement.
var/sqlrowlist = ""
for (var/vote in numberedvotelist)
@@ -1,100 +1,84 @@
//The mob should have a gender you want before running this proc. Will run fine without H
/datum/preferences/proc/random_character(gender_override)
if(gender_override)
gender = gender_override
else
gender = pick(MALE,FEMALE)
skin_tone = random_skin_tone()
hair_style = random_hair_style(gender)
facial_hair_style = random_facial_hair_style(gender)
hair_color = random_short_color()
facial_hair_color = hair_color
eye_color = random_eye_color()
if(!pref_species)
var/rando_race = pick(config.roundstart_races)
pref_species = new rando_race()
features = random_features()
age = rand(AGE_MIN,AGE_MAX)
/datum/preferences/proc/update_preview_icon(nude = 0)
var/wide_icon = 0
var/stamp_x = 0
var/stamp_y = 1
if(features["taur"] != "None")
wide_icon = 1
// Silicons only need a very basic preview since there is no customization for them.
if(job_engsec_high)
switch(job_engsec_high)
if(AI_JF)
preview_icon = icon('icons/mob/AI.dmi', "AI", SOUTH)
preview_icon.Scale(64, 64)
return
if(CYBORG)
preview_icon = icon('icons/mob/robots.dmi', "robot", SOUTH)
preview_icon.Scale(64, 64)
return
// Set up the dummy for its photoshoot
var/mob/living/carbon/human/dummy/mannequin = new()
copy_to(mannequin)
// Determine what job is marked as 'High' priority, and dress them up as such.
var/datum/job/previewJob
var/highRankFlag = job_civilian_high | job_medsci_high | job_engsec_high
if(job_civilian_low & ASSISTANT)
previewJob = SSjob.GetJob("Assistant")
else if(highRankFlag)
var/highDeptFlag
if(job_civilian_high)
highDeptFlag = CIVILIAN
else if(job_medsci_high)
highDeptFlag = MEDSCI
else if(job_engsec_high)
highDeptFlag = ENGSEC
for(var/datum/job/job in SSjob.occupations)
if(job.flag == highRankFlag && job.department_flag == highDeptFlag)
previewJob = job
break
if(previewJob && !nude)
mannequin.job = previewJob.title
previewJob.equip(mannequin, TRUE)
mannequin.update_body()
CHECK_TICK
preview_icon = icon('icons/effects/effects.dmi', "nothing")
preview_icon.Scale((112), (32))
CHECK_TICK
mannequin.setDir(NORTH)
var/icon/stamp = getFlatIcon(mannequin)
CHECK_TICK
if(wide_icon)
stamp_x = 16
else
stamp_x = 32
preview_icon.Blend(stamp, ICON_OVERLAY, stamp_x, stamp_y)
CHECK_TICK
mannequin.setDir(WEST)
stamp = getFlatIcon(mannequin)
CHECK_TICK
if(wide_icon)
stamp_x = 48
else
stamp_x = 64
preview_icon.Blend(stamp, ICON_OVERLAY, stamp_x, stamp_y)
CHECK_TICK
mannequin.setDir(SOUTH)
stamp = getFlatIcon(mannequin)
CHECK_TICK
if(wide_icon)
stamp_x = -15
else
stamp_x = 1
preview_icon.Blend(stamp, ICON_OVERLAY, stamp_x, stamp_y)
CHECK_TICK
preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
CHECK_TICK
qdel(mannequin)
//The mob should have a gender you want before running this proc. Will run fine without H
/datum/preferences/proc/random_character(gender_override)
if(gender_override)
gender = gender_override
else
gender = pick(MALE,FEMALE)
underwear = random_underwear(gender)
undershirt = random_undershirt(gender)
socks = random_socks()
skin_tone = random_skin_tone()
hair_style = random_hair_style(gender)
facial_hair_style = random_facial_hair_style(gender)
hair_color = random_short_color()
facial_hair_color = hair_color
eye_color = random_eye_color()
if(!pref_species)
var/rando_race = pick(config.roundstart_races)
pref_species = new rando_race()
features = random_features()
age = rand(AGE_MIN,AGE_MAX)
/datum/preferences/proc/update_preview_icon(nude = 0)
// Silicons only need a very basic preview since there is no customization for them.
if(job_engsec_high)
switch(job_engsec_high)
if(AI_JF)
preview_icon = icon('icons/mob/ai.dmi', "AI", SOUTH)
preview_icon.Scale(64, 64)
return
if(CYBORG)
preview_icon = icon('icons/mob/robots.dmi', "robot", SOUTH)
preview_icon.Scale(64, 64)
return
// Set up the dummy for its photoshoot
var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES)
copy_to(mannequin)
// Determine what job is marked as 'High' priority, and dress them up as such.
var/datum/job/previewJob
var/highRankFlag = job_civilian_high | job_medsci_high | job_engsec_high
if(job_civilian_low & ASSISTANT)
previewJob = SSjob.GetJob("Assistant")
else if(highRankFlag)
var/highDeptFlag
if(job_civilian_high)
highDeptFlag = CIVILIAN
else if(job_medsci_high)
highDeptFlag = MEDSCI
else if(job_engsec_high)
highDeptFlag = ENGSEC
for(var/datum/job/job in SSjob.occupations)
if(job.flag == highRankFlag && job.department_flag == highDeptFlag)
previewJob = job
break
if(previewJob && !nude)
mannequin.job = previewJob.title
previewJob.equip(mannequin, TRUE)
CHECK_TICK
preview_icon = icon('icons/effects/effects.dmi', "nothing")
preview_icon.Scale(48+32, 16+32)
CHECK_TICK
mannequin.setDir(NORTH)
var/icon/stamp = getFlatIcon(mannequin)
CHECK_TICK
preview_icon.Blend(stamp, ICON_OVERLAY, 25, 17)
CHECK_TICK
mannequin.setDir(WEST)
stamp = getFlatIcon(mannequin)
CHECK_TICK
preview_icon.Blend(stamp, ICON_OVERLAY, 1, 9)
CHECK_TICK
mannequin.setDir(SOUTH)
stamp = getFlatIcon(mannequin)
CHECK_TICK
preview_icon.Blend(stamp, ICON_OVERLAY, 49, 1)
CHECK_TICK
preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
CHECK_TICK
unset_busy_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES)
+1 -3
View File
@@ -711,9 +711,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
update_icon()
/mob/dead/observer/canUseTopic(atom/movable/AM,be_close = FALSE)
if(check_rights(R_ADMIN, 0))
return 1
return
return IsAdminGhost(usr)
/mob/dead/observer/is_literate()
return 1
+4 -2
View File
@@ -13,6 +13,7 @@
var/obj/item/organ/brain/brain = null //The actual brain
var/datum/ai_laws/laws = new()
var/force_replace_ai_name = FALSE
var/overrides_aicore_laws = FALSE // Whether the laws on the MMI, if any, override possible pre-existing laws loaded on the AI core.
/obj/item/device/mmi/update_icon()
if(brain)
@@ -203,8 +204,9 @@
name = "Syndicate Man-Machine Interface"
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs and AIs created with it."
origin_tech = "biotech=4;programming=4;syndicate=2"
overrides_aicore_laws = TRUE
/obj/item/device/mmi/syndie/New()
..()
/obj/item/device/mmi/syndie/Initialize()
. = ..()
laws = new /datum/ai_laws/syndicate_override()
radio.on = 0
@@ -40,7 +40,7 @@
create_internal_organs()
..()
. = ..()
/mob/living/carbon/alien/create_internal_organs()
internal_organs += new /obj/item/organ/brain/alien
@@ -8,7 +8,7 @@
/mob/living/carbon/alien/humanoid/drone/Initialize()
AddAbility(new/obj/effect/proc_holder/alien/evolve(null))
..()
. = ..()
/mob/living/carbon/alien/humanoid/drone/create_internal_organs()
@@ -38,11 +38,11 @@
#define MAX_ALIEN_LEAP_DIST 7
/mob/living/carbon/alien/humanoid/hunter/proc/leap_at(atom/A)
if(pounce_cooldown > world.time)
to_chat(src, "<span class='alertalien'>You are too fatigued to pounce right now!</span>")
if(!canmove || leaping)
return
if(leaping || stat || buckled || lying)
if(pounce_cooldown > world.time)
to_chat(src, "<span class='alertalien'>You are too fatigued to pounce right now!</span>")
return
if(!has_gravity() || !A.has_gravity())
@@ -66,6 +66,7 @@
if(!leaping)
return ..()
pounce_cooldown = world.time + pounce_cooldown_time
if(A)
if(isliving(A))
var/mob/living/L = A
@@ -83,7 +84,6 @@
Knockdown(40, 1, 1)
toggle_leap(0)
pounce_cooldown = world.time + pounce_cooldown_time
else if(A.density && !A.CanPass(src))
visible_message("<span class ='danger'>[src] smashes into [A]!</span>", "<span class ='alertalien'>[src] smashes into [A]!</span>")
Knockdown(40, 1, 1)
@@ -13,7 +13,7 @@
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src))
AddAbility(new /obj/effect/proc_holder/alien/royal/praetorian/evolve())
..()
. = ..()
/mob/living/carbon/alien/humanoid/royal/praetorian/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/large
@@ -48,4 +48,4 @@
return 1
else
to_chat(user, "<span class='notice'>We already have an alive queen.</span>")
return 0
return 0
@@ -8,7 +8,7 @@
/mob/living/carbon/alien/humanoid/sentinel/Initialize()
AddAbility(new /obj/effect/proc_holder/alien/sneak)
..()
. = ..()
/mob/living/carbon/alien/humanoid/sentinel/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel
@@ -18,4 +18,4 @@
/mob/living/carbon/alien/humanoid/sentinel/movement_delay()
. = ..()
. = ..()
@@ -18,12 +18,13 @@
var/drooling = 0 //For Neruotoxic spit overlays
bodyparts = list(/obj/item/bodypart/chest/alien, /obj/item/bodypart/head/alien, /obj/item/bodypart/l_arm/alien,
/obj/item/bodypart/r_arm/alien, /obj/item/bodypart/r_leg/alien, /obj/item/bodypart/l_leg/alien)
devourable = TRUE
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/Initialize()
AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null))
..()
. = ..()
/mob/living/carbon/alien/humanoid/movement_delay()
. = ..()
@@ -42,7 +43,7 @@
<HR>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags_1 & ABSTRACT_1)) ? I : "<font color=grey>Empty</font>"]</a>"
dat += "<BR><B>[get_held_index_name(i)]:</B><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags_1 & ABSTRACT_1)) ? I : "<font color=grey>Empty</font>"]</a>"
dat += "<BR><A href='?src=\ref[src];pouches=1'>Empty Pouches</A>"
if(handcuffed)
@@ -120,4 +121,4 @@
/mob/living/carbon/alien/humanoid/check_breath(datum/gas_mixture/breath)
if(breath && breath.total_moles() > 0 && !sneaking)
playsound(get_turf(src), pick('sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg'), 50, 0, -5)
..()
..()
@@ -4,7 +4,7 @@
icon_state = "larva0"
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
density = FALSE
density = FALSE
maxHealth = 25
health = 25
@@ -22,7 +22,7 @@
AddAbility(new/obj/effect/proc_holder/alien/hide(null))
AddAbility(new/obj/effect/proc_holder/alien/larva_evolve(null))
..()
. = ..()
/mob/living/carbon/alien/larva/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/small/tiny
@@ -65,4 +65,4 @@
/mob/living/carbon/alien/larva/stripPanelEquip(obj/item/what, mob/who)
to_chat(src, "<span class='warning'>You don't have the dexterity to do this!</span>")
return
return
+6 -2
View File
@@ -297,11 +297,14 @@
/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0)
if(I.being_removed)
to_chat(src, "<span class='warning'>You're already attempting to remove [I]!</span>")
return
I.being_removed = TRUE
breakouttime = I.breakouttime
var/displaytime = breakouttime / 600
if(!cuff_break)
visible_message("<span class='warning'>[src] attempts to remove [I]!</span>")
to_chat(src, "<span class='notice'>You attempt to remove [I]... (This will take around [displaytime] minutes and you need to stand still.)</span>")
to_chat(src, "<span class='notice'>You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)</span>")
if(do_after(src, breakouttime, 0, target = src))
clear_cuffs(I, cuff_break)
else
@@ -318,6 +321,7 @@
else if(cuff_break == INSTANT_CUFFBREAK)
clear_cuffs(I, cuff_break)
I.being_removed = FALSE
/mob/living/carbon/proc/uncuff()
if (handcuffed)
@@ -0,0 +1,43 @@
/mob/living/carbon/human/dummy
real_name = "Test Dummy"
status_flags = GODMODE|CANPUSH
var/in_use = FALSE
INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
/mob/living/carbon/human/dummy/Destroy()
in_use = FALSE
return ..()
/mob/living/carbon/human/dummy/Life()
return
/mob/living/carbon/human/dummy/proc/wipe_state()
QDEL_LIST(contents)
cut_overlays(TRUE)
//Inefficient pooling/caching way.
GLOBAL_LIST_EMPTY(human_dummy_list)
/proc/generate_or_wait_for_human_dummy(slotkey)
if(!slotkey)
return new /mob/living/carbon/human/dummy
var/mob/living/carbon/human/dummy/D = GLOB.human_dummy_list[slotkey]
if(istype(D))
UNTIL(!D.in_use)
else
pass()
if(QDELETED(D))
D = new
GLOB.human_dummy_list[slotkey] = D
D.in_use = TRUE
return D
/proc/unset_busy_human_dummy(slotnumber)
if(!slotnumber)
return
var/mob/living/carbon/human/dummy/D = GLOB.human_dummy_list[slotnumber]
if(istype(D))
D.wipe_state()
D.in_use = FALSE
+1 -10
View File
@@ -5,15 +5,6 @@
icon = 'icons/mob/human.dmi'
icon_state = "caucasian_m"
/mob/living/carbon/human/dummy
real_name = "Test Dummy"
status_flags = GODMODE|CANPUSH
INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
/mob/living/carbon/human/dummy/Life()
return
/mob/living/carbon/human/Initialize()
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
@@ -244,7 +235,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore
return
var/time_taken = I.embedded_unsafe_removal_time*I.w_class
usr.visible_message("<span class='warning'>[usr] attempts to remove [I] from their [L.name].</span>","<span class='notice'>You attempt to remove [I] from your [L.name]... (It will take [time_taken/10] seconds.)</span>")
usr.visible_message("<span class='warning'>[usr] attempts to remove [I] from their [L.name].</span>","<span class='notice'>You attempt to remove [I] from your [L.name]... (It will take [DisplayTimeText(time_taken)].)</span>")
if(do_after(usr, time_taken, needhand = 1, target = src))
if(!I || !L || I.loc != src || !(I in L.embedded_objects))
return
@@ -87,12 +87,16 @@
/// SNPC voice handling
/mob/living/carbon/human/interactive/proc/loadVoice()
var/json_file = file("data/npc_saves/snpc.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
knownStrings = json["knownStrings"]
if(fexists("data/npc_saves/snpc.sav"))
var/savefile/S = new /savefile("data/npc_saves/snpc.sav")
S["knownStrings"] >> knownStrings
fdel(S)
else
var/json_file = file("data/npc_saves/snpc.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
knownStrings = json["knownStrings"]
if(isnull(knownStrings))
knownStrings = list()
@@ -1618,4 +1622,4 @@
TRAITS |= TRAIT_ROBUST
TRAITS |= TRAIT_SMART
faction += "bot_power"
. = ..()
. = ..()
@@ -236,6 +236,10 @@
/mob/living/carbon/human/head_update(obj/item/I, forced)
if((I.flags_inv & (HIDEHAIR|HIDEFACIALHAIR)) || forced)
update_hair()
else
var/obj/item/clothing/C = I
if(istype(C) && C.dynamic_hair_suffix)
update_hair()
if(I.flags_inv & HIDEEYES || forced)
update_inv_glasses()
if(I.flags_inv & HIDEEARS || forced)
@@ -111,6 +111,10 @@
randname += " [pick(GLOB.last_names)]"
return randname
//Called when cloning, copies some vars that should be kept
/datum/species/proc/copy_properties_from(datum/species/old_species)
return
//Please override this locally if you want to define when what species qualifies for what rank if human authority is enforced.
@@ -1437,7 +1441,7 @@
H.adjust_blurriness(10)
if(prob(I.force + ((100 - H.health)/2)) && H != user)
SSticker.mode.remove_revolutionary(H.mind)
SSticker.mode.remove_revolutionary(H.mind, FALSE, user)
if(bloody) //Apply blood
if(H.wear_mask)
@@ -1721,4 +1725,4 @@
#undef COLD_DAMAGE_LEVEL_1
#undef COLD_DAMAGE_LEVEL_2
#undef COLD_DAMAGE_LEVEL_3
#undef COLD_DAMAGE_LEVEL_3
@@ -2,8 +2,10 @@
name = "Abductor"
id = "abductor"
say_mod = "gibbers"
sexes = 0
sexes = FALSE
species_traits = list(NOBLOOD,NOBREATH,VIRUSIMMUNE,NOGUNS,NOHUNGER)
mutanttongue = /obj/item/organ/tongue/abductor
var/scientist = 0 // vars to not pollute spieces list with castes
var/team = 1
var/scientist = FALSE // vars to not pollute spieces list with castes
/datum/species/abductor/copy_properties_from(datum/species/abductor/old_species)
scientist = old_species.scientist
@@ -18,11 +18,10 @@
if(H.dna && H.dna.species &&((H.dna.features["wings"] != "Angel") && ("wings" in H.dna.species.mutant_bodyparts)))
H.dna.features["wings"] = "Angel"
H.update_body()
if(ishuman(H)&& !fly)
if(ishuman(H) && !fly)
fly = new
fly.Grant(H)
/datum/species/angel/on_species_loss(mob/living/carbon/human/H)
if(fly)
fly.Remove(H)
@@ -66,7 +65,7 @@
/datum/action/innate/flight
name = "Toggle Flight"
check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_STUN
icon_icon = 'icons/mob/actions/actions_items.dmi'
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "flight"
/datum/action/innate/flight/Activate()
@@ -159,7 +159,7 @@
name = "Plasteel Golem"
id = "plasteel golem"
fixed_mut_color = "bbb"
stunmod = 0.40
stunmod = 0.4
punchdamagelow = 12
punchdamagehigh = 21
punchstunthreshold = 18 //still 40% stun chance
@@ -436,6 +436,7 @@
name = "Unstable Teleport"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "jaunt"
icon_icon = 'icons/mob/actions/actions_spells.dmi'
var/cooldown = 150
var/last_teleport = 0
@@ -9,7 +9,6 @@
exotic_blood = "slimejelly"
damage_overlay_type = ""
var/datum/action/innate/regenerate_limbs/regenerate_limbs
toxic_food = NONE
liked_food = MEAT
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
@@ -60,6 +59,7 @@
name = "Regenerate Limbs"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimeheal"
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
/datum/action/innate/regenerate_limbs/IsAvailable()
@@ -128,7 +128,7 @@
/datum/species/jelly/slime/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
if(ishuman(C))
/* slime_split = new
/* slime_split = new
slime_split.Grant(C)
swap_body = new
swap_body.Grant(C) */
@@ -140,6 +140,10 @@
C.faction |= "slime"
//If you're cloned you get your body pool back
/datum/species/jelly/slime/copy_properties_from(datum/species/jelly/slime/old_species)
bodies = old_species.bodies
/datum/species/jelly/slime/spec_life(mob/living/carbon/human/H)
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
if(prob(5))
@@ -154,6 +158,7 @@
name = "Split Body"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimesplit"
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
/datum/action/innate/split_body/IsAvailable()
@@ -220,6 +225,7 @@
name = "Swap Body"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimeswap"
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
/datum/action/innate/swap_body/Activate()
@@ -326,4 +332,4 @@
M.transfer_to(dupe)
dupe.visible_message("<span class='notice'>[dupe] blinks and looks \
around.</span>",
"<span class='notice'>...and move this one instead.</span>")
"<span class='notice'>...and move this one instead.</span>")
@@ -30,7 +30,7 @@
burnmod = 1.5
blacklisted = TRUE
no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform, slot_s_store)
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,NO_UNDERWEAR,NOHUNGER)
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,NO_UNDERWEAR,NOHUNGER,NO_DNA_COPY,NOTRANSSTING)
mutanteyes = /obj/item/organ/eyes/night_vision/nightmare
var/obj/effect/proc_holder/spell/targeted/shadowwalk/shadowwalk
@@ -1,121 +1,121 @@
/datum/species/synth
name = "Synth" //inherited from the real species, for health scanners and things
id = "synth"
say_mod = "beep boops" //inherited from a user's real species
sexes = 0
species_traits = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER) //all of these + whatever we inherit from the real species
dangerous_existence = 1
blacklisted = 1
meat = null
damage_overlay_type = "synth"
limbs_id = "synth"
var/list/initial_species_traits = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER) //for getting these values back for assume_disguise()
var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off
var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged
/datum/species/synth/military
name = "Military Synth"
id = "military_synth"
armor = 25
punchdamagelow = 10
punchdamagehigh = 19
punchstunthreshold = 14 //about 50% chance to stun
disguise_fail_health = 50
/datum/species/synth/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
..()
assume_disguise(old_species, H)
/datum/species/synth/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "synthflesh")
chem.reaction_mob(H, TOUCH, 2 ,0) //heal a little
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
return 1
else
return ..()
/datum/species/synth/proc/assume_disguise(datum/species/S, mob/living/carbon/human/H)
if(S && !istype(S, type))
name = S.name
say_mod = S.say_mod
sexes = S.sexes
species_traits = initial_species_traits.Copy()
species_traits.Add(S.species_traits)
attack_verb = S.attack_verb
attack_sound = S.attack_sound
miss_sound = S.miss_sound
meat = S.meat
mutant_bodyparts = S.mutant_bodyparts.Copy()
mutant_organs = S.mutant_organs.Copy()
default_features = S.default_features.Copy()
nojumpsuit = S.nojumpsuit
no_equip = S.no_equip.Copy()
limbs_id = S.limbs_id
use_skintones = S.use_skintones
fixed_mut_color = S.fixed_mut_color
hair_color = S.hair_color
fake_species = new S.type
else
name = initial(name)
say_mod = initial(say_mod)
species_traits = initial_species_traits.Copy()
attack_verb = initial(attack_verb)
attack_sound = initial(attack_sound)
miss_sound = initial(miss_sound)
mutant_bodyparts = list()
default_features = list()
nojumpsuit = initial(nojumpsuit)
no_equip = list()
qdel(fake_species)
fake_species = null
meat = initial(meat)
limbs_id = "synth"
use_skintones = 0
sexes = 0
fixed_mut_color = ""
hair_color = ""
for(var/X in H.bodyparts) //propagates the damage_overlay changes
var/obj/item/bodypart/BP = X
BP.update_limb()
H.update_body_parts() //to update limb icon cache with the new damage overlays
//Proc redirects:
//Passing procs onto the fake_species, to ensure we look as much like them as possible
/datum/species/synth/handle_hair(mob/living/carbon/human/H, forced_colour)
if(fake_species)
fake_species.handle_hair(H, forced_colour)
else
return ..()
/datum/species/synth/handle_body(mob/living/carbon/human/H)
if(fake_species)
fake_species.handle_body(H)
else
return ..()
/datum/species/synth/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
if(fake_species)
fake_species.handle_body(H,forced_colour)
else
return ..()
/datum/species/synth/get_spans()
if(fake_species)
return fake_species.get_spans()
return list()
/datum/species/synth/handle_speech(message, mob/living/carbon/human/H)
if(H.health > disguise_fail_health)
if(fake_species)
return fake_species.handle_speech(message,H)
else
return ..()
else
/datum/species/synth
name = "Synth" //inherited from the real species, for health scanners and things
id = "synth"
say_mod = "beep boops" //inherited from a user's real species
sexes = 0
species_traits = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER) //all of these + whatever we inherit from the real species
dangerous_existence = 1
blacklisted = 1
meat = null
damage_overlay_type = "synth"
limbs_id = "synth"
var/list/initial_species_traits = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER,NO_DNA_COPY) //for getting these values back for assume_disguise()
var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off
var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged
/datum/species/synth/military
name = "Military Synth"
id = "military_synth"
armor = 25
punchdamagelow = 10
punchdamagehigh = 19
punchstunthreshold = 14 //about 50% chance to stun
disguise_fail_health = 50
/datum/species/synth/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
..()
assume_disguise(old_species, H)
/datum/species/synth/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "synthflesh")
chem.reaction_mob(H, TOUCH, 2 ,0) //heal a little
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
return 1
else
return ..()
/datum/species/synth/proc/assume_disguise(datum/species/S, mob/living/carbon/human/H)
if(S && !istype(S, type))
name = S.name
say_mod = S.say_mod
sexes = S.sexes
species_traits = initial_species_traits.Copy()
species_traits.Add(S.species_traits)
attack_verb = S.attack_verb
attack_sound = S.attack_sound
miss_sound = S.miss_sound
meat = S.meat
mutant_bodyparts = S.mutant_bodyparts.Copy()
mutant_organs = S.mutant_organs.Copy()
default_features = S.default_features.Copy()
nojumpsuit = S.nojumpsuit
no_equip = S.no_equip.Copy()
limbs_id = S.limbs_id
use_skintones = S.use_skintones
fixed_mut_color = S.fixed_mut_color
hair_color = S.hair_color
fake_species = new S.type
else
name = initial(name)
say_mod = initial(say_mod)
species_traits = initial_species_traits.Copy()
attack_verb = initial(attack_verb)
attack_sound = initial(attack_sound)
miss_sound = initial(miss_sound)
mutant_bodyparts = list()
default_features = list()
nojumpsuit = initial(nojumpsuit)
no_equip = list()
qdel(fake_species)
fake_species = null
meat = initial(meat)
limbs_id = "synth"
use_skintones = 0
sexes = 0
fixed_mut_color = ""
hair_color = ""
for(var/X in H.bodyparts) //propagates the damage_overlay changes
var/obj/item/bodypart/BP = X
BP.update_limb()
H.update_body_parts() //to update limb icon cache with the new damage overlays
//Proc redirects:
//Passing procs onto the fake_species, to ensure we look as much like them as possible
/datum/species/synth/handle_hair(mob/living/carbon/human/H, forced_colour)
if(fake_species)
fake_species.handle_hair(H, forced_colour)
else
return ..()
/datum/species/synth/handle_body(mob/living/carbon/human/H)
if(fake_species)
fake_species.handle_body(H)
else
return ..()
/datum/species/synth/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
if(fake_species)
fake_species.handle_body(H,forced_colour)
else
return ..()
/datum/species/synth/get_spans()
if(fake_species)
return fake_species.get_spans()
return list()
/datum/species/synth/handle_speech(message, mob/living/carbon/human/H)
if(H.health > disguise_fail_health)
if(fake_species)
return fake_species.handle_speech(message,H)
else
return ..()
else
return ..()
@@ -1,3 +1,5 @@
#define REGENERATION_DELAY 60 // After taking damage, how long it takes for automatic regeneration to begin
/datum/species/zombie
// 1spooky
name = "High Functioning Zombie"
@@ -6,7 +8,7 @@
sexes = 0
blacklisted = 1
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,NOZOMBIE,EASYDISMEMBER,EASYLIMBATTACHMENT)
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,NOZOMBIE,EASYDISMEMBER,EASYLIMBATTACHMENT,NOTRANSSTING)
mutant_organs = list(/obj/item/organ/tongue/zombie)
var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
disliked_food = NONE
@@ -20,14 +22,21 @@
armor = 20 // 120 damage to KO a zombie, which kills it
speedmod = 2
mutanteyes = /obj/item/organ/eyes/night_vision/zombie
var/regen_cooldown = 0
/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount)
. = min(2, amount)
/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H)
. = ..()
if(.)
regen_cooldown = world.time + REGENERATION_DELAY
/datum/species/zombie/infectious/spec_life(mob/living/carbon/C)
. = ..()
C.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW
C.heal_overall_damage(4,4)
if(regen_cooldown < world.time)
C.heal_overall_damage(4,4)
if(prob(4))
playsound(C, pick(spooks), 50, TRUE, 10)
if(C.InCritical())
@@ -56,3 +65,5 @@
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
mutant_organs = list(/obj/item/organ/tongue/zombie)
#undef REGENERATION_DELAY
@@ -30,7 +30,7 @@
emote("collapse")
Knockdown(200)
to_chat(src, "<span class='danger'>You feel weak.</span>")
if(radiation > 30 && prob((radiation - 30) * (radiation - 30) * 0.00002))
if(radiation > 30 && prob((radiation - 30) * (radiation - 30) * 0.0002))
gorillize()
return
switch(radiation)
+28 -24
View File
@@ -5,7 +5,7 @@
var/ancestor_chain = 1
var/relic_hat //Note: these two are paths
var/relic_mask
var/memory_saved = 0
var/memory_saved = FALSE
var/list/pet_monkey_names = list("Pun Pun", "Bubbles", "Mojo", "George", "Darwin", "Aldo", "Caeser", "Kanzi", "Kong", "Terk", "Grodd", "Mala", "Bojangles", "Coco", "Able", "Baker", "Scatter", "Norbit", "Travis")
var/list/rare_pet_monkey_names = list("Professor Bobo", "Deempisi's Revenge", "Furious George", "King Louie", "Dr. Zaius", "Jimmy Rustles", "Dinner", "Lanky")
@@ -32,25 +32,33 @@
equip_to_slot_or_del(new relic_mask, slot_wear_mask)
/mob/living/carbon/monkey/punpun/Life()
if(SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory(0)
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory(FALSE, FALSE)
memory_saved = TRUE
..()
/mob/living/carbon/monkey/punpun/death(gibbed)
if(!memory_saved || gibbed)
Write_Memory(1,gibbed)
if(!memory_saved)
Write_Memory(TRUE, gibbed)
..()
/mob/living/carbon/monkey/punpun/proc/Read_Memory()
var/json_file = file("data/npc_saves/Punpun.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
ancestor_name = json["ancestor_name"]
ancestor_chain = json["ancestor_chain"]
relic_hat = json["relic_hat"]
relic_mask = json["relic_hat"]
if(fexists("data/npc_saves/Punpun.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Punpun.sav")
S["ancestor_name"] >> ancestor_name
S["ancestor_chain"] >> ancestor_chain
S["relic_hat"] >> relic_hat
S["relic_mask"] >> relic_mask
fdel("data/npc_saves/Punpun.sav")
else
var/json_file = file("data/npc_saves/Punpun.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
ancestor_name = json["ancestor_name"]
ancestor_chain = json["ancestor_chain"]
relic_hat = json["relic_hat"]
relic_mask = json["relic_hat"]
/mob/living/carbon/monkey/punpun/proc/Write_Memory(dead, gibbed)
var/json_file = file("data/npc_saves/Punpun.json")
@@ -60,14 +68,10 @@
file_data["ancestor_chain"] = null
file_data["relic_hat"] = null
file_data["relic_mask"] = null
if(dead)
file_data["ancestor_name"] = ancestor_name
file_data["ancestor_chain"] = ancestor_chain + 1
file_data["relic_hat"] = head ? head.type : null
file_data["relic_mask"] = wear_mask ? wear_mask.type : null
if(!ancestor_name)
file_data["ancestor_name"] = name
else
file_data["ancestor_name"] = ancestor_name ? ancestor_name : name
file_data["ancestor_chain"] = dead ? ancestor_chain + 1 : ancestor_chain
file_data["relic_hat"] = head ? head.type : null
file_data["relic_mask"] = wear_mask ? wear_mask.type : null
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
if(!dead)
memory_saved = 1
WRITE_FILE(json_file, json_encode(file_data))
+19 -22
View File
@@ -544,11 +544,14 @@
if(!force_moving)
..(pressure_difference, direction, pressure_resistance_prob_delta)
/mob/living/proc/can_resist()
return !((next_move > world.time) || incapacitated(ignore_restraints = TRUE))
/mob/living/verb/resist()
set name = "Resist"
set category = "IC"
if(!isliving(src) || next_move > world.time || incapacitated(ignore_restraints = 1))
if(!can_resist())
return
changeNext_move(CLICK_CD_RESIST)
@@ -709,30 +712,24 @@
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure to restart it in next life().
/mob/living/proc/get_temperature(datum/gas_mixture/environment)
var/loc_temp = T0C
if(istype(loc, /obj/mecha))
var/obj/mecha/M = loc
loc_temp = M.return_temperature()
else if(istype(loc, /obj/structure/transit_tube_pod))
loc_temp = environment.temperature
var/loc_temp = environment ? environment.temperature : T0C
if(isobj(loc))
var/obj/oloc = loc
var/obj_temp = oloc.return_temperature()
if(obj_temp != null)
loc_temp = obj_temp
/* if(ismob(loc))
var/mob/living/mloc = loc
var/mob_temp = mloc.return_temperature()
if(mloc == DEAD)
loc_temp = get_turf(loc) //wew
else
loc_temp = mob_temp
*/
//just gunna ommit this for now, it's on the 'to figgur out' list.
else if(isspaceturf(get_turf(src)))
var/turf/heat_turf = get_turf(src)
loc_temp = heat_turf.temperature
else if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
var/obj/machinery/atmospherics/components/unary/cryo_cell/C = loc
var/datum/gas_mixture/G = C.AIR1
if(G.total_moles() < 10)
loc_temp = environment.temperature
else
loc_temp = G.temperature
else
loc_temp = environment.temperature
return loc_temp
/mob/living/proc/get_standard_pixel_x_offset(lying = 0)
+49 -57
View File
@@ -169,7 +169,7 @@
/mob/living/silicon/ai/verb/pick_icon()
set category = "AI Commands"
set name = "Set AI Core Display"
if(stat || aiRestorePowerRoutine)
if(incapacitated())
return
//if(icon_state == initial(icon_state))
@@ -308,16 +308,15 @@
onclose(src, "airoster")
/mob/living/silicon/ai/proc/ai_call_shuttle()
if(stat == DEAD)
return //won't work if dead
if(isAI(usr))
var/mob/living/silicon/ai/AI = src
if(AI.control_disabled)
to_chat(usr, "Wireless control is disabled!")
return
if(control_disabled)
to_chat(usr, "<span class='warning'>Wireless control is disabled!</span>")
return
var/reason = input(src, "What is the nature of your emergency? ([CALL_SHUTTLE_REASON_LENGTH] characters required.)", "Confirm Shuttle Call") as null|text
if(incapacitated())
return
if(trim(reason))
SSshuttle.requestEvac(src, reason)
@@ -335,8 +334,8 @@
set name = "Toggle Floor Bolts"
if(!isturf(loc)) // if their location isn't a turf
return // stop
if(stat == DEAD)
return //won't work if dead
if(incapacitated())
return
anchored = !anchored // Toggles the anchor
to_chat(src, "<b>You are now [anchored ? "" : "un"]anchored.</b>")
@@ -347,21 +346,16 @@
/mob/living/silicon/ai/proc/ai_cancel_call()
set category = "Malfunction"
if(stat == DEAD)
return //won't work if dead
if(isAI(usr))
var/mob/living/silicon/ai/AI = src
if(AI.control_disabled)
to_chat(src, "Wireless control is disabled!")
return
if(control_disabled)
to_chat(src, "<span class='warning'>Wireless control is disabled!</span>")
return
SSshuttle.cancelEvac(src)
return
/mob/living/silicon/ai/restrained(ignore_grab)
. = 0
/mob/living/silicon/ai/Topic(href, href_list)
if(usr != src)
if(usr != src || incapacitated())
return
..()
if (href_list["mach_close"])
@@ -385,11 +379,10 @@
//Carn: holopad requests
if(href_list["jumptoholopad"])
var/obj/machinery/holopad/H = locate(href_list["jumptoholopad"])
if(stat == CONSCIOUS)
if(H)
H.attack_ai(src) //may as well recycle
else
to_chat(src, "<span class='notice'>Unable to locate the holopad.</span>")
if(H)
H.attack_ai(src) //may as well recycle
else
to_chat(src, "<span class='notice'>Unable to locate the holopad.</span>")
if(href_list["track"])
var/string = href_list["track"]
trackable_mobs()
@@ -434,9 +427,6 @@
if(!GLOB.cameranet.checkCameraVis(M))
to_chat(src, "<span class='warning'>Exosuit is no longer near active cameras.</span>")
return
if(lacks_power())
to_chat(src, "<span class='warning'>You're depowered!</span>")
return
if(!isturf(loc))
to_chat(src, "<span class='warning'>You aren't in your core!</span>")
return
@@ -449,8 +439,8 @@
if(!tracking)
cameraFollow = null
if (!C || stat == DEAD) //C.can_use())
return 0
if (!C)
return FALSE
if(!src.eyeobj)
view_core()
@@ -459,17 +449,17 @@
eyeobj.setLoc(get_turf(C))
//machine = src
return 1
return TRUE
/mob/living/silicon/ai/proc/botcall()
set category = "AI Commands"
set name = "Access Robot Control"
set desc = "Wirelessly control various automatic robots."
if(stat == DEAD)
return //won't work if dead
if(incapacitated())
return
if(control_disabled)
to_chat(src, "Wireless communication is disabled.")
to_chat(src, "<span class='warning'>Wireless control is disabled.</span>")
return
var/turf/ai_current_turf = get_turf(src)
var/ai_Zlevel = ai_current_turf.z
@@ -522,8 +512,6 @@
/mob/living/silicon/ai/triggerAlarm(class, area/A, O, obj/alarmsource)
if(alarmsource.z != z)
return
if (stat == 2)
return 1
var/list/L = alarms[class]
for (var/I in L)
if (I == A.name)
@@ -585,8 +573,8 @@
cameraFollow = null
var/cameralist[0]
if(stat == DEAD)
return //won't work if dead
if(incapacitated())
return
var/mob/living/silicon/ai/U = usr
@@ -629,8 +617,8 @@
set category = "AI Commands"
set name = "AI Status"
if(stat == DEAD)
return //won't work if dead
if(incapacitated())
return
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer", "Dorfy", "Blue Glow", "Red Glow")
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
for (var/M in GLOB.ai_status_displays) //change status of displays
@@ -652,8 +640,8 @@
set desc = "Change the default hologram available to AI to something else."
set category = "AI Commands"
if(stat == DEAD)
return //won't work if dead
if(incapacitated())
return
var/input
switch(alert("Would you like to select a hologram based on a crew member, an animal, or switch to a unique avatar?",,"Crew Member","Unique","Animal"))
if("Crew Member")
@@ -729,9 +717,6 @@
apc.malfvacate()
/mob/living/silicon/ai/proc/toggle_camera_light()
if(stat != CONSCIOUS)
return
camera_light_on = !camera_light_on
if (!camera_light_on)
@@ -755,7 +740,7 @@
var/list/obj/machinery/camera/visible = list()
for (var/datum/camerachunk/CC in eyeobj.visibleCameraChunks)
for (var/obj/machinery/camera/C in CC.cameras)
if (!C.can_use() || get_dist(C, eyeobj) > 7)
if (!C.can_use() || get_dist(C, eyeobj) > 7 || !C.internal_light)
continue
visible |= C
@@ -774,8 +759,8 @@
set desc = "Allows you to change settings of your radio."
set category = "AI Commands"
if(stat == DEAD)
return //won't work if dead
if(incapacitated())
return
to_chat(src, "Accessing Subspace Transceiver control...")
if (radio)
@@ -790,8 +775,8 @@
set desc = "Modify the default radio setting for your automatic announcements."
set category = "AI Commands"
if(stat == DEAD)
return //won't work if dead
if(incapacitated())
return
set_autosay()
/mob/living/silicon/ai/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card)
@@ -818,17 +803,22 @@
/mob/living/silicon/ai/can_buckle()
return 0
/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close = 0)
if(stat)
return
/mob/living/silicon/ai/incapacitated()
if(aiRestorePowerRoutine)
return TRUE
return ..()
/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close = FALSE)
if(control_disabled || incapacitated())
return FALSE
if(be_close && !in_range(M, src))
return
return FALSE
//stop AIs from leaving windows open and using then after they lose vision
//apc_override is needed here because AIs use their own APC when powerless
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
if(M && GLOB.cameranet && !GLOB.cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
return
return 1
return FALSE
return TRUE
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
@@ -931,8 +921,10 @@
set category = "AI Commands"
set name = "Deploy to Shell"
if(stat || lacks_power() || control_disabled)
to_chat(src, "<span class='danger'>Wireless networking module is offline.</span>")
if(incapacitated())
return
if(control_disabled)
to_chat(src, "<span class='warning'>Wireless networking module is offline.</span>")
return
var/list/possible = list()
@@ -1,13 +0,0 @@
diff a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm (rejected hunks)
@@ -35,9 +35,9 @@
if(nuking)
set_security_level("red")
nuking = FALSE
- for(var/obj/item/weapon/pinpointer/P in GLOB.pinpointer_list)
+ for(var/obj/item/weapon/pinpointer/nuke/P in GLOB.pinpointer_list)
P.switch_mode_to(TRACK_NUKE_DISK) //Party's over, back to work, everyone
- P.nuke_warning = FALSE
+ P.alert = FALSE
if(doomsday_device)
doomsday_device.timing = FALSE
@@ -114,9 +114,6 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
var/y1 = max(0, T.y - (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
var/x2 = min(world.maxx, T.x + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
var/y2 = min(world.maxy, T.y + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
//to_chat(world, "X1: [x1] - Y1: [y1] - X2: [x2] - Y2: [y2]")
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
if(chunkGenerated(x, y, T.z))
@@ -161,4 +158,4 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
if(cameranet.chunkGenerated(x, y, z))
var/datum/camerachunk/chunk = cameranet.getCameraChunk(x, y, z)
usr.client.debug_variables(chunk)
*/
*/
@@ -106,8 +106,8 @@
set category = "AI Commands"
set name = "Toggle Camera Acceleration"
if(usr.stat == DEAD)
return //won't work if dead
if(incapacitated())
return
acceleration = !acceleration
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
+9 -7
View File
@@ -18,9 +18,11 @@
return !config.silent_ai
/mob/living/silicon/ai/radio(message, message_mode, list/spans, language)
if(!radio_enabled || aiRestorePowerRoutine || stat) //AI cannot speak if radio is disabled (via intellicard) or depowered.
if(incapacitated())
return FALSE
if(!radio_enabled) //AI cannot speak if radio is disabled (via intellicard) or depowered.
to_chat(src, "<span class='danger'>Your radio transmitter is offline!</span>")
return 0
return FALSE
..()
/mob/living/silicon/ai/get_message_mode(message)
@@ -71,8 +73,8 @@
set desc = "Display a list of vocal words to announce to the crew."
set category = "AI Commands"
if(usr.stat == DEAD)
return //won't work if dead
if(incapacitated())
return
var/dat = "Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you.<BR> \
<UL><LI>You can also click on the word to preview it.</LI>\
@@ -95,7 +97,7 @@
/mob/living/silicon/ai/proc/announcement()
var/static/announcing_vox = 0 // Stores the time of the last announcement
if(announcing_vox > world.time)
to_chat(src, "<span class='notice'>Please wait [round((announcing_vox - world.time) / 10)] seconds.</span>")
to_chat(src, "<span class='notice'>Please wait [DisplayTimeText(announcing_vox - world.time)].</span>")
return
var/message = input(src, "WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", src.last_announcement) as text
@@ -105,11 +107,11 @@
if(!message || announcing_vox > world.time)
return
if(stat != CONSCIOUS)
if(incapacitated())
return
if(control_disabled)
to_chat(src, "<span class='notice'>Wireless interface disabled, unable to interact with announcement PA.</span>")
to_chat(src, "<span class='warning'>Wireless interface disabled, unable to interact with announcement PA.</span>")
return
var/list/words = splittext(trim(message), " ")
+1 -1
View File
@@ -1,5 +1,5 @@
/mob/living/silicon/Login()
if(mind && SSticker.mode)
SSticker.mode.remove_cultist(mind, 0, 0)
SSticker.mode.remove_revolutionary(mind, 0)
SSticker.mode.remove_revolutionary(mind, TRUE)
..()
@@ -127,11 +127,11 @@
if("buy")
if(subscreen == 1)
var/target = href_list["buy"]
if(available_software.Find(target))
if(available_software.Find(target) && !software.Find(target))
var/cost = src.available_software[target]
if(ram >= cost)
ram -= cost
software.Add(target)
ram -= cost
else
temp = "Insufficient RAM available."
else
@@ -248,6 +248,7 @@
medHUD = !medHUD
if(medHUD)
add_med_hud()
else
var/datum/atom_hud/med = GLOB.huds[med_hud]
med.remove_hud_from(src)
@@ -1,7 +1,4 @@
/mob/living/silicon/robot/Login()
..()
regenerate_icons()
show_laws(0)
if(mind)
SSticker.mode.remove_revolutionary(mind)
/mob/living/silicon/robot/Login()
..()
regenerate_icons()
show_laws(0)
@@ -129,6 +129,7 @@
builtInCamera = new (src)
builtInCamera.c_tag = real_name
builtInCamera.network = list("SS13")
builtInCamera.internal_light = FALSE
if(wires.is_cut(WIRE_CAMERA))
builtInCamera.status = 0
module = new /obj/item/robot_module(src)
@@ -307,6 +307,7 @@
/obj/item/device/analyzer,
/obj/item/device/assembly/signaler/cyborg,
/obj/item/areaeditor/blueprints/cyborg,
/obj/item/device/electroadaptive_pseudocircuit,
/obj/item/stack/sheet/metal/cyborg,
/obj/item/stack/sheet/glass/cyborg,
/obj/item/stack/sheet/rglass/cyborg,
@@ -679,4 +680,4 @@
/datum/robot_energy_storage/beacon
max_energy = 30
recharge_rate = 1
name = "Marker Beacon Storage"
name = "Marker Beacon Storage"
@@ -1,19 +0,0 @@
diff a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm (rejected hunks)
@@ -519,7 +519,7 @@
/obj/item/weapon/gun/ballistic/revolver/grenadelauncher/cyborg,
/obj/item/weapon/card/emag,
/obj/item/weapon/crowbar/cyborg,
- /obj/item/weapon/pinpointer/syndicate/cyborg)
+ /obj/item/weapon/pinpointer/syndicate_cyborg)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/security,
@@ -545,7 +545,7 @@
/obj/item/roller/robo,
/obj/item/weapon/card/emag,
/obj/item/weapon/crowbar/cyborg,
- /obj/item/weapon/pinpointer/syndicate/cyborg,
+ /obj/item/weapon/pinpointer/syndicate_cyborg,
/obj/item/stack/medical/gauze/cyborg,
/obj/item/weapon/gun/medbeam)
ratvar_modules = list(
@@ -856,6 +856,7 @@ Pass a positive integer as an argument to override a bot's default speed.
bot_name = name
name = paicard.pai.name
faction = user.faction.Copy()
language_holder = paicard.pai.language_holder.copy(src)
add_logs(user, paicard.pai, "uploaded to [bot_name],")
return 1
else
@@ -432,7 +432,6 @@
return
if(on)
var/speed = (wires.is_cut(WIRE_MOTOR1) ? 0 : 1) + (wires.is_cut(WIRE_MOTOR2) ? 0 : 2)
//to_chat(world, "speed: [speed]")
var/num_steps = 0
switch(speed)
if(0)
@@ -474,8 +473,6 @@
path -= next
return
if(isturf(next))
//to_chat(world, "at ([x],[y]) moving to ([next.x],[next.y])")
if(bloodiness)
var/obj/effect/decal/cleanable/blood/tracks/B = new(loc)
if(blood_DNA && blood_DNA.len)
@@ -497,7 +494,6 @@
var/moved = step_towards(src, next) // attempt to move
if(cell) cell.use(1)
if(moved && oldloc!=loc) // successful move
//to_chat(world, "Successful move.")
blockcount = 0
path -= loc
@@ -508,7 +504,6 @@
else // failed to move
//to_chat(world, "Unable to move.")
blockcount++
mode = BOT_BLOCKED
if(blockcount == 3)
@@ -528,16 +523,13 @@
return
else
buzz(ANNOYED)
//to_chat(world, "Bad turf.")
mode = BOT_NAV
return
else
//to_chat(world, "No path.")
mode = BOT_NAV
return
if(BOT_NAV) // calculate new path
//to_chat(world, "Calc new path.")
mode = BOT_WAIT_FOR_NAV
spawn(0)
calc_path()
@@ -65,10 +65,9 @@
/mob/living/simple_animal/bot/secbot/Initialize()
. = ..()
icon_state = "secbot[on]"
spawn(3)
var/datum/job/detective/J = new/datum/job/detective
access_card.access += J.get_access()
prev_access = access_card.access
var/datum/job/detective/J = new/datum/job/detective
access_card.access += J.get_access()
prev_access = access_card.access
//SECHUD
var/datum/atom_hud/secsensor = GLOB.huds[DATA_HUD_SECURITY_ADVANCED]
@@ -225,21 +224,25 @@ Auto Patrol: []"},
playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
C.visible_message("<span class='danger'>[src] is trying to put zipties on [C]!</span>",\
"<span class='userdanger'>[src] is trying to put zipties on you!</span>")
spawn(60)
if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
return
if(!C.handcuffed)
C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C)
C.update_handcuffed()
playsound(loc, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0)
back_to_idle()
addtimer(CALLBACK(src, .proc/attempt_handcuff, C), 60)
/mob/living/simple_animal/bot/secbot/proc/attempt_handcuff(mob/living/carbon/C)
if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
return
if(!C.handcuffed)
C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C)
C.update_handcuffed()
playsound(src, "law", 50, 0)
back_to_idle()
/mob/living/simple_animal/bot/secbot/proc/update_onsprite()
icon_state = "secbot[on]"
/mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/C)
var/judgement_criteria = judgement_criteria()
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
icon_state = "secbot-c"
spawn(2)
icon_state = "secbot[on]"
addtimer(CALLBACK(src, .proc/update_onsprite), 2)
var/threat = 5
if(ishuman(C))
C.stuttering = 5
@@ -352,15 +355,13 @@ Auto Patrol: []"},
target = null
last_found = world.time
frustration = 0
spawn(0)
handle_automated_action() //ensure bot quickly responds
INVOKE_ASYNC(src, .proc/handle_automated_action)
/mob/living/simple_animal/bot/secbot/proc/back_to_hunt()
anchored = FALSE
frustration = 0
mode = BOT_HUNT
spawn(0)
handle_automated_action() //ensure bot quickly responds
INVOKE_ASYNC(src, .proc/handle_automated_action)
// look for a criminal in view of the bot
/mob/living/simple_animal/bot/secbot/proc/look_for_perp()
@@ -385,8 +386,7 @@ Auto Patrol: []"},
playsound(loc, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0)
visible_message("<b>[src]</b> points at [C.name]!")
mode = BOT_HUNT
spawn(0)
handle_automated_action() // ensure bot quickly responds to a perp
INVOKE_ASYNC(src, .proc/handle_automated_action)
break
else
continue
@@ -30,6 +30,7 @@
var/mob/living/simple_animal/mouse/movement_target
gold_core_spawnable = 2
devourable = TRUE
no_vore = FALSE
/mob/living/simple_animal/pet/cat/Initialize()
. = ..()
@@ -84,7 +85,7 @@
var/list/family = list()//var restored from savefile, has count of each child type
var/list/children = list()//Actual mob instances of children
var/cats_deployed = 0
var/memory_saved = 0
var/memory_saved = FALSE
/mob/living/simple_animal/pet/cat/Runtime/Initialize()
if(prob(5))
@@ -99,6 +100,7 @@
Deploy_The_Cats()
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory()
memory_saved = TRUE
..()
/mob/living/simple_animal/pet/cat/Runtime/make_babies()
@@ -109,21 +111,26 @@
/mob/living/simple_animal/pet/cat/Runtime/death()
if(!memory_saved)
Write_Memory(1)
Write_Memory(TRUE)
..()
/mob/living/simple_animal/pet/cat/Runtime/proc/Read_Memory()
var/json_file = file("data/npc_saves/Runtime.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
family = json["family"]
if(fexists("data/npc_saves/Runtime.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Runtime.sav")
S["family"] >> family
fdel("data/npc_saves/Runtime.sav")
else
var/json_file = file("data/npc_saves/Runtime.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
family = json["family"]
if(isnull(family))
family = list()
/mob/living/simple_animal/pet/cat/Runtime/proc/Write_Memory(dead)
var/json_file = file("data/npc_saves/Runtime.json")
var/list/file_data = list()
family = list()
if(!dead)
for(var/mob/living/simple_animal/pet/cat/kitten/C in children)
@@ -133,9 +140,9 @@
family[C.type] += 1
else
family[C.type] = 1
file_data["family"] = family
fdel(json_file)
WRITE_FILE(json_file, json_encode(family))
memory_saved = 1
WRITE_FILE(json_file, json_encode(file_data))
/mob/living/simple_animal/pet/cat/Runtime/proc/Deploy_The_Cats()
cats_deployed = 1
@@ -13,6 +13,7 @@
speak_chance = 1
turns_per_move = 10
devourable = TRUE
no_vore = FALSE
//Corgis and pugs are now under one dog subtype
@@ -291,7 +292,7 @@
gold_core_spawnable = 0
var/age = 0
var/record_age = 1
var/memory_saved = 0
var/memory_saved = FALSE
var/saved_head //path
/mob/living/simple_animal/pet/dog/corgi/Ian/Initialize()
@@ -307,7 +308,7 @@
P.real_name = "Ian"
P.gender = MALE
P.desc = "It's the HoP's beloved corgi puppy."
Write_Memory(0)
Write_Memory(FALSE)
qdel(src)
else if(age == record_age)
icon_state = "old_corgi"
@@ -317,24 +318,31 @@
turns_per_move = 20
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
if(SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory(0)
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory(FALSE)
memory_saved = TRUE
..()
/mob/living/simple_animal/pet/dog/corgi/Ian/death()
if(!memory_saved)
Write_Memory(1)
Write_Memory(TRUE)
..()
/mob/living/simple_animal/pet/dog/corgi/Ian/proc/Read_Memory()
var/json_file = file("data/npc_saves/Ian.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
age = json["age"]
record_age = json["record_age"]
saved_head = json["saved_head"]
if(fexists("data/npc_saves/Ian.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Ian.sav")
S["age"] >> age
S["record_age"] >> record_age
S["saved_head"] >> saved_head
fdel("data/npc_saves/Ian.sav")
else
var/json_file = file("data/npc_saves/Ian.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
age = json["age"]
record_age = json["record_age"]
saved_head = json["saved_head"]
if(isnull(age))
age = 0
if(isnull(record_age))
@@ -349,14 +357,18 @@
file_data["age"] = age + 1
if((age + 1) > record_age)
file_data["record_age"] = record_age + 1
else
file_data["record_age"] = record_age
if(inventory_head)
file_data["saved_head"] = inventory_head.type
else
file_data["saved_head"] = null
else
file_data["age"] = 0
file_data["record_age"] = record_age
file_data["saved_head"] = null
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
memory_saved = 1
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
..()
@@ -29,6 +29,7 @@
blood_volume = BLOOD_VOLUME_NORMAL
var/obj/item/udder/udder = null
devourable = TRUE
no_vore = FALSE
/mob/living/simple_animal/hostile/retaliate/goat/Initialize()
udder = new()
@@ -119,6 +120,7 @@
gold_core_spawnable = 2
blood_volume = BLOOD_VOLUME_NORMAL
devourable = TRUE
no_vore = FALSE
/mob/living/simple_animal/cow/Initialize()
udder = new()
@@ -251,6 +253,7 @@
gold_core_spawnable = 2
var/static/chicken_count = 0
devourable = TRUE
no_vore = FALSE
/mob/living/simple_animal/chicken/Initialize()
. = ..()
@@ -275,7 +278,6 @@
user.drop_item()
qdel(O)
eggsleft += rand(1, 4)
//to_chat(world, eggsleft)
else
to_chat(user, "<span class='warning'>[name] doesn't seem hungry!</span>")
else
@@ -21,6 +21,7 @@
devourable = TRUE
var/mob/living/simple_animal/mouse/movement_target
var/turns_since_scan = 0
no_vore = FALSE
/mob/living/simple_animal/pet/fox/Life()
//MICE!
@@ -28,6 +28,7 @@
/mob/living/simple_animal/mouse/Initialize()
. = ..()
AddComponent(/datum/component/squeak, list('sound/effects/mousesqueek.ogg'=1), 100)
if(!body_color)
body_color = pick( list("brown","gray","white") )
icon_state = "mouse_[body_color]"
@@ -58,7 +59,6 @@
if(!stat)
var/mob/M = AM
to_chat(M, "<span class='notice'>[icon2html(src, M)] Squeek!</span>")
playsound(src, 'sound/effects/mousesqueek.ogg', 100, 1)
..()
/mob/living/simple_animal/mouse/handle_automated_action()
@@ -13,6 +13,7 @@
speak_chance = 1
turns_per_move = 10
icon = 'icons/mob/penguins.dmi'
no_vore = FALSE
/mob/living/simple_animal/pet/penguin/emperor
name = "Emperor penguin"
@@ -159,7 +159,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
resulthealth = round((summoner.health / summoner.maxHealth) * 100, 0.5)
stat(null, "Summoner Health: [resulthealth]%")
if(cooldown >= world.time)
stat(null, "Manifest/Recall Cooldown Remaining: [max(round((cooldown - world.time)*0.1, 0.1), 0)] seconds")
stat(null, "Manifest/Recall Cooldown Remaining: [DisplayTimeText(cooldown - world.time)]")
/mob/living/simple_animal/hostile/guardian/Move() //Returns to summoner if they move out of range
. = ..()
@@ -30,7 +30,7 @@
..()
if(statpanel("Status"))
if(stealthcooldown >= world.time)
stat(null, "Stealth Cooldown Remaining: [max(round((stealthcooldown - world.time)*0.1, 0.1), 0)] seconds")
stat(null, "Stealth Cooldown Remaining: [DisplayTimeText(stealthcooldown - world.time)]")
/mob/living/simple_animal/hostile/guardian/assassin/AttackingTarget()
. = ..()
@@ -79,7 +79,7 @@
updatestealthalert()
toggle = TRUE
else if(!forced)
to_chat(src, "<span class='danger'><B>You cannot yet enter stealth, wait another [max(round((stealthcooldown - world.time)*0.1, 0.1), 0)] seconds!</span></B>")
to_chat(src, "<span class='danger'><B>You cannot yet enter stealth, wait another [DisplayTimeText(stealthcooldown - world.time)]!</span></B>")
/mob/living/simple_animal/hostile/guardian/assassin/proc/updatestealthalert()
if(stealthcooldown <= world.time)
@@ -14,7 +14,7 @@
..()
if(statpanel("Status"))
if(bomb_cooldown >= world.time)
stat(null, "Bomb Cooldown Remaining: [max(round((bomb_cooldown - world.time)*0.1, 0.1), 0)] seconds")
stat(null, "Bomb Cooldown Remaining: [DisplayTimeText(bomb_cooldown - world.time)]")
/mob/living/simple_animal/hostile/guardian/bomb/AttackingTarget()
. = ..()
@@ -24,11 +24,11 @@
..()
if(statpanel("Status"))
if(beacon_cooldown >= world.time)
stat(null, "Beacon Cooldown Remaining: [max(round((beacon_cooldown - world.time)*0.1, 0.1), 0)] seconds")
stat(null, "Beacon Cooldown Remaining: [DisplayTimeText(beacon_cooldown - world.time)]")
/mob/living/simple_animal/hostile/guardian/healer/AttackingTarget()
. = ..()
if(toggle && iscarbon(target))
if(. && toggle && iscarbon(target))
var/mob/living/carbon/C = target
C.adjustBruteLoss(-5)
C.adjustFireLoss(-5)
@@ -35,6 +35,8 @@
gold_core_spawnable = 0
death_sound = 'sound/voice/hiss6.ogg'
deathmessage = "lets out a waning guttural screech, green blood bubbling from its maw..."
devourable = TRUE
no_vore = FALSE
/mob/living/simple_animal/hostile/alien/drone
name = "alien drone"
@@ -36,6 +36,8 @@
faction = list("russian")
gold_core_spawnable = 1
devourable = TRUE
no_vore = FALSE
//SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!!
/mob/living/simple_animal/hostile/bear/Hudson
@@ -128,11 +128,12 @@
if(istype(target, /obj/machinery/hydroponics))
var/obj/machinery/hydroponics/Hydro = target
pollinate(Hydro)
else if(target == beehome)
var/obj/structure/beebox/BB = target
loc = BB
target = null
wanted_objects -= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home
else if(istype(target, /obj/structure/beebox))
if(target == beehome)
var/obj/structure/beebox/BB = target
forceMove(BB)
target = null
wanted_objects -= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home
return //no don't attack the goddamm box
else
. = ..()
@@ -186,7 +187,7 @@
if(loc == beehome)
idle = min(100, ++idle)
if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
loc = get_turf(beehome)
forceMove(get_turf(beehome))
else
idle = max(0, --idle)
if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME))
@@ -17,6 +17,7 @@
maxHealth = 25
health = 25
devourable = TRUE
no_vore = FALSE
harm_intent_damage = 8
obj_damage = 50
@@ -15,8 +15,6 @@
if(L.reagents)
L.reagents.add_reagent(poison_type, poison_per_bite)
//basic spider mob, these generally guard nests
/mob/living/simple_animal/hostile/poison/giant_spider
name = "giant spider"
@@ -104,6 +102,64 @@
poison_per_bite = 5
move_to_delay = 5
//vipers are the rare variant of the hunter, no IMMEDIATE damage but so much poison medical care will be needed fast.
/mob/living/simple_animal/hostile/poison/giant_spider/hunter/viper
name = "viper"
desc = "Furry and black, it makes you shudder to look at it. This one has effervescent purple eyes."
icon_state = "viper"
icon_living = "viper"
icon_dead = "viper_dead"
maxHealth = 40
health = 40
melee_damage_lower = 1
melee_damage_upper = 1
poison_per_bite = 12
move_to_delay = 4
poison_type = "venom" //all in venom, glass cannon. you bite 5 times and they are DEFINITELY dead, but 40 health and you are extremely obvious. Ambush, maybe?
speed = 1
//tarantulas are really tanky, regenerating (maybe), hulky monster but are also extremely slow, so.
/mob/living/simple_animal/hostile/poison/giant_spider/tarantula
name = "tarantula"
desc = "Furry and black, it makes you shudder to look at it. This one has abyssal red eyes."
icon_state = "tarantula"
icon_living = "tarantula"
icon_dead = "tarantula_dead"
maxHealth = 300 // woah nelly
health = 300
melee_damage_lower = 35
melee_damage_upper = 40
poison_per_bite = 0
move_to_delay = 8
speed = 7
status_flags = NONE
mob_size = MOB_SIZE_LARGE
/mob/living/simple_animal/hostile/poison/giant_spider/tarantula/movement_delay()
var/turf/T = get_turf(src)
if(locate(/obj/structure/spider/stickyweb) in T)
speed = 2
else
speed = 7
. = ..()
//midwives are the queen of the spiders, can send messages to all them and web faster. That rare round where you get a queen spider and turn your 'for honor' players into 'r6siege' players will be a fun one.
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife
name = "midwife"
desc = "Furry and black, it makes you shudder to look at it. This one has scintillating green eyes."
icon_state = "midwife"
icon_living = "midwife"
icon_dead = "midwife_dead"
maxHealth = 40
health = 40
var/datum/action/innate/spider/comm/letmetalkpls
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife/Initialize()
. = ..()
letmetalkpls = new
letmetalkpls.Grant(src)
/mob/living/simple_animal/hostile/poison/giant_spider/ice //spiders dont usually like tempatures of 140 kelvin who knew
name = "giant ice spider"
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
@@ -296,6 +352,39 @@
busy = SPIDER_IDLE
stop_automated_movement = FALSE
/mob/living/simple_animal/hostile/poison/giant_spider/Login()
. = ..()
GLOB.spidermobs[src] = TRUE
/mob/living/simple_animal/hostile/poison/giant_spider/Destroy()
GLOB.spidermobs -= src
return ..()
/datum/action/innate/spider/comm
name = "Command"
button_icon_state = "cult_comms"
/datum/action/innate/spider/comm/IsAvailable()
if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife))
return FALSE
return TRUE
/datum/action/innate/spider/comm/Trigger()
var/input = stripped_input(usr, "Input a message for your legions to follow.", "Command", "")
if(QDELETED(src) || !input || !IsAvailable())
return FALSE
spider_command(usr, input)
return TRUE
/datum/action/innate/spider/comm/proc/spider_command(mob/living/user, message)
if(!message)
return
var/my_message
my_message = "<FONT size = 3><b>COMMAND FROM SPIDER QUEEN:</b> [message]</FONT>"
for(var/mob/living/simple_animal/hostile/poison/giant_spider/M in GLOB.spidermobs)
to_chat(M, my_message)
log_talk(user, "SPIDERCOMMAND: [key_name(user)] : [message]",LOGSAY)
/mob/living/simple_animal/hostile/poison/giant_spider/handle_temperature_damage()
if(bodytemperature < minbodytemp)
adjustBruteLoss(20)
@@ -22,7 +22,7 @@
melee_damage_upper = 18
damage_coeff = list(BRUTE = 1, BURN = 1.5, TOX = 1.5, CLONE = 0, STAMINA = 0, OXY = 1.5)
obj_damage = 20
environment_smash = 2
environment_smash = ENVIRONMENT_SMASH_WALLS
attacktext = "pummels"
attack_sound = 'sound/weapons/punch1.ogg'
dextrous = TRUE
@@ -32,7 +32,11 @@
stat_attack = UNCONSCIOUS
minbodytemp = 270
maxbodytemp = 350
unique_name = TRUE
var/list/gorilla_overlays[GORILLA_TOTAL_LAYERS]
var/oogas = 0
devourable = TRUE
no_vore = FALSE
// Gorillas like to dismember limbs from unconcious mobs.
// Returns null when the target is not an unconcious carbon mob; a list of limbs (possibly empty) otherwise.
@@ -49,6 +53,8 @@
return parts
/mob/living/simple_animal/hostile/gorilla/AttackingTarget()
if(client)
oogaooga()
var/list/parts = target_bodyparts(target)
if(parts)
if(!parts.len)
@@ -61,7 +67,7 @@
var/mob/living/L = target
if(prob(80))
var/atom/throw_target = get_edge_target_turf(L, dir)
L.throw_at(throw_target, rand(1,2), 7, src)
L.throw_at(throw_target, rand(1,2), 7, src)
else
L.Knockdown(20)
visible_message("<span class='danger'>[src] knocks [L] down!</span>")
@@ -70,8 +76,30 @@
var/list/parts = target_bodyparts(target)
return ..() && !istype(the_target, /mob/living/carbon/monkey) && (!parts || parts.len > 3)
/mob/living/simple_animal/hostile/gorilla/CanSmashTurfs(turf/T)
return iswallturf(T)
/mob/living/simple_animal/hostile/gorilla/gib(no_brain)
if(!no_brain)
var/mob/living/brain/B = new(drop_location())
B.name = real_name
B.real_name = real_name
if(mind)
mind.transfer_to(B)
..()
/mob/living/simple_animal/hostile/gorilla/handle_automated_speech(override)
if(speak_chance && (override || prob(speak_chance)))
playsound(src, "sound/creatures/gorilla.ogg", 200)
..()
/mob/living/simple_animal/hostile/gorilla/can_use_guns(obj/item/G)
to_chat(src, "<span class='warning'>Your meaty finger is much too large for the trigger guard!</span>")
return FALSE
/mob/living/simple_animal/hostile/gorilla/proc/oogaooga()
oogas++
if(oogas >= rand(2,6))
playsound(src, "sound/creatures/gorilla.ogg", 200)
oogas = 0
@@ -228,6 +228,9 @@
if(!target || !CanAttack(target))
LoseTarget()
return 0
if(ismob(target.loc))
LoseTarget()
return 0
if(target in possible_targets)
if(target.z != z)
LoseTarget()
@@ -366,23 +369,26 @@
P.original = targeted_atom
P.fire()
return P
/mob/living/simple_animal/hostile/proc/CanSmashTurfs(turf/T)
return iswallturf(T) || ismineralturf(T)
/mob/living/simple_animal/hostile/proc/DestroySurroundings()
if(environment_smash)
EscapeConfinement()
for(var/dir in GLOB.cardinals)
var/turf/T = get_step(targets_from, dir)
if(iswallturf(T) || ismineralturf(T))
if(CanSmashTurfs(T))
if(T.Adjacent(targets_from))
T.attack_animal(src)
for(var/a in T)
var/atom/A = a
if(!A.Adjacent(targets_from))
continue
if(is_type_in_typecache(A, environment_target_typecache))
if(is_type_in_typecache(A, environment_target_typecache) && !A.IsObscured())
A.attack_animal(src)
/mob/living/simple_animal/hostile/proc/EscapeConfinement()
if(buckled)
buckled.attack_animal(src)
@@ -250,7 +250,7 @@ Difficulty: Very Hard
use_power = NO_POWER_USE
var/memory_saved = FALSE
var/list/stored_items = list()
var/static/list/blacklist = typecacheof(list(/obj/item/spellbook))
var/list/blacklist = list()
/obj/machinery/smartfridge/black_box/update_icon()
return
@@ -258,7 +258,8 @@ Difficulty: Very Hard
/obj/machinery/smartfridge/black_box/accept_check(obj/item/O)
if(!istype(O))
return FALSE
if(is_type_in_typecache(O, blacklist))
if(blacklist[O])
visible_message("<span class='boldwarning'>[src] ripples as it rejects [O]. The device will not accept items that have been removed from it.</span>")
return FALSE
return TRUE
@@ -275,6 +276,7 @@ Difficulty: Very Hard
..()
if(!memory_saved && SSticker.current_state == GAME_STATE_FINISHED)
WriteMemory()
memory_saved = TRUE
/obj/machinery/smartfridge/black_box/proc/WriteMemory()
var/json_file = file("data/npc_saves/Blackbox.json")
@@ -286,15 +288,18 @@ Difficulty: Very Hard
file_data["data"] = stored_items
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
memory_saved = TRUE
/obj/machinery/smartfridge/black_box/proc/ReadMemory()
var/json_file = file("data/npc_saves/Blackbox.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
stored_items = json["data"]
if(fexists("data/npc_saves/Blackbox.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Blackbox.sav")
S["stored_items"] >> stored_items
fdel("data/npc_saves/Blackbox.sav")
else
var/json_file = file("data/npc_saves/Blackbox.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
stored_items = json["data"]
if(isnull(stored_items))
stored_items = list()
@@ -304,7 +309,8 @@ Difficulty: Very Hard
//in it's own proc to avoid issues with items that nolonger exist in the code base.
//try catch doesn't always prevent byond runtimes from halting a proc,
/obj/machinery/smartfridge/black_box/proc/create_item(item_type)
new item_type(src)
var/obj/O = new item_type(src)
blacklist[O] = TRUE
/obj/machinery/smartfridge/black_box/Destroy(force = FALSE)
if(force)
@@ -60,6 +60,7 @@ Difficulty: Medium
score_type = DRAKE_SCORE
deathmessage = "collapses into a pile of bones, its flesh sloughing away."
death_sound = 'sound/magic/demon_dies.ogg'
no_vore = FALSE
/mob/living/simple_animal/hostile/megafauna/dragon/Initialize()
. = ..()
@@ -352,9 +353,9 @@ Difficulty: Medium
/obj/effect/temp_visual/dragon_flight/proc/flight(negative)
if(negative)
animate(src, pixel_x = -DRAKE_SWOOP_HEIGHT*0.10, pixel_z = DRAKE_SWOOP_HEIGHT*0.15, time = 3, easing = BOUNCE_EASING)
animate(src, pixel_x = -DRAKE_SWOOP_HEIGHT*0.1, pixel_z = DRAKE_SWOOP_HEIGHT*0.15, time = 3, easing = BOUNCE_EASING)
else
animate(src, pixel_x = DRAKE_SWOOP_HEIGHT*0.10, pixel_z = DRAKE_SWOOP_HEIGHT*0.15, time = 3, easing = BOUNCE_EASING)
animate(src, pixel_x = DRAKE_SWOOP_HEIGHT*0.1, pixel_z = DRAKE_SWOOP_HEIGHT*0.15, time = 3, easing = BOUNCE_EASING)
sleep(3)
icon_state = "swoop"
if(negative)
@@ -0,0 +1,50 @@
/mob/living/simple_animal/hostile/megafauna/dragon
vore_active = TRUE
/mob/living/simple_animal/hostile/megafauna/dragon/Initialize()
// Create and register 'stomachs'
var/datum/belly/megafauna/dragon/maw/maw = new(src)
var/datum/belly/megafauna/dragon/gullet/gullet = new(src)
var/datum/belly/megafauna/dragon/gut/gut = new(src)
for(var/datum/belly/X in list(maw, gullet, gut))
vore_organs[X.name] = X
// Connect 'stomachs' together
maw.transferlocation = gullet
gullet.transferlocation = gut
vore_selected = maw.name // NPC eats into maw
return ..()
/datum/belly/megafauna/dragon
human_prey_swallow_time = 50 // maybe enough to switch targets if distracted
nonhuman_prey_swallow_time = 50
/datum/belly/megafauna/dragon/maw
name = "maw"
inside_flavor = "The maw of the dreaded Ash drake closes around you, engulfing you into a swelteringly hot, disgusting enviroment. The acidic saliva tingles over your form while that tongue pushes you further back...towards the dark gullet beyond."
vore_verb = "scoop"
vore_sound = 'sound/vore/pred/taurswallow.ogg'
swallow_time = 20
escapechance = 25
// From above, will transfer into gullet
transferchance = 25
autotransferchance = 66
autotransferwait = 200
/datum/belly/megafauna/dragon/gullet
name = "gullet"
inside_flavor = "A ripple of muscle and arching of the tongue pushes you down like any other food. No choice in the matter, you're simply consumed. The dark ambiance of the outside world is replaced with working, wet flesh. Your only light being what you brought with you."
swallow_time = 60 // costs extra time to eat directly to here
escapechance = 5
// From above, will transfer into gut
transferchance = 25
autotransferchance = 50
autotransferwait = 200
/datum/belly/megafauna/dragon/gut
name = "stomach"
vore_capacity = 5 //I doubt this many people will actually last in the gut, but...
inside_flavor = "With a rush of burning ichor greeting you, you're introduced to the Drake's stomach. Wrinkled walls greedily grind against you, acidic slimes working into your body as you become fuel and nutriton for a superior predator. All that's left is your body's willingness to resist your destiny."
digest_mode = DM_DRAGON
digest_burn = 5
swallow_time = 100 // costs extra time to eat directly to here
escapechance = 0
@@ -60,7 +60,7 @@
else
var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
if(C && crusher_loot)
if(C.total_damage >= maxHealth * 0.60) //if you do at least 60% of its health with the crusher, you'll get the item
if(C.total_damage >= maxHealth * 0.6) //if you do at least 60% of its health with the crusher, you'll get the item
spawn_crusher_loot()
if(!admin_spawned)
SSblackbox.set_details("megafauna_kills","[initial(name)]")
@@ -89,11 +89,15 @@
. = ..()
if(. && isliving(target))
var/mob/living/L = target
if(L.stat != DEAD)
if(!client && ranged && ranged_cooldown <= world.time)
OpenFire()
if(L.stat >= SOFT_CRIT)
if(vore_active == TRUE && L.devourable == TRUE)
dragon_feeding(src,L)
else if(L.stat == DEAD)
devour(L)
else
devour(L)
if(L.stat != DEAD)
if(!client && ranged && ranged_cooldown <= world.time)
OpenFire()
/mob/living/simple_animal/hostile/megafauna/proc/devour(mob/living/L)
if(!L)
@@ -31,6 +31,7 @@
var/pre_attack = 0
var/pre_attack_icon = "Goliath_preattack"
loot = list(/obj/item/stack/sheet/animalhide/goliath_hide)
no_vore = FALSE
/mob/living/simple_animal/hostile/asteroid/goliath/Life()
. = ..()
@@ -60,7 +60,7 @@
cap_color = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
UpdateMushroomCap()
health = maxHealth
..()
. = ..()
/mob/living/simple_animal/hostile/mushroom/adjustHealth(amount, updating_health = TRUE, forced = FALSE) //Possibility to flee from a fight just to make it more visually interesting
if(!retreat_distance && prob(33))
@@ -38,7 +38,7 @@
minimum_distance = 5
icon_state = "stickmanranged"
icon_living = "stickmanranged"
casingtype = /obj/item/ammo_casing/c45nostamina
casingtype = /obj/item/ammo_casing/c45/nostamina
projectilesound = 'sound/misc/bang.ogg'
loot = list(/obj/item/gun/ballistic/automatic/pistol/stickman)
@@ -95,7 +95,7 @@
minimum_distance = 5
icon_state = "syndicateranged"
icon_living = "syndicateranged"
casingtype = /obj/item/ammo_casing/c45nostamina
casingtype = /obj/item/ammo_casing/c45/nostamina
projectilesound = 'sound/weapons/gunshot_smg.ogg'
loot = list(/obj/effect/gibspawner/human)
+46 -33
View File
@@ -60,6 +60,7 @@
movement_type = FLYING
gold_core_spawnable = 2
devourable = TRUE
no_vore = FALSE
var/parrot_damage_upper = 10
var/parrot_state = PARROT_WANDER //Hunt for a perch when created
@@ -296,7 +297,7 @@
else
parrot_state |= PARROT_FLEE //Otherwise, fly like a bat out of hell!
drop_held_item(0)
if(!stat && M.a_intent == INTENT_HELP)
if(stat != DEAD && M.a_intent == INTENT_HELP)
handle_automated_speech(1) //assured speak/emote
return
@@ -872,7 +873,7 @@
speak = list("Poly wanna cracker!", ":e Check the crystal, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS ABOUT TO DELAMINATE CALL THE SHUTTLE")
gold_core_spawnable = 0
speak_chance = 3
var/memory_saved = 0
var/memory_saved = FALSE
var/rounds_survived = 0
var/longest_survival = 0
var/longest_deathstreak = 0
@@ -903,50 +904,62 @@
rounds_survived = max(++rounds_survived,1)
if(rounds_survived > longest_survival)
longest_survival = rounds_survived
Write_Memory()
Write_Memory(FALSE)
memory_saved = TRUE
..()
/mob/living/simple_animal/parrot/Poly/death(gibbed)
if(!memory_saved)
var/go_ghost = 0
if(rounds_survived == longest_survival || rounds_survived == longest_deathstreak || prob(0.666))
go_ghost = 1
rounds_survived = min(--rounds_survived,0)
if(rounds_survived < longest_deathstreak)
longest_deathstreak = rounds_survived
Write_Memory()
if(go_ghost)
var/mob/living/simple_animal/parrot/Poly/ghost/G = new(loc)
if(mind)
mind.transfer_to(G)
else
G.key = key
Write_Memory(TRUE)
if(rounds_survived == longest_survival || rounds_survived == longest_deathstreak || prob(0.666))
var/mob/living/simple_animal/parrot/Poly/ghost/G = new(loc)
if(mind)
mind.transfer_to(G)
else
G.key = key
..(gibbed)
/mob/living/simple_animal/parrot/Poly/proc/Read_Memory()
var/json_file = file("data/npc_saves/Poly.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
speech_buffer = json["phrases"]
rounds_survived = json["roundssurvived"]
longest_survival = json["longestsurvival"]
longest_deathstreak = json["longestdeathstreak"]
if(fexists("data/npc_saves/Poly.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Poly.sav")
S["phrases"] >> speech_buffer
S["roundssurvived"] >> rounds_survived
S["longestsurvival"] >> longest_survival
S["longestdeathstreak"] >> longest_deathstreak
fdel("data/npc_saves/Poly.sav")
else
var/json_file = file("data/npc_saves/Poly.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
speech_buffer = json["phrases"]
rounds_survived = json["roundssurvived"]
longest_survival = json["longestsurvival"]
longest_deathstreak = json["longestdeathstreak"]
if(!islist(speech_buffer))
speech_buffer = list()
/mob/living/simple_animal/parrot/Poly/proc/Write_Memory()
/mob/living/simple_animal/parrot/Poly/proc/Write_Memory(dead)
var/json_file = file("data/npc_saves/Poly.json")
var/list/file_data = list()
if(islist(speech_buffer))
file_data["phrases"] = speech_buffer
file_data["roundssurvived"] = rounds_survived
file_data["longestsurvival"] = longest_survival
file_data["longestdeathstreak"] = longest_deathstreak
if(dead)
file_data["roundssurvived"] = min(rounds_survived - 1, 0)
file_data["longestsurvival"] = longest_survival
if(rounds_survived - 1 < longest_deathstreak)
file_data["longestdeathstreak"] = rounds_survived - 1
else
file_data["longestdeathstreak"] = longest_deathstreak
else
file_data["roundssurvived"] = rounds_survived + 1
if(rounds_survived + 1 > longest_survival)
file_data["longestsurvival"] = rounds_survived + 1
else
file_data["longestsurvival"] = longest_survival
file_data["longestdeathstreak"] = longest_deathstreak
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
memory_saved = 1
/mob/living/simple_animal/parrot/Poly/ghost
name = "The Ghost of Poly"
@@ -958,8 +971,8 @@
butcher_results = list(/obj/item/ectoplasm = 1)
/mob/living/simple_animal/parrot/Poly/ghost/Initialize()
memory_saved = 1 //At this point nothing is saved
..()
memory_saved = TRUE //At this point nothing is saved
. = ..()
/mob/living/simple_animal/parrot/Poly/ghost/handle_automated_speech()
if(ismob(loc))
@@ -983,4 +996,4 @@
loc = H
H.ContractDisease(P)
parrot_interest = null
H.visible_message("<span class='danger'>[src] dive bombs into [H]'s chest and vanishes!</span>", "<span class='userdanger'>[src] dive bombs into your chest, vanishing! This can't be good!</span>")
H.visible_message("<span class='danger'>[src] dive bombs into [H]'s chest and vanishes!</span>", "<span class='userdanger'>[src] dive bombs into your chest, vanishing! This can't be good!</span>")
@@ -85,6 +85,8 @@
//domestication
var/tame = 0
no_vore = TRUE
/mob/living/simple_animal/Initialize()
. = ..()
GLOB.simple_animals += src
@@ -95,6 +97,9 @@
real_name = name
if(!loc)
stack_trace("Simple animal being instantiated in nullspace")
if(vore_active)
init_belly()
verbs |= /mob/living/proc/animal_nom
/mob/living/simple_animal/Login()
@@ -228,7 +233,6 @@
if( abs(areatemp - bodytemperature) > 40 )
var/diff = areatemp - bodytemperature
diff = diff / 5
//to_chat(world, "changed from [bodytemperature] by [diff] to [bodytemperature + diff]")
bodytemperature += diff
if(!environment_is_safe(environment))
@@ -2,3 +2,101 @@
// List of targets excluded (for now) from being eaten by this mob.
var/list/prey_exclusions = list()
devourable = FALSE //insurance because who knows.
var/vore_active = FALSE // If vore behavior is enabled for this mob
var/vore_default_mode = DM_DIGEST // Default bellymode (DM_DIGEST, DM_HOLD, DM_ABSORB)
var/vore_digest_chance = 25 // Chance to switch to digest mode if resisted
var/vore_escape_chance = 25 // Chance of resisting out of mob
var/vore_stomach_name // The name for the first belly if not "stomach"
var/vore_stomach_flavor // The flavortext for the first belly if not the default
var/vore_fullness = 0 // How "full" the belly is (controls icons)
// Release belly contents beforey being gc'd!
/mob/living/simple_animal/Destroy()
for(var/I in vore_organs)
var/datum/belly/B = vore_organs[I]
B.release_all_contents() // When your stomach is empty
prey_excludes.Cut()
. = ..()
// Update fullness based on size & quantity of belly contents
/mob/living/simple_animal/proc/update_fullness(var/atom/movable/M)
var/new_fullness = 0
for(var/I in vore_organs)
var/datum/belly/B = vore_organs[I]
if (!(M in B.internal_contents))
return FALSE // Nothing's inside
new_fullness += M
vore_fullness = new_fullness
/mob/living/simple_animal/proc/swallow_check()
for(var/I in vore_organs)
var/datum/belly/B = vore_organs[I]
if(vore_active)
update_fullness()
if(!vore_fullness)
// Nothing
return
else
addtimer(CALLBACK(src, .proc/swallow_mob), B.swallow_time)
/mob/living/simple_animal/proc/swallow_mob()
for(var/I in vore_organs)
var/datum/belly/B = vore_organs[I]
for(var/mob/living/M in B.internal_contents)
B.transfer_contents(M, B.transferlocation)
/mob/living/simple_animal/death()
for(var/I in vore_organs)
var/datum/belly/B = vore_organs[I]
B.release_all_contents() // When your stomach is empty
..() // then you have my permission to die.
// Simple animals have only one belly. This creates it (if it isn't already set up)
/mob/living/simple_animal/proc/init_belly()
if(vore_organs.len)
return
if(no_vore) //If it can't vore, let's not give it a stomach.
return
var/datum/belly/B = new /datum/belly(src)
B.immutable = TRUE
B.name = vore_stomach_name ? vore_stomach_name : "stomach"
B.inside_flavor = vore_stomach_flavor ? vore_stomach_flavor : "Your surroundings are warm, soft, and slimy. Makes sense, considering you're inside \the [name]."
B.digest_mode = vore_default_mode
B.escapable = vore_escape_chance > 0
B.escapechance = vore_escape_chance
B.digestchance = vore_digest_chance
B.human_prey_swallow_time = swallowTime
B.nonhuman_prey_swallow_time = swallowTime
B.vore_verb = "swallow"
// TODO - Customizable per mob
B.emote_lists[DM_HOLD] = list( // We need more that aren't repetitive. I suck at endo. -Ace
"The insides knead at you gently for a moment.",
"The guts glorp wetly around you as some air shifts.",
"The predator takes a deep breath and sighs, shifting you somewhat.",
"The stomach squeezes you tight for a moment, then relaxes harmlessly.",
"The predator's calm breathing and thumping heartbeat pulses around you.",
"The warm walls kneads harmlessly against you.",
"The liquids churn around you, though there doesn't seem to be much effect.",
"The sound of bodily movements drown out everything for a moment.",
"The predator's movements gently force you into a different position.")
B.emote_lists[DM_DIGEST] = list(
"The burning acids eat away at your form.",
"The muscular stomach flesh grinds harshly against you.",
"The caustic air stings your chest when you try to breathe.",
"The slimy guts squeeze inward to help the digestive juices soften you up.",
"The onslaught against your body doesn't seem to be letting up; you're food now.",
"The predator's body ripples and crushes against you as digestive enzymes pull you apart.",
"The juices pooling beneath you sizzle against your sore skin.",
"The churning walls slowly pulverize you into meaty nutrients.",
"The stomach glorps and gurgles as it tries to work you into slop.")
src.vore_organs[B.name] = B
src.vore_selected = B.name
+28 -21
View File
@@ -225,7 +225,9 @@
var/mob/living/L = mob
switch(L.incorporeal_move)
if(INCORPOREAL_MOVE_BASIC)
L.loc = get_step(L, direct)
var/T = get_step(L,direct)
if(T)
L.loc = T
L.setDir(direct)
if(INCORPOREAL_MOVE_SHADOW)
if(prob(50))
@@ -254,31 +256,36 @@
return
else
return
L.loc = locate(locx,locy,mobloc.z)
var/limit = 2//For only two trailing shadows.
for(var/turf/T in getline(mobloc, L.loc))
new /obj/effect/temp_visual/dir_setting/ninja/shadow(T, L.dir)
limit--
if(limit<=0)
break
var/target = locate(locx,locy,mobloc.z)
if(target)
L.loc = target
var/limit = 2//For only two trailing shadows.
for(var/turf/T in getline(mobloc, L.loc))
new /obj/effect/temp_visual/dir_setting/ninja/shadow(T, L.dir)
limit--
if(limit<=0)
break
else
new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir)
L.loc = get_step(L, direct)
var/T = get_step(L,direct)
if(T)
L.loc = T
L.setDir(direct)
if(INCORPOREAL_MOVE_JAUNT) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
var/turf/open/floor/stepTurf = get_step(L, direct)
for(var/obj/effect/decal/cleanable/salt/S in stepTurf)
to_chat(L, "<span class='warning'>[S] bars your passage!</span>")
if(isrevenant(L))
var/mob/living/simple_animal/revenant/R = L
R.reveal(20)
R.stun(20)
return
if(stepTurf.flags_1 & NOJAUNT_1)
to_chat(L, "<span class='warning'>Holy energies block your path.</span>")
else
L.loc = get_step(L, direct)
L.setDir(direct)
if(stepTurf)
for(var/obj/effect/decal/cleanable/salt/S in stepTurf)
to_chat(L, "<span class='warning'>[S] bars your passage!</span>")
if(isrevenant(L))
var/mob/living/simple_animal/revenant/R = L
R.reveal(20)
R.stun(20)
return
if(stepTurf.flags_1 & NOJAUNT_1)
to_chat(L, "<span class='warning'>Holy energies block your path.</span>")
else
L.loc = get_step(L, direct)
L.setDir(direct)
return TRUE