diff --git a/code/game/objects/effects/semirandom_mobs_vr.dm b/code/game/objects/effects/semirandom_mobs_vr.dm
index b7008b46277..759270ca231 100644
--- a/code/game/objects/effects/semirandom_mobs_vr.dm
+++ b/code/game/objects/effects/semirandom_mobs_vr.dm
@@ -55,7 +55,10 @@ var/global/list/semirandom_mob_spawner_decisions = list()
list(/mob/living/simple_mob/animal/passive/yithian),
list(
/mob/living/simple_mob/animal/wolf = 10,
- /mob/living/simple_mob/animal/wolf/direwolf = 1
+ /mob/living/simple_mob/animal/wolf/direwolf = 5,
+ /mob/living/simple_mob/vore/greatwolf = 1,
+ /mob/living/simple_mob/vore/greatwolf/black = 1,
+ /mob/living/simple_mob/vore/greatwolf/grey = 1
),
list(/mob/living/simple_mob/vore/rabbit),
list(/mob/living/simple_mob/vore/redpanda),
@@ -109,12 +112,8 @@ var/global/list/semirandom_mob_spawner_decisions = list()
/mob/living/simple_mob/animal/giant_spider/phorogenic = 10,
/mob/living/simple_mob/animal/giant_spider/thermic = 5,
/mob/living/simple_mob/animal/giant_spider/tunneler = 10,
- /mob/living/simple_mob/animal/giant_spider/webslinger = 5
- ),
- list(
- /mob/living/simple_mob/animal/wolf = 10,
- /mob/living/simple_mob/animal/wolf/direwolf = 1
- ),
+ /mob/living/simple_mob/animal/giant_spider/webslinger = 5,
+ /mob/living/simple_mob/animal/giant_spider/broodmother = 1),
list(/mob/living/simple_mob/creature/strong),
list(/mob/living/simple_mob/faithless/strong),
list(/mob/living/simple_mob/animal/goat),
@@ -244,7 +243,6 @@ var/global/list/semirandom_mob_spawner_decisions = list()
list(/mob/living/simple_mob/mechanical/wahlem),
list(/mob/living/simple_mob/animal/passive/fox/syndicate),
list(/mob/living/simple_mob/animal/passive/fox),
- list(/mob/living/simple_mob/animal/wolf/direwolf),
list(/mob/living/simple_mob/animal/space/jelly),
list(
/mob/living/simple_mob/otie/feral,
@@ -292,7 +290,21 @@ var/global/list/semirandom_mob_spawner_decisions = list()
),
list(/mob/living/simple_mob/vore/solargrub),
list(/mob/living/simple_mob/vore/woof),
- list(/mob/living/simple_mob/vore/alienanimals/teppi)
+ list(/mob/living/simple_mob/vore/alienanimals/teppi),
+ list(/mob/living/simple_mob/vore/alienanimals/space_ghost),
+ list(/mob/living/simple_mob/vore/alienanimals/catslug),
+ list(/mob/living/simple_mob/vore/alienanimals/space_jellyfish),
+ list(/mob/living/simple_mob/vore/alienanimals/startreader),
+ list(
+ /mob/living/simple_mob/vore/bigdragon,
+ /mob/living/simple_mob/vore/bigdragon/friendly),
+ list(
+ /mob/living/simple_mob/vore/leopardmander = 50,
+ /mob/living/simple_mob/vore/leopardmander/blue = 10,
+ /mob/living/simple_mob/vore/leopardmander/exotic = 1
+ ),
+ list(/mob/living/simple_mob/vore/sheep),
+ list(/mob/living/simple_mob/vore/weretiger)
)
/obj/random/mob/semirandom_mob_spawner/item_to_spawn()
@@ -363,7 +375,10 @@ var/global/list/semirandom_mob_spawner_decisions = list()
list(/mob/living/simple_mob/animal/passive/yithian) = 10,
list(
/mob/living/simple_mob/animal/wolf = 10,
- /mob/living/simple_mob/animal/wolf/direwolf = 1
+ /mob/living/simple_mob/animal/wolf/direwolf = 5,
+ /mob/living/simple_mob/vore/greatwolf = 1,
+ /mob/living/simple_mob/vore/greatwolf/black = 1,
+ /mob/living/simple_mob/vore/greatwolf/grey = 1
) = 10,
list(/mob/living/simple_mob/vore/rabbit) = 10,
list(/mob/living/simple_mob/vore/redpanda) = 10,
@@ -407,7 +422,18 @@ var/global/list/semirandom_mob_spawner_decisions = list()
) = 5,
list(/mob/living/simple_mob/animal/sif/siffet) = 5,
list(/mob/living/simple_mob/animal/sif/tymisian) = 5,
- list(/mob/living/simple_mob/vore/alienanimals/teppi) = 10
+ list(/mob/living/simple_mob/vore/alienanimals/teppi) = 10,
+ list(/mob/living/simple_mob/vore/alienanimals/dustjumper) = 5,
+ list(/mob/living/simple_mob/vore/alienanimals/space_jellyfish) = 5,
+ list(/mob/living/simple_mob/vore/alienanimals/space_ghost) = 5,
+ list(
+ /mob/living/simple_mob/vore/leopardmander = 50,
+ /mob/living/simple_mob/vore/leopardmander/blue = 10,
+ /mob/living/simple_mob/vore/leopardmander/exotic = 1
+ ) = 5,
+ list(/mob/living/simple_mob/vore/sheep) = 5,
+ list(/mob/living/simple_mob/vore/weretiger) = 5,
+ list(/mob/living/simple_mob/vore/alienanimals/skeleton) = 5
)
/obj/random/mob/semirandom_mob_spawner/monster
@@ -439,8 +465,11 @@ var/global/list/semirandom_mob_spawner_decisions = list()
) = 1,
list(
/mob/living/simple_mob/animal/wolf = 10,
- /mob/living/simple_mob/animal/wolf/direwolf = 1,
- ) = 80,
+ /mob/living/simple_mob/animal/wolf/direwolf = 5,
+ /mob/living/simple_mob/vore/greatwolf = 1,
+ /mob/living/simple_mob/vore/greatwolf/black = 1,
+ /mob/living/simple_mob/vore/greatwolf/grey = 1
+ ) = 40,
list(/mob/living/simple_mob/creature/strong) = 40,
list(/mob/living/simple_mob/faithless/strong) = 20,
list(/mob/living/simple_mob/animal/goat) = 1,
@@ -501,7 +530,18 @@ var/global/list/semirandom_mob_spawner_decisions = list()
/mob/living/simple_mob/vore/oregrub = 5,
/mob/living/simple_mob/vore/oregrub/lava = 1
) = 15,
- list(/mob/living/simple_mob/vore/alienanimals/teppi) = 15
+ list(/mob/living/simple_mob/vore/alienanimals/teppi) = 15,
+ list(/mob/living/simple_mob/vore/alienanimals/space_jellyfish) = 5,
+ list(/mob/living/simple_mob/vore/alienanimals/space_ghost) = 5,
+ list(
+ /mob/living/simple_mob/vore/leopardmander = 50,
+ /mob/living/simple_mob/vore/leopardmander/blue = 10,
+ /mob/living/simple_mob/vore/leopardmander/exotic = 1
+ ) = 5,
+ list(/mob/living/simple_mob/vore/sheep) = 5,
+ list(/mob/living/simple_mob/vore/weretiger) = 5,
+ list(/mob/living/simple_mob/vore/alienanimals/skeleton) = 5,
+ list(/mob/living/simple_mob/vore/alienanimals/catslug) = 5
)
/obj/random/mob/semirandom_mob_spawner/humanoid
@@ -675,7 +715,12 @@ var/global/list/semirandom_mob_spawner_decisions = list()
mob_faction = "vore"
possible_mob_types = list(
- list(/mob/living/simple_mob/animal/wolf/direwolf) = 100,
+ list(
+ /mob/living/simple_mob/animal/wolf/direwolf = 5,
+ /mob/living/simple_mob/vore/greatwolf = 1,
+ /mob/living/simple_mob/vore/greatwolf/black = 1,
+ /mob/living/simple_mob/vore/greatwolf/grey = 1
+ ) = 100,
list(/mob/living/simple_mob/animal/space/jelly) = 70,
list(
/mob/living/simple_mob/otie/feral,
diff --git a/code/game/objects/items/devices/denecrotizer_vr.dm b/code/game/objects/items/devices/denecrotizer_vr.dm
index 164e0693984..70640f2bb87 100644
--- a/code/game/objects/items/devices/denecrotizer_vr.dm
+++ b/code/game/objects/items/devices/denecrotizer_vr.dm
@@ -95,6 +95,10 @@
to_chat(D, "Sorry, someone else has already inhabited [src].")
return FALSE
+ if(capture_caught && !D.client.prefs.capture_crystal)
+ to_chat(D, "Sorry, [src] is participating in capture mechanics, and your preferences do not allow for that.")
+ return FALSE
+
// Insert whatever ban checks you want here if we ever add simplemob bans
return TRUE
diff --git a/code/game/objects/items/weapons/capture_crystal.dm b/code/game/objects/items/weapons/capture_crystal.dm
index c027c9712ff..aada12a941d 100644
--- a/code/game/objects/items/weapons/capture_crystal.dm
+++ b/code/game/objects/items/weapons/capture_crystal.dm
@@ -17,6 +17,7 @@
var/last_activate //Automatically set by things that try to move the bound mob or capture things
var/empty_icon = "empty"
var/full_icon = "full"
+ var/capture_chance_modifier = 1 //So we can have special subtypes with different capture rates!
/obj/item/capture_crystal/Initialize()
. = ..()
@@ -24,92 +25,81 @@
//Let's make sure we clean up our references and things if the crystal goes away (such as when it's digested)
/obj/item/capture_crystal/Destroy()
- . = ..()
if(bound_mob)
if(bound_mob in contents)
unleash()
to_chat(bound_mob, "You feel like yourself again. You are no longer under the influince of \the [src]'s command.")
UnregisterSignal(bound_mob, COMSIG_PARENT_QDELETING)
+ bound_mob.capture_caught = FALSE
bound_mob = null
if(owner)
UnregisterSignal(owner, COMSIG_PARENT_QDELETING)
owner = null
+ return ..()
/obj/item/capture_crystal/examine(user)
. = ..()
- if(user == owner)
- if(bound_mob)
- . += "[bound_mob]'s crystal"
- if(isanimal(bound_mob))
- . += "[bound_mob.health / bound_mob.maxHealth * 100]%"
- if(bound_mob.ooc_notes)
- . += "OOC Notes: \[View\]"
- . += "\[Mechanical Vore Preferences\]"
+ if(user == owner && bound_mob)
+ . += "[bound_mob]'s crystal"
+ if(isanimal(bound_mob))
+ . += "[bound_mob.health / bound_mob.maxHealth * 100]%"
+ if(bound_mob.ooc_notes)
+ . += "OOC Notes: \[View\]"
+ . += "\[Mechanical Vore Preferences\]"
//Command! This lets the owner toggle hostile on AI controlled mobs, or send a silent command message to your bound mob, wherever they may be.
/obj/item/capture_crystal/ui_action_click()
- if(ismob(loc))
- var/mob/living/M = src.loc
- if(M != owner)
- to_chat(M, "\The [src] emits an unpleasant tone... It does not respond to your command.")
- playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
- return
- if(!bound_mob)
- to_chat(M, "\The [src] emits an unpleasant tone... There is nothing to command.")
- playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
- return
- if(isanimal(bound_mob) && !bound_mob.client)
- if(!isnull(bound_mob.get_AI_stance()))
- var/datum/ai_holder/AI = bound_mob.ai_holder
- AI.hostile = !AI.hostile
- if(!AI.hostile)
- AI.set_stance(STANCE_IDLE)
- to_chat(M, span("notice", "\The [bound_mob] is now [AI.hostile ? "hostile" : "passive"]."))
- return
- if(bound_mob.client)
- var/transmit_msg
- transmit_msg = sanitizeSafe(input(usr, "What is your command?", "Command", null) as text, MAX_NAME_LEN)
- if(isnull(transmit_msg))
- to_chat(M, "You decided against it.")
- return
- to_chat(bound_mob, "\The [owner] commands, '[transmit_msg]'")
- to_chat(M, "Your command has been transmitted, '[transmit_msg]'")
- else
- to_chat(M, "\The [src] emits an unpleasant tone... \The [bound_mob] is unresponsive.")
- playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
- else
+ if(!ismob(loc))
return
-
+ var/mob/living/M = src.loc
+ if(M != owner)
+ to_chat(M, "\The [src] emits an unpleasant tone... It does not respond to your command.")
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ return
+ if(!bound_mob)
+ to_chat(M, "\The [src] emits an unpleasant tone... There is nothing to command.")
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ return
+ if(isanimal(bound_mob) && !bound_mob.client)
+ if(!isnull(bound_mob.get_AI_stance()))
+ var/datum/ai_holder/AI = bound_mob.ai_holder
+ AI.hostile = !AI.hostile
+ if(!AI.hostile)
+ AI.set_stance(STANCE_IDLE)
+ to_chat(M, span("notice", "\The [bound_mob] is now [AI.hostile ? "hostile" : "passive"]."))
+ return
+ if(bound_mob.client)
+ var/transmit_msg
+ transmit_msg = sanitizeSafe(input(usr, "What is your command?", "Command", null) as text, MAX_NAME_LEN)
+ if(isnull(transmit_msg))
+ to_chat(M, "You decided against it.")
+ return
+ to_chat(bound_mob, "\The [owner] commands, '[transmit_msg]'")
+ to_chat(M, "Your command has been transmitted, '[transmit_msg]'")
+ else
+ to_chat(M, "\The [src] emits an unpleasant tone... \The [bound_mob] is unresponsive.")
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+
//Lets the owner get AI controlled bound mobs to follow them, or tells player controlled mobs to follow them.
/obj/item/capture_crystal/verb/follow_owner()
set name = "Toggle Follow"
set category = "Object"
set src in usr
- if(ismob(loc))
- var/mob/living/M = src.loc
- if(M != owner)
- to_chat(M, "\The [src] emits an unpleasant tone... It does not respond to your command.")
- playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
- return
- if(bound_mob.stat != CONSCIOUS)
- to_chat(M, "\The [src] emits an unpleasant tone... \The [bound_mob] is not able to hear your command.")
- playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
- return
- if(bound_mob.client)
- to_chat(bound_mob, "\The [owner] wishes for you to follow them.")
- return
- if(bound_mob in contents)
- var/datum/ai_holder/AI = bound_mob.ai_holder
- if(AI.leader)
- to_chat(M, "\The [src] chimes~ \The [bound_mob] stopped following [AI.leader].")
- AI.lose_follow(AI.leader)
- else
- AI.set_follow(M)
- to_chat(M, "\The [src] chimes~ \The [bound_mob] started following following [AI.leader].")
- if(!(bound_mob in view(M)))
- to_chat(M, "\The [src] emits an unpleasant tone... \The [bound_mob] is not able to hear your command.")
- playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
- return
+ if(!ismob(loc))
+ return
+ var/mob/living/M = src.loc
+ if(M != owner)
+ to_chat(M, "\The [src] emits an unpleasant tone... It does not respond to your command.")
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ return
+ if(bound_mob.stat != CONSCIOUS)
+ to_chat(M, "\The [src] emits an unpleasant tone... \The [bound_mob] is not able to hear your command.")
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ return
+ if(bound_mob.client)
+ to_chat(bound_mob, "\The [owner] wishes for you to follow them.")
+ return
+ if(bound_mob in contents)
var/datum/ai_holder/AI = bound_mob.ai_holder
if(AI.leader)
to_chat(M, "\The [src] chimes~ \The [bound_mob] stopped following [AI.leader].")
@@ -117,14 +107,23 @@
else
AI.set_follow(M)
to_chat(M, "\The [src] chimes~ \The [bound_mob] started following following [AI.leader].")
-
+ if(!(bound_mob in view(M)))
+ to_chat(M, "\The [src] emits an unpleasant tone... \The [bound_mob] is not able to hear your command.")
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ return
+ var/datum/ai_holder/AI = bound_mob.ai_holder
+ if(AI.leader)
+ to_chat(M, "\The [src] chimes~ \The [bound_mob] stopped following [AI.leader].")
+ AI.lose_follow(AI.leader)
+ else
+ AI.set_follow(M)
+ to_chat(M, "\The [src] chimes~ \The [bound_mob] started following following [AI.leader].")
/obj/item/capture_crystal/update_icon()
. = ..()
if(spawn_mob_type)
- icon_state = "full"
- return
- if(!bound_mob)
+ icon_state = full_icon
+ else if(!bound_mob)
icon_state = "inactive"
else if(bound_mob in contents)
icon_state = full_icon
@@ -150,15 +149,21 @@
else if(M == user) //You don't have a mob, you ponder the orb instead of trying to capture yourself
user.visible_message("\The [user] ponders \the [src]...", "You ponder \the [src]...")
return
- else //Try to capture someone without throwing
+ else if (cooldown_check()) //Try to capture someone without throwing
user.visible_message("\The [user] taps \the [M] with \the [src].")
activate(user, M)
+ else
+ to_chat(user, "\The [src] emits an unpleasant tone... It is not ready yet.")
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
//Tries to unleash or recall your stored mob
/obj/item/capture_crystal/attack_self(mob/living/user)
if(!cooldown_check())
to_chat(user, "\The [src] emits an unpleasant tone... It is not ready yet.")
- playsound(src, 'sound/effects/capture-crystal-problem.ogg', 75, 1, -1)
+ if(bound_mob)
+ playsound(src, 'sound/effects/capture-crystal-problem.ogg', 75, 1, -1)
+ else
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
return
if(user == bound_mob) //You can't recall yourself
to_chat(user, "\The [src] emits an unpleasant tone... It does not activate for you.")
@@ -176,7 +181,7 @@
//The basic capture command does most of the registration work.
/obj/item/capture_crystal/proc/capture(mob/living/M, mob/living/U)
- if(!M.capture_crystal)
+ if(!M.capture_crystal || M.capture_caught)
to_chat(U, "This creature is not suitable for capture.")
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
return
@@ -184,10 +189,15 @@
owner = U
if(!bound_mob)
bound_mob = M
+ bound_mob.capture_caught = TRUE
+ desc = "A glowing crystal in what appears to be some kind of steel housing."
//Determines the capture chance! So you can't capture AI mobs if they're perfectly healthy and all that
/obj/item/capture_crystal/proc/capture_chance(mob/living/M)
var/capture_chance = ((1 - (M.health / M.maxHealth)) * 100)
+ if(capture_chance_modifier >= 100)
+ return 100
+ capture_chance *= capture_chance_modifier
if(M.stat == UNCONSCIOUS)
capture_chance += 10
else if(M.stat == CONSCIOUS)
@@ -205,7 +215,7 @@
to_chat(U, "This creature is not suitable for capture.")
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
return
- if(!M.capture_crystal)
+ if(!M.capture_crystal || M.capture_caught)
to_chat(U, "This creature is not suitable for capture.")
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
return
@@ -218,6 +228,7 @@
//The clean up procs!
/obj/item/capture_crystal/proc/mob_was_deleted()
UnregisterSignal(bound_mob, COMSIG_PARENT_QDELETING)
+ bound_mob.capture_caught = FALSE
bound_mob = null
owner = null
active = FALSE
@@ -249,6 +260,7 @@
return
if(isliving(target)) //So we don't have a mob, let's try to claim one! Is the target a mob?
var/mob/living/M = target
+ last_activate = world.time
if(M.stat == DEAD) //Is it dead? We can't influence dead things.
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
to_chat(user, "\The [src] clicks unsatisfyingly... \The [M] is not in a state to be captured.")
@@ -278,7 +290,7 @@
S.ai_holder.target = user
S.ai_holder.track_target_position()
S.ai_holder.set_stance(STANCE_FIGHT)
- visible_message("\The [src] bonks into \the [S], angering it!")
+ user.visible_message("\The [src] bonks into \the [S], angering it!")
update_icon()
spawn(activate_cooldown)
update_icon()
@@ -321,6 +333,7 @@
update_icon()
else
to_chat(user, "\The [src] clicks and emits a small, unpleasant tone. \The [bound_mob] cannot be recalled.")
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
//Let's let our mob out!
/obj/item/capture_crystal/proc/unleash(mob/living/user, atom/target)
@@ -389,6 +402,14 @@
to_chat(thrower, "\The [src] clicks unpleasantly...")
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+/obj/item/capture_crystal/great
+ capture_chance_modifier = 1.5
+
+/obj/item/capture_crystal/ultra
+ capture_chance_modifier = 2
+
+/obj/item/capture_crystal/master
+ capture_chance_modifier = 100
/obj/item/capture_crystal/cass
spawn_mob_type = /mob/living/simple_mob/vore/woof/cass
@@ -398,11 +419,14 @@
spawn_mob_type = /mob/living/simple_mob/vore/bigdragon
/obj/item/capture_crystal/bigdragon/friendly
spawn_mob_type = /mob/living/simple_mob/vore/bigdragon/friendly
-
/obj/item/capture_crystal/teppi
spawn_mob_type = /mob/living/simple_mob/vore/alienanimals/teppi
/obj/item/capture_crystal/broodmother
spawn_mob_type = /mob/living/simple_mob/animal/giant_spider/broodmother
+/obj/item/capture_crystal/skeleton
+ spawn_mob_type = /mob/living/simple_mob/vore/alienanimals/skeleton
+/obj/item/capture_crystal/dustjumper
+ spawn_mob_type = /mob/living/simple_mob/vore/alienanimals/dustjumper
/obj/item/capture_crystal/random
var/static/list/possible_mob_types = list(
@@ -506,11 +530,14 @@
/mob/living/simple_mob/animal/giant_spider/phorogenic = 10,
/mob/living/simple_mob/animal/giant_spider/thermic = 5,
/mob/living/simple_mob/animal/giant_spider/tunneler = 10,
- /mob/living/simple_mob/animal/giant_spider/webslinger = 5
- ),
+ /mob/living/simple_mob/animal/giant_spider/webslinger = 5,
+ /mob/living/simple_mob/animal/giant_spider/broodmother = 1),
list(
/mob/living/simple_mob/animal/wolf = 10,
- /mob/living/simple_mob/animal/wolf/direwolf = 1
+ /mob/living/simple_mob/animal/wolf/direwolf = 5,
+ /mob/living/simple_mob/vore/greatwolf = 1,
+ /mob/living/simple_mob/vore/greatwolf/black = 1,
+ /mob/living/simple_mob/vore/greatwolf/grey = 1
),
list(/mob/living/simple_mob/creature/strong),
list(/mob/living/simple_mob/faithless/strong),
@@ -701,12 +728,9 @@
/mob/living/simple_mob/vore/leopardmander/exotic = 1
),
list(/mob/living/simple_mob/vore/sheep),
- list(
- /mob/living/simple_mob/vore/greatwolf,
- /mob/living/simple_mob/vore/greatwolf/black,
- /mob/living/simple_mob/vore/greatwolf/grey
- ),
- list(/mob/living/simple_mob/vore/weretiger)
+ list(/mob/living/simple_mob/vore/weretiger),
+ list(/mob/living/simple_mob/vore/alienanimals/skeleton),
+ list(/mob/living/simple_mob/vore/alienanimals/dustjumper)
)
/obj/item/capture_crystal/random/Initialize()
@@ -716,4 +740,5 @@
return ..()
/mob/living
- var/capture_crystal = TRUE //If TRUE, the mob is capturable. Otherwise it isn't.
\ No newline at end of file
+ var/capture_crystal = TRUE //If TRUE, the mob is capturable. Otherwise it isn't.
+ var/capture_caught = FALSE
\ No newline at end of file
diff --git a/code/game/objects/random/misc_vr.dm b/code/game/objects/random/misc_vr.dm
index 0d3a17c23f2..2157631709c 100644
--- a/code/game/objects/random/misc_vr.dm
+++ b/code/game/objects/random/misc_vr.dm
@@ -23,6 +23,7 @@
prob(30);/obj/item/weapon/aliencoin/gold,
prob(20);/obj/item/weapon/aliencoin/phoron,
prob(10);/obj/item/device/denecrotizer,
+ prob(5);/obj/item/capture_crystal,
prob(5);/obj/item/device/perfect_tele,
prob(5);/obj/item/weapon/bluespace_harpoon,
prob(1);/obj/item/weapon/cell/infinite,
@@ -43,9 +44,43 @@
prob(3);/obj/fiftyspawner/silver,
prob(1);/obj/fiftyspawner/diamond,
prob(5);/obj/fiftyspawner/phoron,
- prob(1);/obj/item/weapon/telecube/randomized
+ prob(1);/obj/item/weapon/telecube/randomized,
+ prob(1);/obj/item/capture_crystal/random
)
/obj/random/awayloot/nofail
name = "garunteed random away mission loot"
spawn_nothing_percentage = 0
+
+/obj/random/awayloot/looseloot
+/obj/random/awayloot/looseloot/item_to_spawn()
+ return pick(prob(50);/obj/item/weapon/aliencoin,
+ prob(40);/obj/item/weapon/aliencoin/silver,
+ prob(30);/obj/item/weapon/aliencoin/gold,
+ prob(20);/obj/item/weapon/aliencoin/phoron,
+ prob(10);/obj/item/device/denecrotizer,
+ prob(5);/obj/item/capture_crystal,
+ prob(5);/obj/item/device/perfect_tele,
+ prob(5);/obj/item/weapon/bluespace_harpoon,
+ prob(1);/obj/item/weapon/cell/infinite,
+ prob(1);/obj/item/weapon/cell/void,
+ prob(1);/obj/item/weapon/cell/device/weapon/recharge/alien,
+ prob(1);/obj/item/clothing/shoes/boots/speed,
+ prob(1);/obj/item/device/nif,
+ prob(1);/obj/item/device/paicard,
+ prob(2);/obj/item/weapon/storage/backpack/dufflebag/syndie,
+ prob(2);/obj/item/weapon/storage/backpack/dufflebag/syndie/ammo,
+ prob(2);/obj/item/weapon/storage/backpack/dufflebag/syndie/med,
+ prob(2);/obj/item/clothing/mask/gas/voice,
+ prob(2);/obj/item/device/radio_jammer,
+ prob(1);/obj/item/toy/bosunwhistle,
+ prob(1);/obj/item/weapon/bananapeel,
+ prob(5);/obj/fiftyspawner/platinum,
+ prob(3);/obj/fiftyspawner/gold,
+ prob(3);/obj/fiftyspawner/silver,
+ prob(1);/obj/fiftyspawner/diamond,
+ prob(5);/obj/fiftyspawner/phoron,
+ prob(1);/obj/item/weapon/telecube/randomized,
+ prob(1);/obj/item/capture_crystal/random,
+ prob(10000);/obj/random/meat
+ )
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/skeleton.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/skeleton.dm
new file mode 100644
index 00000000000..4e9f2f66e07
--- /dev/null
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/skeleton.dm
@@ -0,0 +1,94 @@
+/datum/category_item/catalogue/fauna/skeleton
+ name = "Alien Wildlife - Space Skeleton"
+ desc = "A creature consisting primarily of what appears to be bones with no apparent connective tissue, muscle, or organs.\
+ It is not clear at all how this creature even operates."
+ value = CATALOGUER_REWARD_MEDIUM
+
+/mob/living/simple_mob/vore/alienanimals/skeleton
+ name = "skeleton"
+ desc = "An arrangement of what appears to be bones, given life and mobility. It looks REALLY spooky."
+ catalogue_data = list(/datum/category_item/catalogue/fauna/skeleton)
+
+ icon = 'icons/mob/alienanimals_x32.dmi'
+ icon_state = "skeleton"
+ icon_living = "skeleton"
+ icon_dead = "skeleton_dead"
+
+ faction = "space skeleton"
+ maxHealth = 100
+ health = 100
+ movement_cooldown = 1
+ movement_sound = 'sound/effects/skeleton_walk.ogg' //VERY IMPORTANT
+
+ see_in_dark = 10
+
+ response_help = "rattles"
+ response_disarm = "shoves aside"
+ response_harm = "smashes"
+
+ melee_damage_lower = 1
+ melee_damage_upper = 10
+ attack_sharp = FALSE
+ attacktext = list("spooked", "startled", "jumpscared", "rattled at")
+
+ ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive/skeleton
+
+ min_oxy = 0
+ max_oxy = 0
+ min_tox = 0
+ max_tox = 0
+ min_co2 = 0
+ max_co2 = 0
+ min_n2 = 0
+ max_n2 = 0
+ minbodytemp = 0
+ maxbodytemp = 900
+
+ loot_list = list(
+ /obj/item/weapon/bone = 25,
+ /obj/item/weapon/bone/skull = 25,
+ /obj/item/weapon/bone/ribs = 25,
+ /obj/item/weapon/bone/arm = 25,
+ /obj/item/weapon/bone/leg = 25
+ )
+
+ speak_emote = list("rattles")
+
+ say_list_type = /datum/say_list/skeleton
+
+ vore_active = 1
+ vore_capacity = 1
+ vore_bump_chance = 5
+ vore_ignores_undigestable = 0
+ vore_default_mode = DM_DRAIN
+ vore_icons = SA_ICON_LIVING
+ vore_stomach_name = "stomach"
+ vore_default_contamination_flavor = "Wet"
+ vore_default_contamination_color = "grey"
+ vore_default_item_mode = IM_DIGEST
+
+/datum/say_list/skeleton
+ speak = list("Nyeh heh heeeh","NYAAAAHHHH", "Books are the real treasures of the world!", "Why are skeletons so calm? Because nothing gets under their skin.","When does a skeleton laugh? When someone tickels their funny bone!","What is a skeleton’s favorite mode of transport? A scare-plane.", "What did the skeleton say to the vampire? 'You suck.'","What is a skeleton’s favorite thing to do with their cell phone? Take skelfies.", "How did the skeleton know the other skeleton was lying? He could see right through him.","What’s a skeleton’s least favorite room in the house? The living room.", "How much does an elephant skeleton weigh? Skele-tons.", "Why do skeletons drink so much milk? It’s good for the bones!", "Where do bad jokes about skeletons belong? In the skelebin.","What does a skeleton use to cut through objects? A shoulder blade.", "What kind of jokes do skeletons tell? Humerus ones.")
+ emote_see = list("spins its head around", "shuffles","shambles","practices on the xylophone","drinks some milk","looks at you. Its hollow, bottomless sockets gaze into you greedily.")
+ emote_hear = list("rattles","makes a spooky sound","cackles madly","plinks","clacks")
+
+/mob/living/simple_mob/vore/alienanimals/skeleton/init_vore()
+ ..()
+ var/obj/belly/B = vore_selected
+ B.name = "stomach"
+ B.desc = "You're not sure quite how, but you've found your way inside of the skeleton's stomach! It's cramped and cold and sounds heavily of xylophones!"
+ B.mode_flags = 40
+ B.digest_brute = 0.5
+ B.digest_burn = 0.5
+ B.digestchance = 10
+ B.absorbchance = 0
+ B.escapechance = 25
+
+/mob/living/simple_mob/vore/alienanimals/skeleton/death(gibbed, deathmessage = "falls down and stops moving...")
+ . = ..()
+
+/datum/ai_holder/simple_mob/melee/evasive/skeleton
+ hostile = TRUE
+ retaliate = TRUE
+ destructive = TRUE
+ violent_breakthrough = TRUE
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm
new file mode 100644
index 00000000000..2fe4da26b61
--- /dev/null
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm
@@ -0,0 +1,92 @@
+/datum/category_item/catalogue/fauna/dustjumper
+ name = "Alien Wildlife - Dust Jumper"
+ desc = "A small, quick creature, the dust jumper is a rare space creature.\
+ They have striking similarities to the common mouse, but these creatures are actually most commonly found in space.\
+ They are known to make their homes in asteroids, and leap from one to another when food is scarce.\
+ Dust jumpers are omnivorous, eating what scraps of organic material they can get their little paws on.\
+ They hybernate during long floats through space."
+ value = CATALOGUER_REWARD_MEDIUM
+
+/mob/living/simple_mob/vore/alienanimals/dustjumper
+ name = "dust jumper"
+ desc = "A small, unassuming mammal. It looks quite soft and fluffy, and has bright blue eyes."
+ catalogue_data = list(/datum/category_item/catalogue/fauna/dustjumper)
+
+ icon = 'icons/mob/alienanimals_x32.dmi'
+ icon_state = "space_mouse"
+ icon_living = "space_mouse"
+ icon_dead = "space_mouse_dead"
+
+ faction = "space mouse"
+ maxHealth = 20
+ health = 20
+ movement_cooldown = 1
+
+ see_in_dark = 10
+
+ response_help = "pets"
+ response_disarm = "pushes"
+ response_harm = "punches"
+
+ melee_damage_lower = 1
+ melee_damage_upper = 2
+ attack_sharp = FALSE
+ attacktext = list("nipped", "squeaked at", "hopped on", "kicked")
+
+ ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive/dustjumper
+
+ min_oxy = 0
+ max_oxy = 0
+ min_tox = 0
+ max_tox = 0
+ min_co2 = 0
+ max_co2 = 0
+ min_n2 = 0
+ max_n2 = 0
+ minbodytemp = 0
+ maxbodytemp = 900
+
+ speak_emote = list("squeaks")
+
+ say_list_type = /datum/say_list/mouse
+
+ vore_active = 1
+ vore_capacity = 1
+ vore_bump_chance = 0
+ vore_ignores_undigestable = 0
+ vore_default_mode = DM_DRAIN
+ vore_icons = SA_ICON_LIVING
+ vore_stomach_name = "stomach"
+ vore_default_contamination_flavor = "Wet"
+ vore_default_contamination_color = "grey"
+ vore_default_item_mode = IM_DIGEST
+
+/mob/living/simple_mob/vore/alienanimals/dustjumper/init_vore()
+ ..()
+ var/obj/belly/B = vore_selected
+ B.name = "stomach"
+ B.desc = "You've been packed into the impossibly tight stomach of the dust jumper!!! The broiling heat seeps into you while the walls churn in powerfully, forcing you to curl up in the darkness."
+ B.mode_flags = 40
+ B.digest_brute = 0.5
+ B.digest_burn = 0.5
+ B.digestchance = 10
+ B.absorbchance = 0
+ B.escapechance = 25
+
+/mob/living/simple_mob/vore/alienanimals/dustjumper/Life()
+ . = ..()
+ if(!.)
+ return
+ if(vore_fullness == 0 && movement_cooldown == 50)
+ movement_cooldown = initial(movement_cooldown)
+/mob/living/simple_mob/vore/alienanimals/dustjumper/perform_the_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, delay)
+ . = ..()
+ movement_cooldown = 50
+
+/datum/ai_holder/simple_mob/melee/evasive/dustjumper
+ hostile = FALSE
+ retaliate = TRUE
+ destructive = FALSE
+ violent_breakthrough = FALSE
+ can_flee = TRUE
+ flee_when_dying = TRUE
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm
index d04477199f2..b8de4885ba7 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm
@@ -71,6 +71,8 @@
"rad" = 100
)
+ loot_list = list(/obj/item/weapon/ore/diamond = 100)
+
speak_emote = list("rumbles")
vore_active = 0
@@ -117,7 +119,6 @@
/mob/living/simple_mob/vore/alienanimals/space_ghost/death(gibbed, deathmessage = "fades away!")
. = ..()
- new /obj/item/weapon/ore/diamond(loc, src)
qdel(src)
/mob/living/simple_mob/vore/alienanimals/spooky_ghost
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm
index 7341c6e2ed7..b77d55a2c82 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm
@@ -47,7 +47,7 @@
minbodytemp = 0
maxbodytemp = 900
- loot_list = list(/obj/random/underdark/uncertain)
+ loot_list = list(/obj/random/underdark/uncertain = 25)
armor = list(
"melee" = 100,
diff --git a/icons/mob/alienanimals_x32.dmi b/icons/mob/alienanimals_x32.dmi
index 1f36df70a30..b187ad58735 100644
Binary files a/icons/mob/alienanimals_x32.dmi and b/icons/mob/alienanimals_x32.dmi differ
diff --git a/sound/effects/skeleton_walk.ogg b/sound/effects/skeleton_walk.ogg
new file mode 100644
index 00000000000..d5791ec5420
Binary files /dev/null and b/sound/effects/skeleton_walk.ogg differ
diff --git a/vorestation.dme b/vorestation.dme
index 85f6582c408..031f0c1e936 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -2960,6 +2960,8 @@
#include "code\modules\mob\living\simple_mob\subtypes\animal\animal.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\alien animals\catslug.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\alien animals\jellyfish.dm"
+#include "code\modules\mob\living\simple_mob\subtypes\animal\alien animals\skeleton.dm"
+#include "code\modules\mob\living\simple_mob\subtypes\animal\alien animals\space_mouse.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\alien animals\spacewhale.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\alien animals\spookyghost.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\alien animals\startreader.dm"