Merge pull request #6183 from Citadel-Station-13/upstream-merge-36548

[MIRROR] Added a new ability to sentient diseases
This commit is contained in:
LetterJay
2018-04-01 19:50:43 -05:00
committed by GitHub
13 changed files with 169 additions and 24 deletions
+8 -2
View File
@@ -71,7 +71,8 @@
#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir)
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable)
#define COMSIG_MOVABLE_COLLIDE "movable_collide" //from base of atom/movable/Collide(): (/atom)
#define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (/atom, throwingdatum)
#define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (/atom/hit_atom, /datum/thrownthing/throwingdatum)
#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone" //from base of mob/living/hitby(): (mob/living/target, hit_zone)
#define COMSIG_MOVABLE_BUCKLE "buckle" //from base of atom/movable/buckle_mob(): (mob, force)
#define COMSIG_MOVABLE_UNBUCKLE "unbuckle" //from base of atom/movable/unbuckle_mob(): (mob, force)
@@ -80,7 +81,9 @@
#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob)
#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob)
#define COMSIG_ITEM_EQUIPPED "item_equip" //from base of obj/item/equipped(): (/mob/equipper, slot)
#define COMSIG_ITEM_DROPPED "item_drop" //from base of obj/item/dropped(): (/mob/dropper)
#define COMSIG_ITEM_DROPPED "item_drop"
#define COMSIG_ITEM_PICKUP "item_pickup" //from base of obj/item/pickup(): (/mob/taker)
#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" //from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone)
// /obj/item/clothing signals
#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
@@ -101,3 +104,6 @@
//Wet floors
#define COMSIG_TURF_IS_WET "check_turf_wet" //(): Returns bitflags of wet values.
#define COMSIG_TURF_MAKE_DRY "make_turf_try" //(max_strength, immediate, duration_decrease = INFINITY): Returns bool.
//Food
#define COMSIG_FOOD_EATEN "food_eaten" //from base of obj/item/reagent_containers/food/snacks/attack(): (mob/living/eater, mob/feeder)
+21
View File
@@ -398,7 +398,28 @@
return covered_parts
/proc/slot2body_zone(slot)
switch(slot)
if(slot_back, slot_wear_suit, slot_w_uniform, slot_belt, slot_wear_id)
return BODY_ZONE_CHEST
if(slot_gloves, slot_hands, slot_handcuffed)
return pick(BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND)
if(slot_head, slot_neck, slot_neck, slot_ears)
return BODY_ZONE_HEAD
if(slot_wear_mask)
return BODY_ZONE_PRECISE_MOUTH
if(slot_glasses)
return BODY_ZONE_PRECISE_EYES
if(slot_shoes)
return pick(BODY_ZONE_PRECISE_R_FOOT, BODY_ZONE_PRECISE_L_FOOT)
if(slot_legcuffed)
return pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
//adapted from http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
/proc/heat2colour(temp)
+74 -8
View File
@@ -1,12 +1,78 @@
/datum/component/infective
dupe_mode = COMPONENT_DUPE_ALLOWED
var/list/datum/disease/diseases //make sure these are the static, non-processing versions!
var/expire_time
var/min_clean_strength = CLEAN_WEAK
/datum/component/infective/Initialize(list/datum/disease/_diseases)
RegisterSignal(COMSIG_MOVABLE_CROSSED, .proc/Infect)
diseases = _diseases
/datum/component/infective/Initialize(list/datum/disease/_diseases, expire_in)
if(islist(_diseases))
diseases = diseases
else
diseases = list(_diseases)
if(expire_in)
expire_time = world.time + expire_in
QDEL_IN(src, expire_in)
RegisterSignal(COMSIG_MOVABLE_BUCKLE, .proc/try_infect_buckle)
RegisterSignal(COMSIG_MOVABLE_COLLIDE, .proc/try_infect_collide)
RegisterSignal(COMSIG_MOVABLE_CROSSED, .proc/try_infect_crossed)
RegisterSignal(COMSIG_ITEM_ATTACK_ZONE, .proc/try_infect_attack_zone)
RegisterSignal(COMSIG_ITEM_ATTACK, .proc/try_infect_attack)
RegisterSignal(COMSIG_ITEM_EQUIPPED, .proc/try_infect_equipped)
RegisterSignal(COMSIG_MOVABLE_IMPACT_ZONE, .proc/try_infect_impact_zone)
RegisterSignal(COMSIG_FOOD_EATEN, .proc/try_infect_eat)
RegisterSignal(COMSIG_COMPONENT_CLEAN_ACT, .proc/clean)
/datum/component/infective/proc/Infect(atom/movable/AM)
var/mob/living/carbon/victim = AM
if(istype(victim))
for(var/datum/disease/D in diseases)
victim.ContactContractDisease(D, "feet")
/datum/component/infective/proc/try_infect_eat(mob/living/eater, mob/living/feeder)
for(var/V in diseases)
eater.ForceContractDisease(V)
try_infect(feeder, BODY_ZONE_L_ARM)
/datum/component/infective/proc/clean(clean_strength)
if(clean_strength >= min_clean_strength)
qdel(src)
/datum/component/infective/proc/try_infect_buckle(mob/M, force)
if(isliving(M))
try_infect(M)
/datum/component/infective/proc/try_infect_collide(atom/A)
var/atom/movable/P = parent
if(P.throwing)
//this will be handled by try_infect_impact_zone()
return
if(isliving(A))
try_infect(A)
/datum/component/infective/proc/try_infect_impact_zone(mob/living/target, hit_zone)
try_infect(target, hit_zone)
/datum/component/infective/proc/try_infect_attack_zone(mob/living/carbon/target, mob/living/user, hit_zone)
try_infect(user, BODY_ZONE_L_ARM)
try_infect(target, hit_zone)
/datum/component/infective/proc/try_infect_attack(mob/living/target, mob/living/user)
if(!iscarbon(target)) //this case will be handled by try_infect_attack_zone
try_infect(target)
try_infect(user, BODY_ZONE_L_ARM)
/datum/component/infective/proc/try_infect_equipped(mob/living/L, slot)
var/old_permeability
if(isitem(parent))
//if you are putting an infective item on, it obviously will not protect you, so set its permeability high enough that it will never block ContactContractDisease()
var/obj/item/I = parent
old_permeability = I.permeability_coefficient
I.permeability_coefficient = 1.01
try_infect(L, slot2body_zone(slot))
if(isitem(parent))
var/obj/item/I = parent
I.permeability_coefficient = old_permeability
/datum/component/infective/proc/try_infect_crossed(atom/movable/M)
if(isliving(M))
try_infect(M, BODY_ZONE_PRECISE_L_FOOT)
/datum/component/infective/proc/try_infect(mob/living/L, target_zone)
for(var/V in diseases)
L.ContactContractDisease(V, target_zone)
+8 -4
View File
@@ -46,8 +46,12 @@
if(satiety>0 && prob(satiety/10)) // positive satiety makes it harder to contract the disease.
return
//Lefts and rights do not matter for arms and legs, they both run the same checks
if(!target_zone)
target_zone = pick(head_ch;BODY_ZONE_HEAD,body_ch;"body",hands_ch;"hands",feet_ch;"feet")
target_zone = pick(head_ch;BODY_ZONE_HEAD,body_ch;BODY_ZONE_CHEST,hands_ch;BODY_ZONE_L_ARM,feet_ch;BODY_ZONE_L_LEG)
else
target_zone = check_zone(target_zone)
if(ishuman(src))
var/mob/living/carbon/human/H = src
@@ -63,14 +67,14 @@
if(passed && isobj(H.wear_neck))
Cl = H.wear_neck
passed = prob((Cl.permeability_coefficient*100) - 1)
if("body")
if(BODY_ZONE_CHEST)
if(isobj(H.wear_suit))
Cl = H.wear_suit
passed = prob((Cl.permeability_coefficient*100) - 1)
if(passed && isobj(slot_w_uniform))
Cl = slot_w_uniform
passed = prob((Cl.permeability_coefficient*100) - 1)
if("hands")
if(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)
if(isobj(H.wear_suit) && H.wear_suit.body_parts_covered&HANDS)
Cl = H.wear_suit
passed = prob((Cl.permeability_coefficient*100) - 1)
@@ -78,7 +82,7 @@
if(passed && isobj(H.gloves))
Cl = H.gloves
passed = prob((Cl.permeability_coefficient*100) - 1)
if("feet")
if(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
if(isobj(H.wear_suit) && H.wear_suit.body_parts_covered&FEET)
Cl = H.wear_suit
passed = prob((Cl.permeability_coefficient*100) - 1)
+1 -1
View File
@@ -400,7 +400,7 @@
SSspacedrift.processing[src] = src
return 1
/atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum)
/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
set waitfor = 0
SendSignal(COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
return hit_atom.hitby(src)
+2 -2
View File
@@ -440,7 +440,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/datum/action/A = X
if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
SendSignal(COMSIG_ITEM_EQUIPPED,user,slot)
item_flags |= IN_INVENTORY
//sometimes we only want to grant the item's action if it's equipped in a specific slot.
@@ -571,8 +570,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
else
return
/obj/item/throw_impact(atom/A)
/obj/item/throw_impact(atom/A, datum/thrownthing/throwingdatum)
if(A && !QDELETED(A))
SendSignal(COMSIG_MOVABLE_IMPACT, A, throwingdatum)
if(is_hot() && isliving(A))
var/mob/living/L = A
L.IgniteMob()
@@ -228,6 +228,7 @@
return
usr.visible_message("<span class='notice'>[usr] grabs \the [src.name].</span>", "<span class='notice'>You grab \the [src.name].</span>")
var/C = new item_chair(loc)
TransferComponents(C)
usr.put_in_hands(C)
qdel(src)
@@ -279,6 +280,7 @@
user.visible_message("<span class='notice'>[user] rights \the [src.name].</span>", "<span class='notice'>You right \the [name].</span>")
var/obj/structure/chair/C = new origin_type(get_turf(loc))
TransferComponents(C)
C.setDir(dir)
qdel(src)
@@ -7,6 +7,7 @@ is currently following.
GLOBAL_LIST_INIT(disease_ability_singletons, list(
new /datum/disease_ability/action/cough(),
new /datum/disease_ability/action/sneeze(),
new /datum/disease_ability/action/infect(),
new /datum/disease_ability/symptom/cough(),
new /datum/disease_ability/symptom/sneeze(),\
new /datum/disease_ability/symptom/hallucigen(),
@@ -165,7 +166,6 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
short_desc = "Force the host you are following to sneeze, spreading your infection to those in front of them."
long_desc = "Force the host you are following to sneeze with extra force, spreading your infection to any victims in a 4 meter cone in front of your host.<br>Cooldown: 20 seconds"
/datum/action/cooldown/disease_sneeze
name = "Sneeze"
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
@@ -194,6 +194,47 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
StartCooldown()
return TRUE
/datum/disease_ability/action/infect
name = "Secrete Infection"
actions = list(/datum/action/cooldown/disease_infect)
cost = 2
required_total_points = 3
short_desc = "Cause all objects your host is touching to become infectious for a limited time, spreading your infection to anyone who touches them."
long_desc = "Cause the host you are following to excrete an infective substance from their pores, causing all objects touching their skin to transmit your infection to anyone who touches them for the next 30 seconds. This includes the floor, if they are not wearing shoes, and any items they are holding, if they are not wearing gloves.<br>Cooldown: 40 seconds"
/datum/action/cooldown/disease_infect
name = "Secrete Infection"
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
button_icon_state = "infect"
desc = "Cause the host you are following to excrete an infective substance from their pores, causing all objects touching their skin to transmit your infection to anyone who touches them for the next 30 seconds.<br>Cooldown: 40 seconds"
cooldown_time = 400
/datum/action/cooldown/disease_infect/Trigger()
if(!..())
return FALSE
var/mob/camera/disease/D = owner
var/mob/living/carbon/human/H = D.following_host
if(!H)
return FALSE
for(var/V in H.get_equipped_items(FALSE))
var/obj/O = V
O.AddComponent(/datum/component/infective, D.disease_template, 300)
//no shoes? infect the floor.
if(!H.shoes)
var/turf/T = get_turf(H)
if(T && !isspaceturf(T))
T.AddComponent(/datum/component/infective, D.disease_template, 300)
//no gloves? infect whatever we are holding.
if(!H.gloves)
for(var/V in H.held_items)
if(!V)
continue
var/obj/O = V
O.AddComponent(/datum/component/infective, D.disease_template, 300)
StartCooldown()
return TRUE
//passive symptom abilities
/datum/disease_ability/symptom/cough
+7 -6
View File
@@ -37,20 +37,20 @@
else
..()
/obj/item/reagent_containers/food/snacks/proc/On_Consume()
if(!usr)
/obj/item/reagent_containers/food/snacks/proc/On_Consume(mob/living/eater)
if(!eater)
return
if(!reagents.total_volume)
var/obj/item/trash_item = generate_trash(usr)
var/obj/item/trash_item = generate_trash(eater)
qdel(src)
usr.put_in_hands(trash_item)
eater.put_in_hands(trash_item)
/obj/item/reagent_containers/food/snacks/attack_self(mob/user)
return
/obj/item/reagent_containers/food/snacks/attack(mob/living/M, mob/user, def_zone)
/obj/item/reagent_containers/food/snacks/attack(mob/living/M, mob/living/user, def_zone)
if(user.a_intent == INTENT_HARM)
return ..()
if(!eatverb)
@@ -109,11 +109,12 @@
M.satiety -= junkiness
playsound(M.loc,'sound/items/eatfood.ogg', rand(10,50), 1)
if(reagents.total_volume)
SendSignal(COMSIG_FOOD_EATEN, M, user)
var/fraction = min(bitesize / reagents.total_volume, 1)
reagents.reaction(M, INGEST, fraction)
reagents.trans_to(M, bitesize)
bitecount++
On_Consume()
On_Consume(M)
checkLiked(fraction, M)
return 1
@@ -75,6 +75,7 @@
affecting = get_bodypart(ran_zone(user.zone_selected))
if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest)
affecting = bodyparts[1]
I.SendSignal(COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
send_item_attack_message(I, user, affecting.name)
if(I.force)
//CIT CHANGES START HERE - combatmode and resting checks
@@ -173,6 +173,8 @@
affecting = get_bodypart(ran_zone(user.zone_selected))
var/target_area = parse_zone(check_zone(user.zone_selected)) //our intended target
I.SendSignal(COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
SSblackbox.record_feedback("nested tally", "item_used_for_combat", 1, list("[I.force]", "[I.type]"))
SSblackbox.record_feedback("tally", "zone_targeted", 1, target_area)
@@ -67,6 +67,7 @@
var/zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
var/volume = I.get_volume_by_throwforce_and_or_w_class()
I.SendSignal(COMSIG_MOVABLE_IMPACT_ZONE, src, zone)
dtype = I.damtype
if (I.throwforce > 0) //If the weapon's throwforce is greater than zero...