Security / PseudoCargo Expansion (#6482)

* Security Expansion work.

* Weaponized Racism, Stowaways, Meteors

* Fix Fix. Prep modular armor for addition.

* Fix the boots.

* More modular armor work. Now in cargo!

* Fixfix

* Fixfix

* Thank you anxiety very cool.

* Make a Stowaway Antag

* FixFix
This commit is contained in:
Mechoid
2019-11-24 14:22:25 -08:00
committed by Anewbe
parent 2dddf3d594
commit 7ecdcb40d2
83 changed files with 2710 additions and 68 deletions
+12
View File
@@ -116,6 +116,18 @@
return 0
/datum/language/swarmbot
name = LANGUAGE_SWARMBOT
desc = "A confusing mechanical language spoken by some form of ancient machine."
speech_verb = "clatters"
ask_verb = "chatters"
exclaim_verb = "shrieks"
colour = "changeling"
key = "_"
flags = NO_STUTTER | RESTRICTED
syllables = list("^", "v", "-", ".", "~")
space_chance = 60
//for your antag purposes.
/datum/language/minbus
name = LANGUAGE_MINBUS
+36 -3
View File
@@ -32,6 +32,7 @@
var/will_patrol = 0 // If set to 1, will patrol, duh
var/patrol_speed = 1 // How many times per tick we move when patrolling
var/target_speed = 2 // Ditto for chasing the target
var/panic_on_alert = FALSE // Will the bot go faster when the alert level is raised?
var/min_target_dist = 1 // How close we try to get to the target
var/max_target_dist = 50 // How far we are willing to go
var/max_patrol_dist = 250
@@ -170,14 +171,20 @@
if(!A || !A.loc || prob(1))
ignore_list -= A
handleRegular()
var/panic_speed_mod = 0
if(panic_on_alert)
panic_speed_mod = handlePanic()
if(target && confirmTarget(target))
if(Adjacent(target))
handleAdjacentTarget()
else
handleRangedTarget()
if(!wait_if_pulled || !pulledby)
for(var/i = 1 to target_speed)
sleep(20 / (target_speed + 1))
for(var/i = 1 to (target_speed + panic_speed_mod))
sleep(20 / (target_speed + panic_speed_mod + 1))
stepToTarget()
if(max_frustration && frustration > max_frustration * target_speed)
handleFrustrated(1)
@@ -186,7 +193,7 @@
lookForTargets()
if(will_patrol && !pulledby && !target)
if(patrol_path && patrol_path.len)
for(var/i = 1 to patrol_speed)
for(var/i = 1 to (patrol_speed + panic_speed_mod))
sleep(20 / (patrol_speed + 1))
handlePatrol()
if(max_frustration && frustration > max_frustration * patrol_speed)
@@ -205,6 +212,32 @@
/mob/living/bot/proc/handleRangedTarget()
return
/mob/living/bot/proc/handlePanic() // Speed modification based on alert level.
. = 0
switch(get_security_level())
if("green")
. = 0
if("yellow")
. = 0
if("violet")
. = 0
if("orange")
. = 0
if("blue")
. = 1
if("red")
. = 2
if("delta")
. = 2
return .
/mob/living/bot/proc/stepToTarget()
if(!target || !target.loc)
return
+26
View File
@@ -38,6 +38,32 @@
spawn(600)
ignore_list -= g
/mob/living/bot/cleanbot/handlePanic() // Speed modification based on alert level.
. = 0
switch(get_security_level())
if("green")
. = 0
if("yellow")
. = 1
if("violet")
. = 1
if("orange")
. = 1
if("blue")
. = 2
if("red")
. = 2
if("delta")
. = 2
return .
/mob/living/bot/cleanbot/lookForTargets()
for(var/obj/effect/decal/cleanable/D in view(world.view, src)) // There was some odd code to make it start with nearest decals, it's unnecessary, this works
if(confirmTarget(D))
+26
View File
@@ -300,6 +300,32 @@
else if(amount > maxAmount)
amount = maxAmount
/mob/living/bot/floorbot/handlePanic() // Speed modification based on alert level.
. = 0
switch(get_security_level())
if("green")
. = 0
if("yellow")
. = 0
if("violet")
. = 0
if("orange")
. = 1
if("blue")
. = 1
if("red")
. = 2
if("delta")
. = 2
return .
/* Assembly */
/obj/item/weapon/storage/toolbox/mechanical/attackby(var/obj/item/stack/tile/floor/T, mob/living/user as mob)
+26
View File
@@ -49,6 +49,32 @@
/mob/living/bot/medbot/handleAdjacentTarget()
UnarmedAttack(target)
/mob/living/bot/medbot/handlePanic() // Speed modification based on alert level.
. = 0
switch(get_security_level())
if("green")
. = 0
if("yellow")
. = 0
if("violet")
. = 1
if("orange")
. = 0
if("blue")
. = 1
if("red")
. = 2
if("delta")
. = 2
return .
/mob/living/bot/medbot/lookForTargets()
for(var/mob/living/carbon/human/H in view(7, src)) // Time to find a patient!
if(confirmTarget(H))
+32
View File
@@ -13,6 +13,8 @@
patrol_speed = 2
target_speed = 3
density = 1
var/default_icon_state = "secbot"
var/idcheck = FALSE // If true, arrests for having weapons without authorization.
var/check_records = FALSE // If true, arrests people without a record.
@@ -39,6 +41,8 @@
name = "Officer Beepsky"
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
will_patrol = TRUE
maxHealth = 130
health = 130
/mob/living/bot/secbot/slime
name = "Slime Securitron"
@@ -56,6 +60,8 @@
/mob/living/bot/secbot/slime/slimesky
name = "Doctor Slimesky"
desc = "An old friend of Officer Beep O'sky. He prescribes beatings to rowdy slimes so that real doctors don't need to treat the xenobiologists."
maxHealth = 130
health = 130
/mob/living/bot/secbot/update_icons()
if(on && busy)
@@ -219,6 +225,32 @@
global_announcer.autosay("[src] is [action] a level [threat] [action != "fighting" ? "suspect" : "threat"] <b>[target_name(target)]</b> in <b>[get_area(src)]</b>.", "[src]", "Security")
UnarmedAttack(target)
/mob/living/bot/secbot/handlePanic() // Speed modification based on alert level.
. = 0
switch(get_security_level())
if("green")
. = 0
if("yellow")
. = 0
if("violet")
. = 0
if("orange")
. = 0
if("blue")
. = 1
if("red")
. = 2
if("delta")
. = 2
return .
// So Beepsky talks while beating up simple mobs.
/mob/living/bot/secbot/proc/insult(var/mob/living/L)
if(can_next_insult > world.time)
@@ -419,6 +419,10 @@
// Called in life() when the mob has no client.
/datum/species/proc/handle_npc(var/mob/living/carbon/human/H)
if(H.stat == CONSCIOUS && H.ai_holder)
if(H.resting)
H.resting = FALSE
H.update_canmove()
return
// Called when lying down on a water tile.
@@ -50,8 +50,10 @@
if(H)
if(H.looksSynthetic())
return "flashing a 'system offline' light"
else
else if(!H.ai_holder)
return show_ssd
else
return
/datum/species/proc/get_blood_colour(var/mob/living/carbon/human/H)
if(H)
@@ -62,6 +62,8 @@
if(prob(1))
H.emote(pick("scratch","jump","roll","tail"))
..()
/datum/species/monkey/get_random_name()
return "[lowertext(name)] ([rand(100,999)])"
@@ -60,6 +60,8 @@ var/list/mob_hat_cache = list()
var/serial_number = 0
var/name_override = 0
var/foreign_droid = FALSE
holder_type = /obj/item/weapon/holder/drone
can_be_antagged = FALSE
@@ -118,7 +120,8 @@ var/list/mob_hat_cache = list()
updatename()
/mob/living/silicon/robot/drone/init()
aiCamera = new/obj/item/device/camera/siliconcam/drone_camera(src)
if(!scrambledcodes && !foreign_droid)
aiCamera = new/obj/item/device/camera/siliconcam/drone_camera(src)
additional_law_channels["Drone"] = ":d"
if(!laws) laws = new law_type
if(!module) module = new module_type(src)
@@ -253,10 +256,10 @@ var/list/mob_hat_cache = list()
//For some goddamn reason robots have this hardcoded. Redefining it for our fragile friends here.
/mob/living/silicon/robot/drone/updatehealth()
if(status_flags & GODMODE)
health = 35
health = maxHealth
stat = CONSCIOUS
return
health = 35 - (getBruteLoss() + getFireLoss())
health = maxHealth - (getBruteLoss() + getFireLoss())
return
//Easiest to check this here, then check again in the robot proc.
@@ -29,6 +29,9 @@
for(var/mob/living/silicon/robot/drone/D in mob_list)
if(D.z != src.z)
continue
if(D.foreign_droid)
continue
dat += "<BR>[D.real_name] ([D.stat == 2 ? "<font color='red'>INACTIVE</FONT>" : "<font color='green'>ACTIVE</FONT>"])"
dat += "<font dize = 9><BR>Cell charge: [D.cell.charge]/[D.cell.maxcharge]."
dat += "<BR>Currently located in: [get_area(D)]."
@@ -56,6 +56,22 @@
/obj/item/weapon/stock_parts
)
/obj/item/weapon/gripper/security
name = "security gripper"
desc = "A simple grasping tool for corporate security work."
icon_state = "gripper-sec"
can_hold = list(
/obj/item/weapon/paper,
/obj/item/weapon/paper_bundle,
/obj/item/weapon/pen,
/obj/item/weapon/sample,
/obj/item/weapon/forensics/sample_kit,
/obj/item/device/taperecorder,
/obj/item/device/tape,
/obj/item/device/uv_light
)
/obj/item/weapon/gripper/paperwork
name = "paperwork gripper"
desc = "A simple grasping tool for clerical work."
@@ -0,0 +1,98 @@
/mob/living/silicon/robot/drone/swarm
name = "swarm drone"
real_name = "drone"
icon = 'icons/mob/swarmbot.dmi'
icon_state = "swarmer"
faction = "swarmer"
maxHealth = 75
health = 75
cell_emp_mult = 0.5
universal_speak = 0
universal_understand = 1
gender = NEUTER
pass_flags = PASSTABLE
braintype = "Drone"
lawupdate = 0
density = 1
idcard_type = /obj/item/weapon/card/id/syndicate
req_access = list(999)
integrated_light_power = 3
local_transmit = 0
can_pull_size = ITEMSIZE_NO_CONTAINER
can_pull_mobs = MOB_PULL_SMALLER
can_enter_vent_with = list(
/obj)
mob_always_swap = 1
softfall = TRUE
mob_size = MOB_LARGE
law_type = /datum/ai_laws/swarm_drone
module_type = /obj/item/weapon/robot_module/drone/swarm
hat_x_offset = 0
hat_y_offset = -10
foreign_droid = TRUE
scrambledcodes = TRUE
holder_type = /obj/item/weapon/holder/drone
can_be_antagged = TRUE
var/spell_setup = list(
/spell/aoe_turf/conjure/swarmer,
/spell/aoe_turf/conjure/forcewall/swarm,
/spell/aoe_turf/blink/swarm,
/spell/aoe_turf/conjure/swarmer/gunner,
/spell/aoe_turf/conjure/swarmer/melee
)
/mob/living/silicon/robot/drone/swarm/Initialize()
..()
add_language(LANGUAGE_SWARMBOT, 1)
for(var/spell in spell_setup)
src.add_spell(new spell, "nano_spell_ready", /obj/screen/movable/spell_master/swarm)
/mob/living/silicon/robot/drone/swarm/init()
..()
QDEL_NULL(aiCamera)
flavor_text = "Some form of ancient machine."
/mob/living/silicon/robot/drone/swarm/gunner
name = "swarm gunner"
real_name = "drone"
icon = 'icons/mob/swarmbot.dmi'
icon_state = "swarmer_ranged"
faction = "swarmer"
law_type = /datum/ai_laws/swarm_drone/soldier
module_type = /obj/item/weapon/robot_module/drone/swarm/ranged
spell_setup = list(
/spell/aoe_turf/conjure/swarmer,
/spell/aoe_turf/conjure/forcewall/swarm,
/spell/aoe_turf/blink/swarm
)
/mob/living/silicon/robot/drone/swarm/melee
name = "swarm melee"
real_name = "drone"
icon = 'icons/mob/swarmbot.dmi'
icon_state = "swarmer_melee"
faction = "swarmer"
law_type = /datum/ai_laws/swarm_drone/soldier
module_type = /obj/item/weapon/robot_module/drone/swarm/melee
spell_setup = list(
/spell/aoe_turf/conjure/swarmer,
/spell/aoe_turf/conjure/forcewall/swarm,
/spell/aoe_turf/blink/swarm
)
@@ -0,0 +1,117 @@
/spell/aoe_turf/conjure/swarmer
name = "Self Replication"
desc = "This ability constructs a standard swarmer shell that may activate at some point."
school = "conjuration"
charge_max = 120 SECONDS
spell_flags = 0
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/structure/ghost_pod/ghost_activated/swarm_drone/event)
hud_state = "swarm_replicate"
/spell/aoe_turf/conjure/swarmer/conjure_animation(var/atom/movable/overlay/animation, var/turf/target)
animation.icon_state = "deflect_static"
flick("shield2",animation)
spawn(1 SECOND)
qdel(animation)
/spell/aoe_turf/conjure/forcewall/swarm
name = "Null-Field"
desc = "Create a bubble of null-point energy."
summon_type = list(/obj/effect/forcefield/swarm)
duration = 30 SECONDS
charge_max = 60 SECONDS
school = "conjuration"
invocation = "none"
invocation_type = SpI_NONE
range = 0
hud_state = "wiz_shield"
/obj/effect/forcefield/swarm
desc = "A pocket of strange energy."
name = "Null-Field"
icon = 'icons/effects/effects.dmi'
icon_state = "shield-old"
invisibility = 0
/spell/aoe_turf/conjure/zeropointwell
name = "Zero-Point Well"
desc = "This ability constructs a standard zero-point energy well, capable of charging nearby swarmers."
school = "conjuration"
charge_max = 120 SECONDS
spell_flags = 0
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/structure/cult/pylon/swarm/zp_well)
hud_state = "swarm_zeropoint"
/spell/aoe_turf/conjure/zeropointbarricade
name = "Zero-Point Barricade"
desc = "This ability constructs a standard zero-point energy wall, used to create a secure passageway for allies, and a bastion for defense."
school = "conjuration"
charge_max = 120 SECONDS
spell_flags = 0
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/structure/cult/pylon/swarm/defender)
hud_state = "swarm_barricade"
/spell/aoe_turf/blink/swarm
name = "Warp"
desc = "Your null-point drive jaunts you to a new location."
school = "abjuration"
charge_max = 5 MINUTES
spell_flags = Z2NOCAST | IGNOREDENSE
invocation = "none"
invocation_type = SpI_NONE
range = 10
inner_radius = 5
hud_state = "swarm_warp"
/spell/aoe_turf/conjure/swarmer/gunner
name = "Generate Gunner"
desc = "This spell constructs a gunner swarmer shell that may activate at some point."
school = "conjuration"
charge_type = Sp_CHARGES
charge_max = 1
spell_flags = 0
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/gunner)
hud_state = "swarm_replicate"
/spell/aoe_turf/conjure/swarmer/melee
name = "Generate Impaler"
desc = "This spell constructs an impaler swarmer shell that may activate at some point."
school = "conjuration"
charge_type = Sp_CHARGES
charge_max = 1
spell_flags = 0
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/melee)
hud_state = "swarm_replicate"
@@ -0,0 +1,162 @@
//Swarm Assimilator / Breacher
/obj/item/weapon/matter_decompiler/swarm
name = "matter assimilator"
desc = "Used to eat some forms of simple machinery; and large, wall-shaped blocks of metal with energetic fields."
icon = 'icons/obj/device.dmi'
icon_state = "decompiler_swarm"
var/field_cooldown = 1 MINUTE
var/last_field = 0
/obj/item/weapon/matter_decompiler/swarm/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
if(!proximity) return //Not adjacent.
//We only want to deal with using this on turfs. Specific items aren't important.
var/turf/T = get_turf(target)
if(!istype(T))
return
//Used to give the right message.
var/grabbed_something = FALSE
for(var/mob/M in T)
if(istype(M,/mob/living/simple_mob/animal/passive/lizard) || istype(M,/mob/living/simple_mob/animal/passive/mouse))
src.loc.visible_message("<span class='danger'>[src.loc] sucks [M] into its decompiler. There's a horrible crunching noise.</span>","<span class='danger'>It's a bit of a struggle, but you manage to suck [M] into your decompiler. It makes a series of visceral crunching noises.</span>")
new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
qdel(M)
if(wood)
wood.add_charge(2000)
if(plastic)
plastic.add_charge(2000)
return
else if(istype(M,/mob/living/silicon/robot/drone) && !M.client)
var/mob/living/silicon/robot/D = src.loc
if(!istype(D))
return
to_chat(D, "<span class='danger'>You begin decompiling [M].</span>")
if(!do_after(D,50))
to_chat(D, "<span class='danger'>You need to remain still while decompiling such a large object.</span>")
return
if(!M || !D) return
to_chat(D, "<span class='danger'>You carefully and thoroughly decompile [M], storing as much of its resources as you can within yourself.</span>")
qdel(M)
new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
if(metal)
metal.add_charge(15000)
if(glass)
glass.add_charge(15000)
if(wood)
wood.add_charge(2000)
if(plastic)
plastic.add_charge(1000)
return
else
continue
for(var/obj/W in T)
//Different classes of items give different commodities.
if(istype(W,/obj/structure/girder))
if(metal)
metal.add_charge(500)
else if(istype(W,/obj/machinery/power/emitter))
if(metal)
metal.add_charge(3000)
if(plastic)
plastic.add_charge(1000)
else if(istype(W,/obj/machinery/space_heater))
if(metal)
metal.add_charge(1500)
if(plastic)
plastic.add_charge(750)
else if(istype(W,/obj/structure/closet))
var/obj/structure/closet/C = W
if(!C.opened)
continue
if(istype(W,/obj/structure/closet/coffin))
if(wood)
wood.add_charge(1000)
else if(istype(W,/obj/structure/closet/crate/plastic))
if(plastic)
plastic.add_charge(750)
else
if(metal)
metal.add_charge(1000)
else
continue
qdel(W)
grabbed_something = TRUE
if(istype(T,/turf/simulated/wall) && (last_field < world.time + field_cooldown))
if(!(locate(/obj/effect/temporary_effect/pulse/disintegrate)))
last_field = world.time
to_chat(user, "<span class='alien'>You deploy an energetic field through \the [T], beginning its deconstruction.</span>")
to_chat(user, "<span class='warning'>You should stand back.</span>")
new /obj/effect/temporary_effect/pulse/disintegrate(T)
else
to_chat(user, "<span class='notice'>There is already a disintigration field affecting \the [T].</span>")
if(grabbed_something)
to_chat(user, "<span class='notice'>You deploy your decompiler and clear out the contents of \the [T].</span>")
else
to_chat(user, "<span class='danger'>Nothing on \the [T] is useful to you.</span>")
return
/obj/effect/temporary_effect/pulse/disintegrate
name = "molecular debonding field"
desc = "This is something you do not want to near."
icon = 'icons/mob/swarmbot.dmi'
icon_state = "disintegrate_pulse"
light_range = 4
light_power = 5
light_color = "#00B4D9"
pulses_remaining = 5
pulse_delay = 2 SECONDS
/obj/effect/temporary_effect/pulse/disintegrate/emp_act()
visible_message("<span class='warning'>\The [src] flickers, before dispersing energetically.</span>")
qdel(src)
/obj/effect/temporary_effect/pulse/disintegrate/on_pulse()
var/turf/T = get_turf(src)
if(istype(T,/turf/simulated/wall))
explosion(get_turf(src), -1, -1, 1, 3, adminlog = 0)
else
qdel(src)
/obj/effect/temporary_effect/pulse/disintegrate/Destroy()
if(istype(get_turf(src), /turf/simulated/wall))
explosion(get_turf(src), -1, 1, 2, 5, adminlog = 1)
..()
/obj/item/weapon/gun/energy/xray/swarm
name = "spectral projector"
desc = "A high-power laser gun capable of expelling concentrated gamma blasts, which are able to penetrate matter easier than \
standard xray beams, resulting in an effective 'anti-everything' energy weapon."
icon_state = "xray"
item_state = "xray"
origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 3, TECH_MAGNET = 2)
projectile_type = /obj/item/projectile/beam/shock
charge_cost = 175
self_recharge = TRUE
use_external_power = TRUE
firemodes = list(
list(mode_name="kill", projectile_type=/obj/item/projectile/beam/gamma, charge_cost = 300),
list(mode_name="deter", projectile_type=/obj/item/projectile/beam/shock, charge_cost = 175),
)
/obj/item/weapon/gun/energy/xray/swarm/Initialize()
..()
adjust_scale(-1, 1)
@@ -521,6 +521,7 @@ var/global/list/robot_modules = list(
src.modules += new /obj/item/weapon/gun/energy/taser/xeno/sec/robot(src)
src.modules += new /obj/item/taperoll/police(src)
src.modules += new /obj/item/weapon/reagent_containers/spray/pepper(src)
src.modules += new /obj/item/weapon/gripper/security(src)
src.emag = new /obj/item/weapon/gun/energy/laser/mounted(src)
/obj/item/weapon/robot_module/robot/security/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
@@ -0,0 +1,29 @@
/obj/item/weapon/robot_module/drone/swarm
name = "swarm drone module"
var/id
/obj/item/weapon/robot_module/drone/swarm/New(var/mob/living/silicon/robot/robot)
..()
id = robot.idcard
src.modules += id
src.modules += new /obj/item/weapon/rcd/electric/mounted/borg/swarm(src)
src.modules += new /obj/item/device/flash/robot(src)
src.modules += new /obj/item/weapon/handcuffs/cable/tape/cyborg(src)
src.modules += new /obj/item/weapon/melee/baton/robot(src)
src.modules += new /obj/item/weapon/gun/energy/taser/mounted/cyborg/swarm(src)
src.modules += new /obj/item/weapon/matter_decompiler/swarm(src)
/obj/item/weapon/robot_module/drone/swarm/ranged
name = "swarm gunner module"
/obj/item/weapon/robot_module/drone/swarm/ranged/New(var/mob/living/silicon/robot/robot)
..()
src.modules += new /obj/item/weapon/gun/energy/xray/swarm(src)
/obj/item/weapon/robot_module/drone/swarm/melee/New(var/mob/living/silicon/robot/robot)
..()
src.modules += new /obj/item/weapon/melee/energy/sword/ionic_rapier/lance(src)
@@ -117,3 +117,17 @@
if(prob(poison_chance))
to_chat(L, "<span class='warning'>You feel a tiny prick.</span>")
L.reagents.add_reagent(poison_type, poison_per_bite)
/mob/living/simple_mob/animal/giant_spider/proc/make_spiderling()
adjust_scale(icon_scale_x * 0.7, icon_scale_y * 0.7)
maxHealth = round(maxHealth * 0.5)
health = round(health * 0.5)
melee_damage_lower *= 0.7
melee_damage_upper *= 0.7
response_harm = "kicks"
see_in_dark = max(2, round(see_in_dark * 0.6))
if(poison_per_bite)
poison_per_bite *= 1.3
@@ -22,3 +22,23 @@
speak_emote = list("hisses")
say_list_type = /datum/say_list/lizard
/mob/living/simple_mob/animal/passive/lizard/large
desc = "A cute, big lizard."
maxHealth = 20
health = 20
melee_damage_lower = 5
melee_damage_upper = 15
attack_sharp = TRUE
/mob/living/simple_mob/animal/passive/lizard/large/Initialize()
..()
adjust_scale(rand(12, 20) / 10)
/mob/living/simple_mob/animal/passive/lizard/large/defensive
maxHealth = 30
health = 30
ai_holder_type = /datum/ai_holder/simple_mob/retaliate/cooperative
@@ -97,6 +97,17 @@
body_color = "brown"
icon_state = "mouse_brown"
/mob/living/simple_mob/animal/passive/mouse/rat
name = "rat"
maxHealth = 20
health = 20
ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive
/mob/living/simple_mob/animal/passive/mouse/rat/Initialize()
..()
adjust_scale(1.2)
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_mob/animal/passive/mouse/brown/Tom
name = "Tom"
+14
View File
@@ -425,6 +425,20 @@ proc/is_blind(A)
lname = "<span class='name'>[lname]</span> "
M << "<span class='deadsay'>" + create_text_tag("dead", "DEAD:", M.client) + " [lname][follow][message]</span>"
/proc/say_dead_object(var/message, var/obj/subject = null)
for(var/mob/M in player_list)
if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights)) && M.is_preference_enabled(/datum/client_preference/show_dsay))
var/follow
var/lname = "Game Master"
if(M.forbid_seeing_deadchat && !M.client.holder)
continue
if(subject)
lname = "[subject.name] ([subject.x],[subject.y],[subject.z])"
lname = "<span class='name'>[lname]</span> "
M << "<span class='deadsay'>" + create_text_tag("event_dead", "EVENT:", M.client) + " [lname][follow][message]</span>"
//Announces that a ghost has joined/left, mainly for use with wizards
/proc/announce_ghost_joinleave(O, var/joined_ghosts = 1, var/message = "")
var/client/C