Zombies upgrade (#17366)

* step 0

* sdad

* asdfsad

* safsad

* actual sprites for the bull from whitewolftamer

* Apply suggestions from code review

Co-authored-by: Cody Brittain <cbrittain10@yahoo.com>

* Update html/changelogs/fluffyghost-zombieupgrade.yml

Co-authored-by: Cody Brittain <cbrittain10@yahoo.com>

* sisyphus

---------

Co-authored-by: Cody Brittain <cbrittain10@yahoo.com>
This commit is contained in:
Fluffy
2023-10-17 21:05:27 +00:00
committed by GitHub
co-authored by Cody Brittain
parent c69513fa3f
commit f966e50ce1
22 changed files with 392 additions and 45 deletions
@@ -95,8 +95,6 @@
sync_organ_dna()
make_blood()
available_maneuvers = species.maneuvers.Copy()
pixel_x = species.icon_x_offset
pixel_y = species.icon_y_offset
@@ -1441,6 +1439,11 @@
if(species.holder_type)
holder_type = species.holder_type
//Clear out the manouvers of the previous specie and add the one of the current specie
available_maneuvers = null
if(species?.maneuvers)
available_maneuvers = species.maneuvers.Copy()
icon_state = lowertext(species.name)
species.create_organs(src)
@@ -257,7 +257,7 @@
var/hit_dam_type = attack.damage_type
var/damage_flags = attack.damage_flags()
real_damage += attack.get_unarmed_damage(H)
real_damage += attack.get_unarmed_damage(src, H)
real_damage *= damage_multiplier
rand_damage *= damage_multiplier
@@ -384,6 +384,8 @@ This function restores all organs.
/mob/living/carbon/human/proc/get_organ(var/zone, var/allow_no_result = FALSE)
SHOULD_NOT_SLEEP(TRUE)
RETURN_TYPE(/obj/item/organ)
if(!zone)
if(allow_no_result)
return
@@ -80,7 +80,7 @@
stamina = 500 //Tireless automatons
stamina_recovery = 1
sprint_speed_factor = 0.3
exhaust_threshold = 0 //No oxyloss, so zero threshold
exhaust_threshold = 10
max_nutrition_factor = -1
@@ -164,8 +164,6 @@
unarmed_types = list(/datum/unarmed_attack/bite/infectious, /datum/unarmed_attack/claws/strong/zombie)
darksight = 8
slowdown = 0.5
has_fine_manipulation = FALSE
speech_sounds = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg')
@@ -194,11 +192,11 @@
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/zombie)
)
total_health = 100
total_health = 80
slowdown = 2
vision_flags = DEFAULT_SIGHT | SEE_MOBS
vision_flags = DEFAULT_SIGHT
reagent_tag = IS_UNDEAD
@@ -219,7 +217,7 @@
stamina = 500 //Tireless automatons
stamina_recovery = 1
sprint_speed_factor = 0.1
exhaust_threshold = 0 //No oxyloss, so zero threshold
exhaust_threshold = 10
inherent_verbs = list(/mob/living/carbon/human/proc/darkness_eyes)
@@ -235,6 +233,17 @@
H.accent = ACCENT_BLUESPACE
return ..()
//Zombies do not have oxygen, so we have to handle the sprint this way
/datum/species/zombie/handle_sprint_cost(var/mob/living/carbon/human/H, var/cost, var/pre_move)
. = ..()
if(exhaust_threshold && (H.stamina) < (exhaust_threshold * 0.8))
H.m_intent = M_WALK
H.hud_used.move_intent.update_move_icon(H)
to_chat(H, SPAN_DANGER("You're too exhausted to run anymore!"))
H.flash_pain(H.get_shock())
return 0
/datum/species/zombie/tajara
name = SPECIES_ZOMBIE_TAJARA
name_plural = "Tajara Zombies"
@@ -311,3 +320,99 @@
dust_remains_type = /obj/effect/decal/remains/xeno/burned
default_h_style = "Skrell Short Tentacles"
///A zombie tuned for tankness
/datum/species/zombie/bull
name = SPECIES_ZOMBIE_BULL
name_plural = SPECIES_ZOMBIE_BULL+"s"
icobase = 'icons/mob/human_races/zombie/r_zombie_bull.dmi'
deform = 'icons/mob/human_races/zombie/r_zombie_bull.dmi'
total_health = 300
allowed_eat_types = TYPE_ORGANIC | TYPE_HUMANOID | TYPE_SYNTHETIC | TYPE_WEIRD
gluttonous = GLUT_ANYTHING
stomach_capacity = 10
stamina = 50
sprint_speed_factor = 0.9
slowdown = 2
exhaust_threshold = 20
bump_flag = HEAVY
species_height = HEIGHT_CLASS_TALL
natural_armor = list(
ballistic = ARMOR_BALLISTIC_RIFLE,
laser = ARMOR_LASER_MEDIUM,
melee = ARMOR_MELEE_MAJOR,
bomb = null,
energy = ARMOR_ENERGY_RESISTANT
)
unarmed_types = list(/datum/unarmed_attack/bite/infectious)
///A zombie tuned to hunt preys
/datum/species/zombie/hunter
name = SPECIES_ZOMBIE_HUNTER
name_plural = SPECIES_ZOMBIE_HUNTER+"s"
icobase = 'icons/mob/human_races/zombie/r_zombie_hunter.dmi'
deform = 'icons/mob/human_races/zombie/r_zombie_hunter.dmi'
slowdown = 2
total_health = 90
stamina = 40
sprint_speed_factor = 0.9
slowdown = -2
standing_jump_range = 5
natural_climbing = TRUE
vision_flags = SEE_SELF | SEE_MOBS
hearing_sensitivity = HEARING_VERY_SENSITIVE
natural_armor = list(
ballistic = ARMOR_BALLISTIC_MEDIUM,
laser = ARMOR_LASER_PISTOL,
melee = ARMOR_MELEE_MAJOR,
bomb = ARMOR_BOMB_PADDED,
energy = ARMOR_ENERGY_SMALL
)
unarmed_types = list(/datum/unarmed_attack/shocking) //This zombie cannot infect, it's an harrass type of zombie
///A zombie tuned for charge attacks
/datum/species/zombie/rhino
name = SPECIES_ZOMBIE_RHINO
name_plural = SPECIES_ZOMBIE_RHINO+"s"
icobase = 'icons/mob/human_races/zombie/r_zombie_rhino.dmi'
deform = 'icons/mob/human_races/zombie/r_zombie_rhino.dmi'
slowdown = 2
total_health = 120
stamina = 50
sprint_speed_factor = 0.7
standing_jump_range = 5
vision_flags = SEE_SELF
bump_flag = HEAVY
push_flags = HEAVY
mob_size = MOB_LARGE
grab_mod = 5
natural_armor = list(
ballistic = ARMOR_BALLISTIC_MEDIUM,
laser = ARMOR_LASER_PISTOL,
melee = ARMOR_MELEE_MAJOR,
bomb = ARMOR_BOMB_PADDED,
energy = ARMOR_ENERGY_SMALL
)
maneuvers = list(/singleton/maneuver/leap/areagrab)
unarmed_types = list(/datum/unarmed_attack/bite/infectious, /datum/unarmed_attack/golem)
@@ -98,7 +98,7 @@
attack_verb = list("jumped on")
attack_name = "weak stomp"
/datum/unarmed_attack/stomp/weak/get_unarmed_damage()
/datum/unarmed_attack/stomp/weak/get_unarmed_damage(var/mob/attacker, var/mob/living/carbon/human/target)
return damage
/datum/unarmed_attack/stomp/weak/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
@@ -212,6 +212,12 @@
var/trioxin_amount = REAGENT_VOLUME(target.reagents, /singleton/reagent/toxin/trioxin)
target.reagents.add_reagent(/singleton/reagent/toxin/trioxin, min(10, ZOMBIE_MAX_TRIOXIN - trioxin_amount))
/datum/unarmed_attack/bite/infectious/get_unarmed_damage(var/mob/attacker, var/target)
if(istype(target, /mob/living/heavy_vehicle))
return damage * 4
. = ..()
/datum/unarmed_attack/golem
attack_verb = list("smashed", "crushed", "rammed")
attack_noun = list("fist")
@@ -44,7 +44,16 @@ var/global/list/sparring_attack_cache = list()
return FALSE
/datum/unarmed_attack/proc/get_unarmed_damage()
/**
* Returns the unarmed damage of an attack, aka what damage the attack does if there's no objects involved
*
* * attacker - The `/mob` that is performing the attack
* * target - The target of the attack, aka who is being attacked/damaged
*/
/datum/unarmed_attack/proc/get_unarmed_damage(var/mob/attacker, var/target)
SHOULD_BE_PURE(TRUE)
SHOULD_NOT_SLEEP(TRUE)
return damage
/datum/unarmed_attack/proc/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/attack_damage,var/zone)
@@ -104,13 +113,26 @@ var/global/list/sparring_attack_cache = list()
target.visible_message("<span class='danger'>[target] has been weakened!</span>")
target.apply_effect(3, WEAKEN, armor*100)
/datum/unarmed_attack/proc/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
var/obj/item/organ/external/affecting = target.get_organ(zone)
/datum/unarmed_attack/proc/show_attack(var/mob/living/carbon/human/user, var/mob/living/target, var/zone, var/attack_damage)
SHOULD_NOT_SLEEP(TRUE)
var/affecting = null
if(istype(target, /mob/living/carbon/human))
var/mob/living/carbon/human/human = target
var/obj/item/organ/organ = human.get_organ(zone)
affecting = organ?.name
else if(istype(target, /mob/living/heavy_vehicle))
var/mob/living/heavy_vehicle/mech = target
var/obj/item/mech_component/component = mech.zoneToComponent(zone)
affecting = component?.name
if(!affecting)
return
user.visible_message(SPAN_WARNING("[user] [pick(attack_verb)] [target] in the [affecting.name]!"))
user.visible_message(SPAN_WARNING("[user] [pick(attack_verb)] [target] in the [affecting]!"))
playsound(user.loc, attack_sound, 25, 1, -1)
/datum/unarmed_attack/proc/show_attack_simple(var/mob/living/carbon/human/user, var/mob/living/target, var/zone)
@@ -246,8 +268,8 @@ var/global/list/sparring_attack_cache = list()
return FALSE
/datum/unarmed_attack/kick/get_unarmed_damage(var/mob/living/carbon/human/user)
var/obj/item/clothing/shoes = user.shoes
/datum/unarmed_attack/kick/get_unarmed_damage(var/mob/attacker, var/mob/living/carbon/human/target)
var/obj/item/clothing/shoes = target.shoes
if(!istype(shoes))
return damage
return damage + (shoes ? shoes.force : 0)
@@ -294,8 +316,8 @@ var/global/list/sparring_attack_cache = list()
return FALSE
/datum/unarmed_attack/stomp/get_unarmed_damage(var/mob/living/carbon/human/user)
var/obj/item/clothing/shoes = user.shoes
/datum/unarmed_attack/stomp/get_unarmed_damage(var/mob/attacker, var/mob/living/carbon/human/target)
var/obj/item/clothing/shoes = target.shoes
return damage + (shoes ? shoes.force : 0)
/datum/unarmed_attack/stomp/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
@@ -332,4 +354,4 @@ var/global/list/sparring_attack_cache = list()
desc = "Sparring: A heavy strike to your opponent. With poise and precision, no evidence will be left behind! They WILL ABSOLUTELY feel this, but will suffer no dangerous side effect, unless you punch them into cardiac arrest! Show off your might!"
damage = 4
attack_name = "heavy hit"
attack_sound = /singleton/sound_category/punch_bassy_sound
attack_sound = /singleton/sound_category/punch_bassy_sound
@@ -1476,6 +1476,8 @@ There are several things that need to be remembered:
//Drawcheck functions
//These functions check if an item should be drawn, or if its covered up by something else
/mob/living/carbon/human/proc/check_draw_gloves()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
if (!gloves)
return FALSE
else if (gloves.flags_inv & ALWAYSDRAW)
@@ -1486,6 +1488,8 @@ There are several things that need to be remembered:
return TRUE
/mob/living/carbon/human/proc/check_draw_right_ear()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
if (!r_ear)
return FALSE
else if (r_ear.flags_inv & ALWAYSDRAW)
@@ -1496,6 +1500,8 @@ There are several things that need to be remembered:
/mob/living/carbon/human/proc/check_draw_left_ear()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
if (!l_ear)
return FALSE
else if (l_ear.flags_inv & ALWAYSDRAW)
@@ -1505,6 +1511,8 @@ There are several things that need to be remembered:
return TRUE
/mob/living/carbon/human/proc/check_draw_glasses()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
if (!glasses)
return FALSE
else if (glasses.flags_inv & ALWAYSDRAW)
@@ -1516,6 +1524,8 @@ There are several things that need to be remembered:
/mob/living/carbon/human/proc/check_draw_mask()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
if (!wear_mask)
return FALSE
else if (wear_mask.flags_inv & ALWAYSDRAW)
@@ -1526,6 +1536,8 @@ There are several things that need to be remembered:
return TRUE
/mob/living/carbon/human/proc/check_draw_shoes()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
if (!shoes)
return FALSE
else if (shoes.flags_inv & ALWAYSDRAW)
@@ -1536,6 +1548,8 @@ There are several things that need to be remembered:
return TRUE
/mob/living/carbon/human/proc/check_draw_underclothing()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
if (!w_uniform)
return FALSE
else if (w_uniform.flags_inv & ALWAYSDRAW)
@@ -1546,6 +1560,8 @@ There are several things that need to be remembered:
return TRUE
/mob/living/carbon/human/proc/check_draw_wrists()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
if (!wrists)
return FALSE
else if (wrists.flags_inv & ALWAYSDRAW)
@@ -19,6 +19,7 @@
end_leap(user, target, old_pass_flags)
/singleton/maneuver/leap/proc/end_leap(var/mob/living/user, var/atom/target, var/pass_flag)
SHOULD_NOT_SLEEP(TRUE)
user.pass_flags = pass_flag
if(ishuman(user))
var/mob/living/carbon/human/H = user
@@ -114,4 +115,50 @@
/singleton/maneuver/leap/tesla_body
cooldown = 20 SECONDS
delay = 4 SECONDS
stamina_cost = 30
stamina_cost = 30
/singleton/maneuver/leap/areagrab
cooldown = 5 MINUTES
delay = 3 SECONDS
stamina_cost = 50
/singleton/maneuver/leap/areagrab/show_initial_message(mob/living/user, atom/target)
. = ..()
user.balloon_alert_to_viewers("OUUGUGUUUUUUUUUUUGBHGH", "OUUGUGUUUUUUUUUUUGBHGH")
//Let them hear, let them fear
for(var/mob/living/carbon/human/person_in_range in get_hearers_in_LOS(world.view+5))
to_chat(person_in_range,
SPAN_HIGHDANGER("OUUGUGUUUUUUUUUUUGBHGH!!!")
)
/singleton/maneuver/leap/areagrab/end_leap(var/mob/living/user, var/atom/target, pass_flag)
. = ..()
var/list/mob/living/affected_mobs = list()
for(var/mob/living/subject in range(1))
affected_mobs += subject
affected_mobs -= user //Exclude ourself from it
if(length(affected_mobs))
var/mob/living/very_unlucky_guy = pick(affected_mobs)
for(var/mob/living/subject as anything in (affected_mobs - very_unlucky_guy))
INVOKE_ASYNC(subject, TYPE_PROC_REF(/atom/movable, throw_at_random), FALSE, 3, THROWNOBJ_KNOCKBACK_SPEED)
INVOKE_ASYNC(subject, TYPE_PROC_REF(/mob/living, Weaken), 5)
if(ismob(very_unlucky_guy) && user.Adjacent(very_unlucky_guy))
var/obj/item/grab/G = new(user, user, very_unlucky_guy)
user.put_in_active_hand(G)
G.state = GRAB_NECK
G.icon_state = "grabbed+1"
G.synch()
G.update_icon()
G.hud.icon_state = "kill"
G.hud.name = "kill"
@@ -534,7 +534,7 @@
simple_harm_attack(user)
return
attack.show_attack_simple(user, src, pick(organ_names))
var/actual_damage = attack.get_unarmed_damage(user) //Punch and kick no longer have get_unarmed_damage due to how humanmob combat works. If we have none, we'll apply a small random amount.
var/actual_damage = attack.get_unarmed_damage(src, user) //Punch and kick no longer have get_unarmed_damage due to how humanmob combat works. If we have none, we'll apply a small random amount.
if(!actual_damage)
actual_damage = harm_intent_damage ? rand(1, harm_intent_damage) : 0
apply_damage(actual_damage, attack.damage_type)
+6 -9
View File
@@ -154,15 +154,12 @@
/proc/iszombie(A)
if(ishuman(A))
var/mob/living/carbon/human/H = A
switch(H.get_species())
if(SPECIES_ZOMBIE)
return TRUE
if(SPECIES_ZOMBIE_TAJARA)
return TRUE
if(SPECIES_ZOMBIE_UNATHI)
return TRUE
if(SPECIES_ZOMBIE_SKRELL)
return TRUE
if(istype(H.get_species(TRUE), /datum/species/zombie))
return TRUE
else
return FALSE
return FALSE
/proc/isundead(A)