mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-09 16:14:13 +00:00
Unfucks zombies (#13101)
* Unfucks zombies * MAGIC FUCKING NUMBERS * MAGIC_FUCKING_NUMBERS * Apparently we don't use that file * Good spots by comic
This commit is contained in:
@@ -66,3 +66,9 @@
|
||||
#define LIGHT_COLOR_SLIME_LAMP "#AFC84B" //Weird color, between yellow and green, very slimy. rgb(175, 200, 75)
|
||||
#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" //Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175)
|
||||
#define LIGHT_COLOR_HALOGEN "#F0FAFA" //Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250)
|
||||
|
||||
//Defines for lighting status, see power/lighting.dm
|
||||
#define LIGHT_OK 0
|
||||
#define LIGHT_EMPTY 1
|
||||
#define LIGHT_BROKEN 2
|
||||
#define LIGHT_BURNED 3
|
||||
@@ -101,7 +101,7 @@ var/global/list/spider_types = typesof(/mob/living/simple_animal/hostile/giant_s
|
||||
if(istype(the_target,/obj/machinery/light))
|
||||
var/obj/machinery/light/L = the_target
|
||||
// Not empty or broken
|
||||
return L.status != 1 && L.status != 2
|
||||
return L.status != LIGHT_EMPTY && L.status != LIGHT_BROKEN
|
||||
return ..(the_target)
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/proc/CanOpenDoor(var/obj/machinery/door/D)
|
||||
|
||||
@@ -1,6 +1,33 @@
|
||||
/mob/living/simple_animal/hostile/necro
|
||||
var/mob/creator
|
||||
var/unique_name = 0
|
||||
faction = "necro"
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/New(loc, mob/living/Owner, datum/mind/Controller)
|
||||
..()
|
||||
if(Owner)
|
||||
faction = "\ref[Owner]"
|
||||
friends.Add(Owner)
|
||||
creator = Owner
|
||||
if(Controller)
|
||||
mind = Controller
|
||||
ckey = ckey(mind.key)
|
||||
to_chat(src, "<big><span class='warning'>You have been risen from the dead by your new master, [Owner]. Do his bidding so long as he lives, for when he falls so do you.</span></big>")
|
||||
var/ref = "\ref[Owner.mind]"
|
||||
var/list/necromancers
|
||||
if(!(Owner.mind in ticker.mode.necromancer))
|
||||
ticker.mode:necromancer[ref] = list()
|
||||
necromancers = ticker.mode:necromancer[ref]
|
||||
necromancers.Add(Controller)
|
||||
ticker.mode:necromancer[ref] = necromancers
|
||||
ticker.mode.update_necro_icons_added(Owner.mind)
|
||||
ticker.mode.update_necro_icons_added(Controller)
|
||||
ticker.mode.update_all_necro_icons()
|
||||
ticker.mode.risen.Add(Controller)
|
||||
|
||||
if(name == initial(name) && !unique_name)
|
||||
name += " ([rand(1,1000)])"
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/skeleton
|
||||
name = "skeleton"
|
||||
desc = "Truly the ride never ends."
|
||||
@@ -39,12 +66,14 @@
|
||||
|
||||
environment_smash = 1
|
||||
meat_type = null
|
||||
|
||||
/*
|
||||
#define EVOLVING 1
|
||||
#define MOVING_TO_TARGET 2
|
||||
#define EATING 3
|
||||
#define OPENING_DOOR 4
|
||||
//#define SMASHING_LIGHT 5
|
||||
#define SMASHING_LIGHT 5*/
|
||||
|
||||
#define MAX_EAT_MULTIPLIER 4 //Dead for humans is -maxHealth, uncloneable is -maxHealth * 2
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/zombie //Boring ol default zombie
|
||||
name = "zombie"
|
||||
@@ -73,6 +102,7 @@
|
||||
melee_damage_upper = 20
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
stat_attack = DEAD
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
@@ -89,7 +119,7 @@
|
||||
var/times_revived //Tracks how many times the zombie has regenerated from death
|
||||
var/times_eaten //Tracks how many times the zombie has chewed on a human corpse
|
||||
var/can_evolve = FALSE //False if we don't want it to evolve
|
||||
var/busy //If the zombie is busy, and what it's busy doing
|
||||
//var/busy //If the zombie is busy, and what it's busy doing
|
||||
|
||||
#define CANT 0
|
||||
#define CAN 1
|
||||
@@ -99,44 +129,67 @@
|
||||
|
||||
var/break_doors = CANT //If CAN, they can attempt to open doors. If CANPLUS, they break the door down entirely
|
||||
var/health_cap = 250 //Maximum possible health it can have. Because screw having a 1000 health mob
|
||||
/* wanted_objects = list(
|
||||
/obj/machinery/light, // Bust out lights
|
||||
var/busy = FALSE //Stop spamming the damn doorsmash
|
||||
wanted_objects = list(
|
||||
/obj/machinery/light,
|
||||
/obj/machinery/door // Bust out lights
|
||||
)
|
||||
search_objects = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/zombie/CanAttack(var/atom/the_target)
|
||||
if(the_target == creator)
|
||||
return 0
|
||||
if(ismob(the_target))
|
||||
var/mob/living/M = the_target
|
||||
if(ishuman(the_target)) //Checking for food
|
||||
var/mob/living/carbon/human/H = the_target
|
||||
if(H.isDead())
|
||||
if(check_edibility(H))
|
||||
return the_target
|
||||
else
|
||||
return 0
|
||||
else
|
||||
return ..(the_target)
|
||||
else
|
||||
if(M.isDead())
|
||||
return 0
|
||||
|
||||
if(istype(the_target,/obj/machinery/door)) //Checking for doors
|
||||
var/obj/machinery/door/D = the_target
|
||||
if(can_open_door(D))
|
||||
return the_target
|
||||
else
|
||||
return 0
|
||||
if(istype(the_target,/obj/machinery/light))
|
||||
var/obj/machinery/light/L = the_target
|
||||
// Not empty or broken
|
||||
return L.status != 1 && L.status != 2
|
||||
return ..(the_target)*/ //Too buggy, gets caught on terrain way too much
|
||||
return L.status != LIGHT_EMPTY && L.status != LIGHT_BROKEN
|
||||
|
||||
return ..(the_target)
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/zombie/AttackingTarget()
|
||||
if(!target)
|
||||
return
|
||||
|
||||
if(target == creator)
|
||||
return
|
||||
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(H.isDead() && check_edibility(H))
|
||||
eat(H)
|
||||
return 0
|
||||
|
||||
if(istype (target, /obj/machinery/door))
|
||||
var/obj/machinery/door/D = target
|
||||
if(can_open_door(D))
|
||||
force_door(D)
|
||||
return 0
|
||||
|
||||
return..()
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/New(loc, mob/living/Owner, datum/mind/Controller)
|
||||
..()
|
||||
if(Owner)
|
||||
faction = "\ref[Owner]"
|
||||
friends.Add(Owner)
|
||||
if(Controller)
|
||||
mind = Controller
|
||||
ckey = ckey(mind.key)
|
||||
to_chat(src, "<big><span class='warning'>You have been risen from the dead by your new master, [Owner]. Do his bidding so long as he lives, for when he falls so do you.</span></big>")
|
||||
var/ref = "\ref[Owner.mind]"
|
||||
var/list/necromancers
|
||||
if(!(Owner.mind in ticker.mode.necromancer))
|
||||
ticker.mode:necromancer[ref] = list()
|
||||
necromancers = ticker.mode:necromancer[ref]
|
||||
necromancers.Add(Controller)
|
||||
ticker.mode:necromancer[ref] = necromancers
|
||||
ticker.mode.update_necro_icons_added(Owner.mind)
|
||||
ticker.mode.update_necro_icons_added(Controller)
|
||||
ticker.mode.update_all_necro_icons()
|
||||
ticker.mode.risen.Add(Controller)
|
||||
|
||||
if(name == initial(name) && !unique_name)
|
||||
name += " ([rand(1,1000)])"
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/zombie/Life()
|
||||
..()
|
||||
/*TODONE
|
||||
First, check if the zombie can potentially evolve
|
||||
Have the zombie move to a corpse and start chewing at it
|
||||
@@ -145,12 +198,10 @@
|
||||
*/
|
||||
if(!isUnconscious())
|
||||
if(stance == HOSTILE_STANCE_IDLE && !client) //Not doing anything at the time
|
||||
var/list/can_see = view(src, vision_range)
|
||||
if(!busy)
|
||||
if(can_evolve)//Can we evolve, and have we fed
|
||||
busy = EVOLVING
|
||||
check_evolve()
|
||||
busy = 0
|
||||
if(can_evolve)//Can we evolve, and have we fed
|
||||
check_evolve()
|
||||
..()
|
||||
/*
|
||||
if((health < maxHealth) || (maxHealth < health_cap) && !busy)
|
||||
var/mob/living/carbon/human/C = find_food(can_see)//Is there something to eat in range?
|
||||
if(C) //If so, chow down
|
||||
@@ -162,6 +213,7 @@
|
||||
eat(C)
|
||||
C = null
|
||||
walk(src, 0)
|
||||
|
||||
if(!busy && break_doors != CANT)//So we don't try to eat and open doors
|
||||
var/obj/machinery/door/D = find_door(can_see)//Is there a door to open in range?
|
||||
if(D)
|
||||
@@ -173,13 +225,13 @@
|
||||
force_door(D)
|
||||
D = null
|
||||
walk(src, 0)
|
||||
|
||||
else
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
else
|
||||
walk(src,0)
|
||||
|
||||
*/
|
||||
/*
|
||||
/mob/living/simple_animal/hostile/necro/zombie/proc/find_food(var/list/can_see)
|
||||
for(var/mob/living/carbon/human/C in can_see) //Because of how can_see lists things, it'll go in order of closest to furthest
|
||||
if(C.isDead() && check_edibility(C))
|
||||
@@ -198,7 +250,10 @@
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
walk(src,0)
|
||||
*/
|
||||
/mob/living/simple_animal/hostile/necro/zombie/proc/can_open_door(var/obj/machinery/door/D)
|
||||
if(busy) //Already smashing a door or eating something
|
||||
return 0
|
||||
if((istype(D,/obj/machinery/door/poddoor) || istype(D, /obj/machinery/door/airlock/multi_tile/glass) || istype(D, /obj/machinery/door/window)) && !client)
|
||||
return 0
|
||||
if(break_doors == CANT)//Moreso used for when a player-controlled zombie attempts to forceopen a door
|
||||
@@ -236,47 +291,57 @@
|
||||
D.visible_message("<span class='warning'>\The [D]'s motors whine as something attempts to brute force their way through it!</span>")
|
||||
playsound(get_turf(D), 'sound/effects/grillehit.ogg', 50, 1)
|
||||
D.shake(1, 8)
|
||||
if(do_after(src, D, 100*time_mult, needhand = FALSE)) //Roughly 10 seconds for people on the other side of the door to run the heck away
|
||||
if(can_open_door(D))//Let's see if nobody quickly bolted it
|
||||
if(break_doors == CANPLUS) //Guaranteed
|
||||
D.visible_message("<span class='warning'>\The [D] breaks open under the pressure</span>")
|
||||
if(istype(D, /obj/machinery/door/airlock/))
|
||||
var/obj/machinery/door/airlock/A = D
|
||||
A.locked = 0
|
||||
A.welded = 0
|
||||
A.jammed = 0
|
||||
D.open(1)
|
||||
else
|
||||
if(prob(33))
|
||||
D.visible_message("<span class='warning'>\The [D] creaks open under force, steadily</span>")
|
||||
busy = TRUE
|
||||
var/target_loc = D.loc
|
||||
var/self_loc = src.loc
|
||||
spawn(10 SECONDS*time_mult)
|
||||
if(D.loc == target_loc && self_loc == src.loc) //Not moved
|
||||
if(can_open_door(D))//Let's see if nobody quickly bolted it
|
||||
if(break_doors == CANPLUS) //Guaranteed
|
||||
D.visible_message("<span class='warning'>\The [D] breaks open under the pressure</span>")
|
||||
if(istype(D, /obj/machinery/door/airlock/))
|
||||
var/obj/machinery/door/airlock/A = D
|
||||
A.locked = 0
|
||||
A.welded = 0
|
||||
A.jammed = 0
|
||||
D.open(1)
|
||||
busy = 0
|
||||
else
|
||||
if(prob(33))
|
||||
D.visible_message("<span class='warning'>\The [D] creaks open under force, steadily</span>")
|
||||
D.open(1)
|
||||
else
|
||||
playsound(get_turf(D), 'sound/effects/grillehit.ogg', 50, 1)
|
||||
D.shake(1, 8)
|
||||
busy = FALSE
|
||||
stop_automated_movement = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/zombie/proc/check_edibility(var/mob/living/carbon/human/target)
|
||||
if(!(target.isDead()))
|
||||
return 0 //It ain't dead
|
||||
if(isjusthuman(target)) //Humans are always edible
|
||||
return 1
|
||||
if(target.health > -400) //So they're not caught eating the same dumb bird all day
|
||||
return 1
|
||||
if(busy)
|
||||
return 0
|
||||
if((health < maxHealth) || (maxHealth < health_cap))
|
||||
if(!(target.isDead()))
|
||||
return 0 //It ain't dead
|
||||
if(isjusthuman(target)) //Humans are always edible
|
||||
return 1
|
||||
if(target.health > -(target.maxHealth*MAX_EAT_MULTIPLIER)) //So they're not caught eating the same dumb bird all day
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/zombie/proc/eat(var/mob/living/carbon/human/target)
|
||||
//Deal a random amount of brute damage to the corpse in question, heal the zombie by the damage dealt halved
|
||||
visible_message("<span class='notice'>\The [src] starts to take a bite out of \the [target].</span>")
|
||||
visible_message("<span class='warning'>\The [src] takes a bite out of \the [target].</span>")
|
||||
busy = TRUE
|
||||
stop_automated_movement = 1
|
||||
if(do_after(src, target, 50, needhand = FALSE))
|
||||
playsound(get_turf(src), 'sound/weapons/bite.ogg', 50, 1)
|
||||
var/damage = rand(melee_damage_lower, melee_damage_upper)
|
||||
target.adjustBruteLoss(damage)
|
||||
health = min(maxHealth, health+damage)
|
||||
if(maxHealth < health_cap)
|
||||
maxHealth += 5 //A well fed zombie is a scary zombie
|
||||
times_eaten += 1
|
||||
playsound(get_turf(src), 'sound/weapons/bite.ogg', 50, 1)
|
||||
var/damage = rand(melee_damage_lower, melee_damage_upper)
|
||||
target.adjustBruteLoss(damage)
|
||||
if(maxHealth < health_cap)
|
||||
maxHealth += 5 //A well fed zombie is a scary zombie
|
||||
health = min(maxHealth, health+damage)
|
||||
times_eaten += 1
|
||||
busy = FALSE
|
||||
stop_automated_movement = 0
|
||||
busy = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/zombie/proc/check_evolve()
|
||||
if(!can_evolve) //How did you get here if not?
|
||||
@@ -311,8 +376,11 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/zombie/proc/evolve(var/mob/living/simple_animal/evolve_to)
|
||||
if(ispath(evolve_to, /mob/living/simple_animal/hostile/necro))
|
||||
var/mob/living/evolution = new evolve_to(src.loc,,)
|
||||
var/mob/living/simple_animal/hostile/necro/evolution = new evolve_to(src.loc,,)
|
||||
evolution.name = name //We want to keep the name
|
||||
evolution.inherit_mind(src)
|
||||
evolution.creator = creator
|
||||
evolution.friends = friends.Copy()
|
||||
if(mind)
|
||||
mind.transfer_to(evolution) //Just in the offchance we have a player in control
|
||||
qdel(src)
|
||||
@@ -326,6 +394,9 @@
|
||||
times_revived += 1
|
||||
|
||||
/mob/living/simple_animal/hostile/necro/zombie/UnarmedAttack(atom/A) //There's got to be a better way to keep everything together
|
||||
if(A == creator) //Evil necromancy magic means no attacking our creator
|
||||
to_chat(src, "Try as you might, you can't bring yourself to attack [A]")
|
||||
return
|
||||
..()
|
||||
if(istype(A, /obj/machinery/door))
|
||||
if(can_open_door(A))
|
||||
|
||||
@@ -2,13 +2,6 @@
|
||||
//
|
||||
// consists of light fixtures (/obj/machinery/light) and light tube/bulb items (/obj/item/weapon/light)
|
||||
|
||||
// status values shared between lighting fixtures and items
|
||||
#define LIGHT_OK 0
|
||||
#define LIGHT_EMPTY 1
|
||||
#define LIGHT_BROKEN 2
|
||||
#define LIGHT_BURNED 3
|
||||
|
||||
|
||||
/obj/machinery/light_construct
|
||||
name = "light fixture frame"
|
||||
desc = "A light fixture under construction."
|
||||
|
||||
Reference in New Issue
Block a user