From b560ff82844599b2259377bb877479573bc9c46c Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sun, 17 Nov 2019 06:23:12 +0100 Subject: [PATCH 001/148] refactoring code to allow all living mobs to use shields. --- code/__HELPERS/unsorted.dm | 10 --- code/_onclick/item_attack.dm | 20 ++--- .../mob/living/carbon/alien/alien_defense.dm | 15 ++-- .../carbon/alien/humanoid/humanoid_defense.dm | 74 +++++++++---------- .../mob/living/carbon/carbon_defense.dm | 65 ++++++++-------- .../mob/living/carbon/human/human_defense.dm | 53 ++++--------- .../mob/living/carbon/human/species.dm | 5 -- .../living/carbon/monkey/monkey_defense.dm | 4 +- code/modules/mob/living/living_defense.dm | 34 ++++++++- .../mob/living/silicon/ai/ai_defense.dm | 20 ++++- .../mob/living/silicon/pai/pai_defense.dm | 3 + .../mob/living/silicon/silicon_defense.dm | 15 ---- .../living/simple_animal/animal_defense.dm | 4 +- code/modules/paperwork/paperplane.dm | 2 +- 14 files changed, 167 insertions(+), 157 deletions(-) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 9abe42ea8e..43791a5642 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -758,16 +758,6 @@ GLOBAL_LIST_INIT(can_embed_types, typecacheof(list( /obj/item/stack/rods, /obj/item/pipe))) -/proc/can_embed(obj/item/W) - if(W.get_sharpness()) - return 1 - if(is_pointed(W)) - return 1 - - if(is_type_in_typecache(W, GLOB.can_embed_types)) - return 1 - - /* Checks if that loc and dir has an item on the wall */ diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 3a45e9bf60..9107fa9e3e 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -109,17 +109,19 @@ take_damage(I.force, I.damtype, "melee", 1) /mob/living/attacked_by(obj/item/I, mob/living/user) + //CIT CHANGES START HERE - combatmode and resting checks + var/totitemdamage = I.force + if(iscarbon(user)) + var/mob/living/carbon/tempcarb = user + if(!tempcarb.combatmode) + totitemdamage *= 0.5 + if(user.resting) + totitemdamage *= 0.5 + //CIT CHANGES END HERE + if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration)) + return FALSE send_item_attack_message(I, user) if(I.force) - //CIT CHANGES START HERE - combatmode and resting checks - var/totitemdamage = I.force - if(iscarbon(user)) - var/mob/living/carbon/tempcarb = user - if(!tempcarb.combatmode) - totitemdamage *= 0.5 - if(user.resting) - totitemdamage *= 0.5 - //CIT CHANGES END HERE apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage if(I.damtype == BRUTE) if(prob(33)) diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index b9e27c0637..b6fbe3a875 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -6,8 +6,10 @@ return 2 //no ears /mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush) - ..(AM, skipcatch = TRUE, hitpush = FALSE) + return ..(AM, skipcatch = TRUE, hitpush = FALSE) +/mob/living/carbon/alien/can_embed(obj/item/I) + return FALSE /*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other. As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble. @@ -50,9 +52,9 @@ In all, this is a lot like the monkey code. /N /mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M) - if(..()) //to allow surgery to return properly. - return 0 - + . = ..() + if(.) //To allow surgery to return properly. + return switch(M.a_intent) if("help") help_shake_act(M) @@ -60,11 +62,10 @@ In all, this is a lot like the monkey code. /N grabbedby(M) if ("harm") M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - return 1 + return FALSE if("disarm") M.do_attack_animation(src, ATTACK_EFFECT_DISARM) - return 1 - return 0 + return FALSE /mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M) diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm index b3839a6033..c2be4249a2 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm @@ -21,46 +21,46 @@ return 1 /mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M) - if(..()) - switch(M.a_intent) - if ("harm") - var/damage = rand(1, 9) - if (prob(90)) - playsound(loc, "punch", 25, 1, -1) - visible_message("[M] has punched [src]!", \ - "[M] has punched [src]!", null, COMBAT_MESSAGE_RANGE) - if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of knocking an alien down. - Unconscious(40) - visible_message("[M] has knocked [src] down!", \ - "[M] has knocked [src] down!") - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) - apply_damage(damage, BRUTE, affecting) - log_combat(M, src, "attacked") + . = ..() + if(.) //To allow surgery to return properly. + return + switch(M.a_intent) + if ("harm") + var/damage = rand(1, 9) + if (prob(90)) + playsound(loc, "punch", 25, 1, -1) + visible_message("[M] has punched [src]!", \ + "[M] has punched [src]!", null, COMBAT_MESSAGE_RANGE) + if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of knocking an alien down. + Unconscious(40) + visible_message("[M] has knocked [src] down!", \ + "[M] has knocked [src] down!") + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + apply_damage(damage, BRUTE, affecting) + log_combat(M, src, "attacked") + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to punch [src]!", \ + "[M] has attempted to punch [src]!", null, COMBAT_MESSAGE_RANGE) + + if ("disarm") + if (!lying) + if (prob(5)) + Unconscious(40) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + log_combat(M, src, "pushed") + visible_message("[M] has pushed down [src]!", \ + "[M] has pushed down [src]!") else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to punch [src]!", \ - "[M] has attempted to punch [src]!", null, COMBAT_MESSAGE_RANGE) - - if ("disarm") - if (!lying) - if (prob(5)) - Unconscious(40) + if (prob(50)) + dropItemToGround(get_active_held_item()) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - log_combat(M, src, "pushed") - visible_message("[M] has pushed down [src]!", \ - "[M] has pushed down [src]!") + visible_message("[M] has disarmed [src]!", \ + "[M] has disarmed [src]!", null, COMBAT_MESSAGE_RANGE) else - if (prob(50)) - dropItemToGround(get_active_held_item()) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has disarmed [src]!", \ - "[M] has disarmed [src]!", null, COMBAT_MESSAGE_RANGE) - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to disarm [src]!",\ - "[M] has attempted to disarm [src]!", null, COMBAT_MESSAGE_RANGE) - - + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to disarm [src]!",\ + "[M] has attempted to disarm [src]!", null, COMBAT_MESSAGE_RANGE) /mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) if(!no_effect && !visual_effect_icon) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index b0e9b808df..6f03ea4364 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -48,31 +48,48 @@ if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment)) affecting.dismember(P.damtype) -/mob/living/carbon/proc/can_catch_item(skip_throw_mode_check) - . = FALSE +/mob/living/carbon/catch_item(obj/item/I, skip_throw_mode_check = FALSE) + . = ..() if(!skip_throw_mode_check && !in_throw_mode) return if(get_active_held_item()) return if(restrained()) return - return TRUE + I.attack_hand(src) + if(get_active_held_item() == I) //if our attack_hand() picks up the item... + visible_message("[src] catches [I]!") //catch that sucker! + throw_mode_off() + return TRUE -/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE) - if(!skipcatch) //ugly, but easy - if(can_catch_item()) - if(istype(AM, /obj/item)) - var/obj/item/I = AM - if(isturf(I.loc)) - I.attack_hand(src) - if(get_active_held_item() == I) //if our attack_hand() picks up the item... - visible_message("[src] catches [I]!") //catch that sucker! - throw_mode_off() - return 1 - ..() +/mob/living/carbon/can_embed(obj/item/I) + if(I.get_sharpness() || is_pointed(I) || is_type_in_typecache(I, GLOB.can_embed_types)) + return TRUE +/mob/living/carbon/embed_item(obj/item/I) + throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) + var/obj/item/bodypart/L = pick(bodyparts) + L.embedded_objects |= I + I.add_mob_blood(src)//it embedded itself in you, of course it's bloody! + I.forceMove(src) + L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier) + visible_message("[I] embeds itself in [src]'s [L.name]!","[I] embeds itself in your [L.name]!") + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded) /mob/living/carbon/attacked_by(obj/item/I, mob/living/user) + //CIT CHANGES START HERE - combatmode and resting checks + var/totitemdamage = I.force + if(iscarbon(user)) + var/mob/living/carbon/tempcarb = user + if(!tempcarb.combatmode) + totitemdamage *= 0.5 + if(user.resting) + totitemdamage *= 0.5 + if(!combatmode) + totitemdamage *= 1.5 + //CIT CHANGES END HERE + if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration)) + return FALSE var/obj/item/bodypart/affecting if(user == src) affecting = get_bodypart(check_zone(user.zone_selected)) //we're self-mutilating! yay! @@ -83,17 +100,6 @@ SEND_SIGNAL(I, 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 - var/totitemdamage = I.force - if(iscarbon(user)) - var/mob/living/carbon/tempcarb = user - if(!tempcarb.combatmode) - totitemdamage *= 0.5 - if(user.resting) - totitemdamage *= 0.5 - if(!combatmode) - totitemdamage *= 1.5 - //CIT CHANGES END HERE apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC) var/basebloodychance = affecting.brute_dam + totitemdamage @@ -127,7 +133,9 @@ //ATTACK HAND IGNORING PARENT RETURN VALUE /mob/living/carbon/attack_hand(mob/living/carbon/human/user) - + . = ..() + if(.) //To allow surgery to return properly. + return for(var/thing in diseases) var/datum/disease/D = thing if(D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN) @@ -142,8 +150,7 @@ if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM) for(var/datum/surgery/S in surgeries) if(S.next_step(user, user.a_intent)) - return 1 - return 0 + return TRUE /mob/living/carbon/attack_paw(mob/living/carbon/monkey/M) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 2ab7c6d404..fda60aeb98 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -100,23 +100,29 @@ return 1 return 0 -/mob/living/carbon/human/proc/check_shields(atom/AM, var/damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0) +/mob/living/proc/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0) var/block_chance_modifier = round(damage / -3) - for(var/obj/item/I in held_items) if(!istype(I, /obj/item/clothing)) var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type)) - return 1 + return TRUE + return FALSE + +/mob/living/carbon/human/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0) + . = ..() + if(.) + return + var/block_chance_modifier = round(damage / -3) if(wear_suit) var/final_block_chance = wear_suit.block_chance - (CLAMP((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier if(wear_suit.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type)) - return 1 + return TRUE if(w_uniform) var/final_block_chance = w_uniform.block_chance - (CLAMP((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier if(w_uniform.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type)) - return 1 - return 0 + return TRUE + return FALSE /mob/living/carbon/human/proc/check_block() if(mind) @@ -125,37 +131,7 @@ return FALSE /mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE) - if(dna && dna.species) - var/spec_return = dna.species.spec_hitby(AM, src) - if(spec_return) - return spec_return - var/obj/item/I - var/throwpower = 30 - if(istype(AM, /obj/item)) - I = AM - throwpower = I.throwforce - if(I.thrownby == src) //No throwing stuff at yourself to trigger hit reactions - return ..() - if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK)) - hitpush = FALSE - skipcatch = TRUE - blocked = TRUE - else if(I) - if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD) - if(can_embed(I)) - if(prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE)) - throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) - var/obj/item/bodypart/L = pick(bodyparts) - L.embedded_objects |= I - I.add_mob_blood(src)//it embedded itself in you, of course it's bloody! - I.forceMove(src) - L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier) - visible_message("[I] embeds itself in [src]'s [L.name]!","[I] embeds itself in your [L.name]!") - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded) - hitpush = FALSE - skipcatch = TRUE //can't catch the now embedded item - - return ..() + return dna?.species?.spec_hitby(AM, src) || ..() /mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0) if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (HAS_TRAIT(src, TRAIT_FAT)) && ismonkey(pulling)) @@ -203,7 +179,8 @@ return 1 /mob/living/carbon/human/attack_hand(mob/user) - if(..()) //to allow surgery to return properly. + . = ..() + if(.) //To allow surgery to return properly. return if(ishuman(user)) var/mob/living/carbon/human/H = user diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 49ae178d8c..b54f30df57 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1678,11 +1678,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) return if(M.mind) attacker_style = M.mind.martial_art - if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK)) - log_combat(M, H, "attempted to touch") - H.visible_message("[M] attempted to touch [H]!") - return 0 - SEND_SIGNAL(M, COMSIG_MOB_ATTACK_HAND, M, H, attacker_style) switch(M.a_intent) if("help") help(M, H, attacker_style) diff --git a/code/modules/mob/living/carbon/monkey/monkey_defense.dm b/code/modules/mob/living/carbon/monkey/monkey_defense.dm index df90dd56fd..da5f8e75c3 100644 --- a/code/modules/mob/living/carbon/monkey/monkey_defense.dm +++ b/code/modules/mob/living/carbon/monkey/monkey_defense.dm @@ -28,9 +28,9 @@ apply_damage(damage, BRUTE, affecting) /mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M) - if(..()) //To allow surgery to return properly. + . = ..() + if(.) //To allow surgery to return properly. return - switch(M.a_intent) if("help") help_shake_act(M) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 93e64fd4cc..f5dd982ad5 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -55,9 +55,32 @@ else return 0 +/mob/living/proc/catch_item(obj/item/I, skip_throw_mode_check = FALSE) + return FALSE + +/mob/living/proc/embed_item(obj/item/I) + return + +/mob/living/proc/can_embed(obj/item/I) + return FALSE + /mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE) - if(istype(AM, /obj/item)) - var/obj/item/I = AM + var/obj/item/I + var/throwpower = 30 + if(isitem(AM)) + I = AM + throwpower = I.throwforce + if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK)) + hitpush = FALSE + skipcatch = TRUE + blocked = TRUE + else if(I && I.throw_speed >= EMBED_THROWSPEED_THRESHOLD && can_embed(I, src) && prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE)) + embed_item(I) + hitpush = FALSE + skipcatch = TRUE //can't catch the now embedded item + if(I) + if(!skipcatch && isturf(I.loc) && catch_item(I)) + return TRUE 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() @@ -211,6 +234,13 @@ Move(user.loc) return 1 +/mob/living/attack_hand(mob/user) + ..() //Ignoring parent return value here. + SEND_SIGNAL(user, COMSIG_MOB_ATTACK_HAND, user, src) + if((user != src) && user.a_intent != INTENT_HELP && check_shields(user, 0, user.name, attack_type = UNARMED_ATTACK)) + log_combat(user, src, "attempted to touch") + visible_message("[user] attempted to touch [src]!") + return TRUE /mob/living/attack_slime(mob/living/simple_animal/slime/M) if(!SSticker.HasRoundStarted()) diff --git a/code/modules/mob/living/silicon/ai/ai_defense.dm b/code/modules/mob/living/silicon/ai/ai_defense.dm index 7c59c2b791..8799d34a08 100644 --- a/code/modules/mob/living/silicon/ai/ai_defense.dm +++ b/code/modules/mob/living/silicon/ai/ai_defense.dm @@ -1,8 +1,26 @@ +//ATTACK HAND IGNORING PARENT RETURN VALUE +/mob/living/silicon/ai/attack_hand(mob/living/carbon/human/M) + . = ..() + if(.) //the attack was blocked + return + switch(M.a_intent) + if ("help") + M.visible_message("[M] pets [src].", \ + "You pet [src].") + if("grab") + grabbedby(M) + else + M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) + playsound(src.loc, 'sound/effects/bang.ogg', 10, 1) + visible_message("[M] punches [src], but doesn't leave a dent.", \ + "[M] punches [src], but doesn't leave a dent.", null, COMBAT_MESSAGE_RANGE) /mob/living/silicon/ai/attacked_by(obj/item/I, mob/living/user, def_zone) + . = ..() + if(!.) + return FALSE if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt. spark_system.start() - return ..() /mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M) diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm index dda8ddfebd..647951ed4e 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -27,6 +27,9 @@ Knockdown(200) /mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user) + . = ..() + if(.) + return switch(user.a_intent) if("help") visible_message("[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.") diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 073a2eec2b..482ecc429f 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -63,21 +63,6 @@ return 1 return 0 -//ATTACK HAND IGNORING PARENT RETURN VALUE -/mob/living/silicon/attack_hand(mob/living/carbon/human/M) - switch(M.a_intent) - if ("help") - M.visible_message("[M] pets [src].", \ - "You pet [src].") - if("grab") - grabbedby(M) - else - M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - playsound(src.loc, 'sound/effects/bang.ogg', 10, 1) - visible_message("[M] punches [src], but doesn't leave a dent.", \ - "[M] punches [src], but doesn't leave a dent.", null, COMBAT_MESSAGE_RANGE) - return 0 - /mob/living/silicon/attack_drone(mob/living/simple_animal/drone/M) if(M.a_intent == INTENT_HARM) return diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index 793df63c87..e74b29be44 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -1,7 +1,9 @@ /mob/living/simple_animal/attack_hand(mob/living/carbon/human/M) - ..() + . = ..() + if(.) //the attack was blocked + return switch(M.a_intent) if("help") if (health > 0) diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index b547089aef..9ba7fba157 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -100,7 +100,7 @@ /obj/item/paperplane/throw_impact(atom/hit_atom) if(iscarbon(hit_atom)) var/mob/living/carbon/C = hit_atom - if(C.can_catch_item(TRUE)) + if(!get_active_held_item() && !restrained()) var/datum/action/innate/origami/origami_action = locate() in C.actions if(origami_action?.active) //if they're a master of origami and have the ability turned on, force throwmode on so they'll automatically catch the plane. C.throw_mode_on() From 5d06ea5d486a40900d68221307e334a32f352673 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sun, 17 Nov 2019 07:16:53 +0100 Subject: [PATCH 002/148] o --- code/modules/paperwork/paperplane.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index 9ba7fba157..0920b76332 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -100,7 +100,7 @@ /obj/item/paperplane/throw_impact(atom/hit_atom) if(iscarbon(hit_atom)) var/mob/living/carbon/C = hit_atom - if(!get_active_held_item() && !restrained()) + if(!C.get_active_held_item() && !C.restrained()) var/datum/action/innate/origami/origami_action = locate() in C.actions if(origami_action?.active) //if they're a master of origami and have the ability turned on, force throwmode on so they'll automatically catch the plane. C.throw_mode_on() From 6e9d2d57c08244309234a6efbf0818511cf26e9a Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sun, 17 Nov 2019 22:06:19 +0100 Subject: [PATCH 003/148] check_shields from human to living, part 2 --- code/game/atoms.dm | 2 +- .../mob/living/carbon/alien/alien_defense.dm | 35 +++--- .../carbon/alien/humanoid/humanoid_defense.dm | 10 +- .../carbon/alien/larva/larva_defense.dm | 38 ++++--- .../mob/living/carbon/carbon_defense.dm | 2 +- .../mob/living/carbon/human/human_defense.dm | 105 +++++++----------- .../mob/living/carbon/monkey/combat.dm | 22 ++++ .../living/carbon/monkey/monkey_defense.dm | 99 +++++++++-------- code/modules/mob/living/living_defense.dm | 36 +++++- .../mob/living/silicon/ai/ai_defense.dm | 24 ---- .../mob/living/silicon/pai/pai_defense.dm | 23 ++-- .../mob/living/silicon/robot/robot_defense.dm | 36 +++--- .../mob/living/silicon/silicon_defense.dm | 44 ++++++-- .../living/simple_animal/animal_defense.dm | 51 +++++---- .../mob/living/simple_animal/bot/honkbot.dm | 2 +- .../mob/living/simple_animal/friendly/cat.dm | 8 +- .../mob/living/simple_animal/friendly/dog.dm | 4 +- .../friendly/drone/interaction.dm | 38 +++---- .../living/simple_animal/hostile/mushroom.dm | 4 +- .../mob/living/simple_animal/slime/slime.dm | 10 +- 20 files changed, 316 insertions(+), 277 deletions(-) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index e8651ba93d..f9c45184b7 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -164,7 +164,7 @@ return FALSE -/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) +/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) if(does_attack_animation) user.changeNext_move(CLICK_CD_MELEE) diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index b6fbe3a875..839239a888 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -16,13 +16,10 @@ As such, they can either help or harm other aliens. Help works like the human he In all, this is a lot like the monkey code. /N */ /mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M) - if(isturf(loc) && istype(loc.loc, /area/start)) - to_chat(M, "No attacking people at spawn, you jackass.") - return - + . = ..() switch(M.a_intent) - if ("help") + if (INTENT_HELP) if(!recoveringstam) resting = 0 AdjustStun(-60) @@ -31,10 +28,9 @@ In all, this is a lot like the monkey code. /N AdjustSleeping(-100) visible_message("[M.name] nuzzles [src] trying to wake [p_them()] up!") - if ("grab") - grabbedby(M) - - else + if(INTENT_DISARM, INTENT_HARM) + if(!.) // the attack was blocked or was help/grab intent + return if(health > 0) M.do_attack_animation(src, ATTACK_EFFECT_BITE) playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) @@ -56,23 +52,26 @@ In all, this is a lot like the monkey code. /N if(.) //To allow surgery to return properly. return switch(M.a_intent) - if("help") + if(INTENT_HELP) help_shake_act(M) - if("grab") + if(INTENT_GRAB) grabbedby(M) - if ("harm") + if (INTENT_HARM) + if(HAS_TRAIT(M, TRAIT_PACIFISM)) + to_chat(M, "You don't want to hurt [src]!") + return TRUE M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - return FALSE - if("disarm") + if(INTENT_DISARM) + if(HAS_TRAIT(M, TRAIT_PACIFISM)) + to_chat(M, "You don't want to hurt [src]!") + return TRUE M.do_attack_animation(src, ATTACK_EFFECT_DISARM) - return FALSE /mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M) if(..()) - if (stat != DEAD) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) - apply_damage(rand(1, 3), BRUTE, affecting) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + apply_damage(rand(1, 3), BRUTE, affecting) /mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M) diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm index c2be4249a2..468abf251a 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm @@ -5,9 +5,11 @@ else ..() -/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) +/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) if(user.a_intent == INTENT_HARM) - ..(user, 1) + . = ..(user, TRUE) + if(.) + return adjustBruteLoss(15) var/hitverb = "punched" if(mob_size < MOB_SIZE_LARGE) @@ -25,7 +27,7 @@ if(.) //To allow surgery to return properly. return switch(M.a_intent) - if ("harm") + if (INTENT_HARM) var/damage = rand(1, 9) if (prob(90)) playsound(loc, "punch", 25, 1, -1) @@ -43,7 +45,7 @@ visible_message("[M] has attempted to punch [src]!", \ "[M] has attempted to punch [src]!", null, COMBAT_MESSAGE_RANGE) - if ("disarm") + if (INTENT_DISARM) if (!lying) if (prob(5)) Unconscious(40) diff --git a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm index 69c1be707d..88c34f4387 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm @@ -1,26 +1,30 @@ /mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M) - if(..()) - var/damage = rand(1, 9) - if (prob(90)) - playsound(loc, "punch", 25, 1, -1) - log_combat(M, src, "attacked") - visible_message("[M] has kicked [src]!", \ - "[M] has kicked [src]!", null, COMBAT_MESSAGE_RANGE) - if ((stat != DEAD) && (damage > 4.9)) - Unconscious(rand(100,200)) + . = ..() + if(. || M.a_intent == INTENT_HELP || M.a_intent == INTENT_GRAB) + return + var/damage = rand(1, 9) + if (prob(90)) + playsound(loc, "punch", 25, 1, -1) + log_combat(M, src, "attacked") + visible_message("[M] has kicked [src]!", \ + "[M] has kicked [src]!", null, COMBAT_MESSAGE_RANGE) + if ((stat != DEAD) && (damage > 4.9)) + Unconscious(rand(100,200)) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) - apply_damage(damage, BRUTE, affecting) - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to kick [src]!", \ - "[M] has attempted to kick [src]!", null, COMBAT_MESSAGE_RANGE) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + apply_damage(damage, BRUTE, affecting) + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to kick [src]!", \ + "[M] has attempted to kick [src]!", null, COMBAT_MESSAGE_RANGE) -/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) +/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) if(user.a_intent == INTENT_HARM) - ..(user, 1) + . = ..(user, TRUE) + if(.) + return adjustBruteLoss(5 + rand(1,9)) new /datum/forced_movement(src, get_step_away(user,src, 30), 1) return 1 diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 6f03ea4364..d045e5361d 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -134,7 +134,7 @@ //ATTACK HAND IGNORING PARENT RETURN VALUE /mob/living/carbon/attack_hand(mob/living/carbon/human/user) . = ..() - if(.) //To allow surgery to return properly. + if(.) //was the attack blocked? return for(var/thing in diseases) var/datum/disease/D = thing diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index fda60aeb98..7e7cb18d37 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -85,11 +85,7 @@ return -1 // complete projectile permutation - if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration)) - P.on_hit(src, 100, def_zone) - return 2 - - return (..(P , def_zone)) + return ..() /mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object if(wear_suit) @@ -100,15 +96,6 @@ return 1 return 0 -/mob/living/proc/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0) - var/block_chance_modifier = round(damage / -3) - for(var/obj/item/I in held_items) - if(!istype(I, /obj/item/clothing)) - var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example - if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type)) - return TRUE - return FALSE - /mob/living/carbon/human/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0) . = ..() if(.) @@ -165,12 +152,12 @@ return dna.species.spec_attacked_by(I, user, affecting, a_intent, src) -/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) +/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) if(user.a_intent == INTENT_HARM) - var/hulk_verb = pick("smash","pummel") - if(check_shields(user, 15, "the [hulk_verb]ing")) + . = ..(user, TRUE) + if(.) return - ..(user, 1) + var/hulk_verb = pick("smash","pummel") playsound(loc, user.dna.species.attack_sound, 25, 1, -1) var/message = "[user] has [hulk_verb]ed [src]!" visible_message("[message]", \ @@ -214,56 +201,50 @@ if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites. if(..()) //successful monkey bite, this handles disease contraction. var/damage = rand(1, 3) - if(check_shields(M, damage, "the [M.name]")) - return 0 - if(stat != DEAD) - apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee")) + apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee")) return 1 /mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M) - if(check_shields(M, 0, "the M.name")) - visible_message("[M] attempted to touch [src]!") - return 0 + . = ..() + if(!.) + return + if(M.a_intent == INTENT_HARM) + if (w_uniform) + w_uniform.add_fingerprint(M) + var/damage = prob(90) ? 20 : 0 + if(!damage) + playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) + visible_message("[M] has lunged at [src]!", \ + "[M] has lunged at [src]!") + return 0 + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + if(!affecting) + affecting = get_bodypart(BODY_ZONE_CHEST) + var/armor_block = run_armor_check(affecting, "melee", null, null,10) - if(..()) - if(M.a_intent == INTENT_HARM) - if (w_uniform) - w_uniform.add_fingerprint(M) - var/damage = prob(90) ? 20 : 0 - if(!damage) - playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) - visible_message("[M] has lunged at [src]!", \ - "[M] has lunged at [src]!") - return 0 - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) - if(!affecting) - affecting = get_bodypart(BODY_ZONE_CHEST) - var/armor_block = run_armor_check(affecting, "melee", null, null,10) + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + visible_message("[M] has slashed at [src]!", \ + "[M] has slashed at [src]!") + log_combat(M, src, "attacked") + if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful + return 1 + apply_damage(damage, BRUTE, affecting, armor_block) - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - visible_message("[M] has slashed at [src]!", \ - "[M] has slashed at [src]!") - log_combat(M, src, "attacked") - if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful - return 1 - apply_damage(damage, BRUTE, affecting, armor_block) - - if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead. - var/obj/item/I = get_active_held_item() - if(I && dropItemToGround(I)) - playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) - visible_message("[M] disarmed [src]!", \ - "[M] disarmed [src]!") + if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead. + var/obj/item/I = get_active_held_item() + if(I && dropItemToGround(I)) + playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) + visible_message("[M] disarmed [src]!", \ + "[M] disarmed [src]!") + else + playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) + if(!lying) //CITADEL EDIT + Knockdown(100, TRUE, FALSE, 30, 25) else - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - if(!lying) //CITADEL EDIT - Knockdown(100, TRUE, FALSE, 30, 25) - else - Knockdown(100) - log_combat(M, src, "tackled") - visible_message("[M] has tackled down [src]!", \ - "[M] has tackled down [src]!") - + Knockdown(100) + log_combat(M, src, "tackled") + visible_message("[M] has tackled down [src]!", \ + "[M] has tackled down [src]!") /mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L) diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm index 25bc243f07..59f694e0f6 100644 --- a/code/modules/mob/living/carbon/monkey/combat.dm +++ b/code/modules/mob/living/carbon/monkey/combat.dm @@ -365,6 +365,28 @@ retaliate(L) return ..() +/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M) + if(M.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB)) + retaliate(M) + else if(M.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB)) + retaliate(M) + return ..() + +/mob/living/carbon/monkey/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + if(prob(MONKEY_RETALIATE_HARM_PROB)) + retaliate(user) + . = ..(user, TRUE) + if(.) + return + var/hulk_verb = pick("smash","pummel") + playsound(loc, user.dna.species.attack_sound, 25, 1, -1) + var/message = "[user] has [hulk_verb]ed [src]!" + visible_message("[message]", \ + "[message]") + adjustBruteLoss(15) + return 1 + /mob/living/carbon/monkey/attack_paw(mob/living/L) if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB)) retaliate(L) diff --git a/code/modules/mob/living/carbon/monkey/monkey_defense.dm b/code/modules/mob/living/carbon/monkey/monkey_defense.dm index da5f8e75c3..6d2d7bcbcf 100644 --- a/code/modules/mob/living/carbon/monkey/monkey_defense.dm +++ b/code/modules/mob/living/carbon/monkey/monkey_defense.dm @@ -13,9 +13,8 @@ affecting = get_bodypart(BODY_ZONE_CHEST) if(M.limb_destroyer) dismembering_strike(M, affecting.body_zone) - if(stat != DEAD) - var/dmg = rand(1, 5) - apply_damage(dmg, BRUTE, affecting) + var/dmg = rand(1, 5) + apply_damage(dmg, BRUTE, affecting) /mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L) if(..()) //successful larva bite. @@ -32,11 +31,14 @@ if(.) //To allow surgery to return properly. return switch(M.a_intent) - if("help") + if(INTENT_HELP) help_shake_act(M) - if("grab") + if(INTENT_GRAB) grabbedby(M) - if("harm") + if(INTENT_HARM) + if(HAS_TRAIT(M, TRAIT_PACIFISM)) + to_chat(M, "You don't want to hurt [src]!") + return M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) if (prob(75)) visible_message("[M] has punched [name]!", \ @@ -60,7 +62,7 @@ playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) visible_message("[M] has attempted to punch [name]!", \ "[M] has attempted to punch [name]!", null, COMBAT_MESSAGE_RANGE) - if("disarm") + if(INTENT_DISARM) if(!IsUnconscious()) M.do_attack_animation(src, ATTACK_EFFECT_DISARM) if (prob(25)) @@ -74,50 +76,51 @@ visible_message("[M] has disarmed [src]!", "[M] has disarmed [src]!", null, COMBAT_MESSAGE_RANGE) /mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M) - if(..()) //if harm or disarm intent. - if (M.a_intent == INTENT_HARM) - if ((prob(95) && health > 0)) - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - var/damage = rand(15, 30) - if (damage >= 25) - damage = rand(20, 40) - if(AmountUnconscious() < 300) - Unconscious(rand(200, 300)) - visible_message("[M] has wounded [name]!", \ - "[M] has wounded [name]!", null, COMBAT_MESSAGE_RANGE) - else - visible_message("[M] has slashed [name]!", \ - "[M] has slashed [name]!", null, COMBAT_MESSAGE_RANGE) - - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) - log_combat(M, src, "attacked") - if(!affecting) - affecting = get_bodypart(BODY_ZONE_CHEST) - if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful - return 1 - apply_damage(damage, BRUTE, affecting) - + . = ..() + if(!.) // the attack was blocked or was help/grab intent + return + if (M.a_intent == INTENT_HARM) + if ((prob(95) && health > 0)) + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + var/damage = rand(15, 30) + if (damage >= 25) + damage = rand(20, 40) + if(AmountUnconscious() < 300) + Unconscious(rand(200, 300)) + visible_message("[M] has wounded [name]!", \ + "[M] has wounded [name]!", null, COMBAT_MESSAGE_RANGE) else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to lunge at [name]!", \ - "[M] has attempted to lunge at [name]!", null, COMBAT_MESSAGE_RANGE) + visible_message("[M] has slashed [name]!", \ + "[M] has slashed [name]!", null, COMBAT_MESSAGE_RANGE) - if (M.a_intent == INTENT_DISARM) - var/obj/item/I = null - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - if(prob(95)) - Knockdown(20) - visible_message("[M] has tackled down [name]!", \ - "[M] has tackled down [name]!", null, COMBAT_MESSAGE_RANGE) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + log_combat(M, src, "attacked") + if(!affecting) + affecting = get_bodypart(BODY_ZONE_CHEST) + if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful + return 1 + apply_damage(damage, BRUTE, affecting) + + else + playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to lunge at [name]!", \ + "[M] has attempted to lunge at [name]!", null, COMBAT_MESSAGE_RANGE) + + else + var/obj/item/I = null + playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) + if(prob(95)) + Knockdown(20) + visible_message("[M] has tackled down [name]!", \ + "[M] has tackled down [name]!", null, COMBAT_MESSAGE_RANGE) + else + I = get_active_held_item() + if(dropItemToGround(I)) + visible_message("[M] has disarmed [name]!", "[M] has disarmed [name]!", null, COMBAT_MESSAGE_RANGE) else - I = get_active_held_item() - if(dropItemToGround(I)) - visible_message("[M] has disarmed [name]!", "[M] has disarmed [name]!", null, COMBAT_MESSAGE_RANGE) - else - I = null - log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]") - updatehealth() - + I = null + log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]") + updatehealth() /mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M) . = ..() diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index f5dd982ad5..d4f07e531e 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -36,7 +36,19 @@ /mob/living/proc/on_hit(obj/item/projectile/P) return +/mob/living/proc/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0) + var/block_chance_modifier = round(damage / -3) + for(var/obj/item/I in held_items) + if(!istype(I, /obj/item/clothing)) + var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example + if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type)) + return TRUE + return FALSE + /mob/living/bullet_act(obj/item/projectile/P, def_zone) + if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration)) + P.on_hit(src, 100, def_zone) + return 2 var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null) if(!P.nodamage) apply_damage(P.damage, P.damage_type, def_zone, armor) @@ -242,6 +254,17 @@ visible_message("[user] attempted to touch [src]!") return TRUE +/mob/living/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) + to_chat(user, "You don't want to hurt [src]!") + return TRUE + var/hulk_verb = pick("smash","pummel") + if(user != src && check_shields(user, 15, "the [hulk_verb]ing")) + return TRUE + ..() + return FALSE + /mob/living/attack_slime(mob/living/simple_animal/slime/M) if(!SSticker.HasRoundStarted()) to_chat(M, "You cannot attack people before the game has started.") @@ -295,6 +318,8 @@ if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH)) to_chat(M, "You can't bite with your mouth covered!") return FALSE + if(check_shields(M, 0, "the [M.name]")) + return FALSE M.do_attack_animation(src, ATTACK_EFFECT_BITE) if (prob(75)) log_combat(M, src, "attacked") @@ -331,20 +356,23 @@ return FALSE /mob/living/attack_alien(mob/living/carbon/alien/humanoid/M) + if((M != src) && M.a_intent != INTENT_HELP && check_shields(M, 0, "the [M.name]")) + visible_message("[M] attempted to touch [src]!") + return FALSE switch(M.a_intent) - if ("help") + if (INTENT_HELP) visible_message("[M] caresses [src] with its scythe like arm.") return FALSE - if ("grab") + if (INTENT_GRAB) grabbedby(M) return FALSE - if("harm") + if(INTENT_HARM) if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE M.do_attack_animation(src) return TRUE - if("disarm") + if(INTENT_DISARM) M.do_attack_animation(src, ATTACK_EFFECT_DISARM) return TRUE diff --git a/code/modules/mob/living/silicon/ai/ai_defense.dm b/code/modules/mob/living/silicon/ai/ai_defense.dm index 8799d34a08..97d26f672a 100644 --- a/code/modules/mob/living/silicon/ai/ai_defense.dm +++ b/code/modules/mob/living/silicon/ai/ai_defense.dm @@ -1,20 +1,3 @@ -//ATTACK HAND IGNORING PARENT RETURN VALUE -/mob/living/silicon/ai/attack_hand(mob/living/carbon/human/M) - . = ..() - if(.) //the attack was blocked - return - switch(M.a_intent) - if ("help") - M.visible_message("[M] pets [src].", \ - "You pet [src].") - if("grab") - grabbedby(M) - else - M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - playsound(src.loc, 'sound/effects/bang.ogg', 10, 1) - visible_message("[M] punches [src], but doesn't leave a dent.", \ - "[M] punches [src], but doesn't leave a dent.", null, COMBAT_MESSAGE_RANGE) - /mob/living/silicon/ai/attacked_by(obj/item/I, mob/living/user, def_zone) . = ..() if(!.) @@ -22,13 +5,6 @@ if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt. spark_system.start() - -/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M) - if(!SSticker.HasRoundStarted()) - to_chat(M, "You cannot attack people before the game has started.") - return - ..() - /mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user) return //immune to slimes diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm index 647951ed4e..f8fc5faaab 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -26,16 +26,14 @@ fold_in(force = 1) Knockdown(200) +//ATTACK HAND IGNORING PARENT RETURN VALUE /mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user) - . = ..() - if(.) - return switch(user.a_intent) - if("help") + if(INTENT_HELP) visible_message("[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.") - if("disarm") + if(INTENT_DISARM) visible_message("[user] boops [src] on the head!") - if("harm") + if(INTENT_HARM) user.do_attack_animation(src) if (user.name == master) visible_message("Responding to its master's touch, [src] disengages its holochassis emitter, rapidly losing coherence.") @@ -44,14 +42,19 @@ if(user.put_in_hands(card)) user.visible_message("[user] promptly scoops up [user.p_their()] pAI's card.") else + if(HAS_TRAIT(user, TRAIT_PACIFISM)) + to_chat(user, "You don't want to hurt [src]!") + return visible_message("[user] stomps on [src]!.") take_holo_damage(2) + else + grabbedby(user) -/mob/living/silicon/pai/bullet_act(obj/item/projectile/Proj) - if(Proj.stun) +/mob/living/silicon/pai/bullet_act(obj/item/projectile/P, def_zone) + if(P.stun) fold_in(force = TRUE) - src.visible_message("The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!") - . = ..(Proj) + visible_message("The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!") + . = ..() /mob/living/silicon/pai/stripPanelUnequip(obj/item/what, mob/who, where) //prevents stripping to_chat(src, "Your holochassis stutters and warps intensely as you attempt to interact with the object, forcing you to cease lest the field fail.") diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 0f09b6f62a..ddf2da2343 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -14,6 +14,9 @@ return ..() /mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M) + . = ..() + if(!.) // the attack was blocked or was help/grab intent + return if (M.a_intent == INTENT_DISARM) if(!(lying)) M.do_attack_animation(src, ATTACK_EFFECT_DISARM) @@ -30,9 +33,6 @@ visible_message("[M] has forced back [src]!", \ "[M] has forced back [src]!", null, COMBAT_MESSAGE_RANGE) playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1) - else - ..() - return /mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M) if(..()) //successful slime shock @@ -56,23 +56,17 @@ //ATTACK HAND IGNORING PARENT RETURN VALUE /mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user) add_fingerprint(user) - if(opened && !wiresexposed && !issilicon(user)) - if(cell) - cell.update_icon() - cell.add_fingerprint(user) - user.put_in_active_hand(cell) - to_chat(user, "You remove \the [cell].") - cell = null - update_icons() - diag_hud_set_borgcell() + if(opened && !wiresexposed && cell && !issilicon(user)) + cell.update_icon() + cell.add_fingerprint(user) + user.put_in_active_hand(cell) + to_chat(user, "You remove \the [cell].") + cell = null + update_icons() + diag_hud_set_borgcell() if(!opened) - if(..()) // hulk attack - spark_system.start() - spawn(0) - step_away(src,user,15) - sleep(3) - step_away(src,user,15) + return ..() /mob/living/silicon/robot/fire_act() if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them @@ -182,9 +176,9 @@ if (stat != DEAD) adjustBruteLoss(30) -/mob/living/silicon/robot/bullet_act(var/obj/item/projectile/Proj) - ..(Proj) +/mob/living/silicon/robot/bullet_act(obj/item/projectile/P, def_zone) + ..() updatehealth() - if(prob(75) && Proj.damage > 0) + if(prob(75) && P.damage > 0) spark_system.start() return 2 diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 482ecc429f..80a5058ed4 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -6,7 +6,10 @@ return 2 /mob/living/silicon/attack_alien(mob/living/carbon/alien/humanoid/M) - if(..()) //if harm or disarm intent + . = ..() + if(!.) // the attack was blocked or was help/grab intent + return + if(M.a_intent == INTENT_HARM) var/damage = 20 if (prob(90)) log_combat(M, src, "attacked") @@ -53,9 +56,11 @@ if(L.a_intent == INTENT_HELP) visible_message("[L.name] rubs its head against [src].") -/mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) +/mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) if(user.a_intent == INTENT_HARM) - ..(user, 1) + . = ..(user, TRUE) + if(.) + return adjustBruteLoss(rand(10, 15)) playsound(loc, "punch", 25, 1, -1) visible_message("[user] has punched [src]!", \ @@ -63,6 +68,22 @@ return 1 return 0 +/mob/living/silicon/attack_hand(mob/living/carbon/human/M) + . = ..() + if(.) //the attack was blocked + return + switch(M.a_intent) + if (INTENT_HELP) + M.visible_message("[M] pets [src].", \ + "You pet [src].") + if(INTENT_GRAB) + grabbedby(M) + else + M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) + playsound(src.loc, 'sound/effects/bang.ogg', 10, 1) + visible_message("[M] punches [src], but doesn't leave a dent.", \ + "[M] punches [src], but doesn't leave a dent.", null, COMBAT_MESSAGE_RANGE) + /mob/living/silicon/attack_drone(mob/living/simple_animal/drone/M) if(M.a_intent == INTENT_HARM) return @@ -93,19 +114,22 @@ M.visible_message("[M] is thrown off of [src]!") flash_act(affect_silicon = 1) -/mob/living/silicon/bullet_act(obj/item/projectile/Proj) - if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - adjustBruteLoss(Proj.damage) - if(prob(Proj.damage*1.5)) +/mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone) + if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration)) + P.on_hit(src, 100, def_zone) + return 2 + if((P.damage_type == BRUTE || P.damage_type == BURN)) + adjustBruteLoss(P.damage) + if(prob(P.damage*1.5)) for(var/mob/living/M in buckled_mobs) M.visible_message("[M] is knocked off of [src]!") unbuckle_mob(M) M.Knockdown(40) - if(Proj.stun || Proj.knockdown) + if(P.stun || P.knockdown) for(var/mob/living/M in buckled_mobs) unbuckle_mob(M) - M.visible_message("[M] is knocked off of [src] by the [Proj]!") - Proj.on_hit(src) + M.visible_message("[M] is knocked off of [src] by the [P]!") + P.on_hit(src) return 2 /mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/static) diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index e74b29be44..4542f140d4 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -5,18 +5,18 @@ if(.) //the attack was blocked return switch(M.a_intent) - if("help") + if(INTENT_HELP) if (health > 0) visible_message("[M] [response_help] [src].") playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - if("grab") + if(INTENT_GRAB) if(grab_state >= GRAB_AGGRESSIVE && isliving(pulling)) vore_attack(M, pulling) else grabbedby(M) - if("harm", "disarm") + if(INTENT_HARM, INTENT_DISARM) if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt [src]!") return @@ -29,12 +29,11 @@ updatehealth() return TRUE -/mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) +/mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) if(user.a_intent == INTENT_HARM) - if(HAS_TRAIT(user, TRAIT_PACIFISM)) - to_chat(user, "You don't want to hurt [src]!") - return FALSE - ..(user, 1) + . = ..(user, TRUE) + if(.) + return playsound(loc, "punch", 25, 1, -1) visible_message("[user] has punched [src]!", \ "[user] has punched [src]!", null, COMBAT_MESSAGE_RANGE) @@ -43,10 +42,9 @@ /mob/living/simple_animal/attack_paw(mob/living/carbon/monkey/M) if(..()) //successful monkey bite. - if(stat != DEAD) - var/damage = rand(1, 3) - attack_threshold_check(damage) - return 1 + var/damage = rand(1, 3) + attack_threshold_check(damage) + return 1 if (M.a_intent == INTENT_HELP) if (health > 0) visible_message("[M.name] [response_help] [src].") @@ -54,20 +52,21 @@ /mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M) - if(..()) //if harm or disarm intent. - if(M.a_intent == INTENT_DISARM) - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - visible_message("[M] [response_disarm] [name]!", \ - "[M] [response_disarm] [name]!", null, COMBAT_MESSAGE_RANGE) - log_combat(M, src, "disarmed") - else - var/damage = rand(15, 30) - visible_message("[M] has slashed at [src]!", \ - "[M] has slashed at [src]!", null, COMBAT_MESSAGE_RANGE) - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - attack_threshold_check(damage) - log_combat(M, src, "attacked") - return 1 + . = ..() + if(!.) // the attack was blocked or was help/grab intent + return + if(M.a_intent == INTENT_DISARM) + playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) + visible_message("[M] [response_disarm] [name]!", \ + "[M] [response_disarm] [name]!", null, COMBAT_MESSAGE_RANGE) + log_combat(M, src, "disarmed") + else + var/damage = rand(15, 30) + visible_message("[M] has slashed at [src]!", \ + "[M] has slashed at [src]!", null, COMBAT_MESSAGE_RANGE) + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + attack_threshold_check(damage) + log_combat(M, src, "attacked") /mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L) . = ..() diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index 1c19cd82a1..5ca3f1f758 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -112,7 +112,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, mode = BOT_HUNT /mob/living/simple_animal/bot/honkbot/attack_hand(mob/living/carbon/human/H) - if(H.a_intent == "harm") + if(H.a_intent == INTENT_HARM) retaliate(H) addtimer(CALLBACK(src, .proc/react_buzz), 5) return ..() diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 3a21a04bf9..de43098496 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -231,9 +231,9 @@ /mob/living/simple_animal/pet/cat/attack_hand(mob/living/carbon/human/M) . = ..() switch(M.a_intent) - if("help") + if(INTENT_HELP) wuv(1, M) - if("harm") + if(INTENT_HARM) wuv(-1, M) /mob/living/simple_animal/pet/cat/proc/wuv(change, mob/M) @@ -288,7 +288,9 @@ D.frost_donut() /mob/living/simple_animal/pet/cat/cak/attack_hand(mob/living/L) - ..() + . = ..() + if(.) //the attack was blocked + return if(L.a_intent == INTENT_HARM && L.reagents && !stat) L.reagents.add_reagent("nutriment", 0.4) L.reagents.add_reagent("vitamin", 0.4) diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index c194233c42..366a1ff20f 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -638,9 +638,9 @@ /mob/living/simple_animal/pet/dog/attack_hand(mob/living/carbon/human/M) . = ..() switch(M.a_intent) - if("help") + if(INTENT_HELP) wuv(1,M) - if("harm") + if(INTENT_HARM) wuv(-1,M) /mob/living/simple_animal/pet/dog/proc/wuv(change, mob/M) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm index 33031fd80c..b2f58bc01b 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm @@ -31,26 +31,24 @@ //ATTACK HAND IGNORING PARENT RETURN VALUE /mob/living/simple_animal/drone/attack_hand(mob/user) - if(ishuman(user)) - if(stat == DEAD || status_flags & GODMODE || !can_be_held) - ..() - return - if(user.get_active_held_item()) - to_chat(user, "Your hands are full!") - return - visible_message("[user] starts picking up [src].", \ - "[user] starts picking you up!") - if(!do_after(user, 20, target = src)) - return - visible_message("[user] picks up [src]!", \ - "[user] picks you up!") - if(buckled) - to_chat(user, "[src] is buckled to [buckled] and cannot be picked up!") - return - to_chat(user, "You pick [src] up.") - drop_all_held_items() - var/obj/item/clothing/head/mob_holder/drone/DH = new(get_turf(src), src) - user.put_in_hands(DH) + if(user.a_intent != INTENT_HELP || !LAZYLEN(user.held_items) || stat == DEAD || status_flags & GODMODE || !can_be_held) + return ..() + if(user.get_active_held_item()) + to_chat(user, "Your hands are full!") + return + visible_message("[user] starts picking up [src].", \ + "[user] starts picking you up!") + if(!do_after(user, 20, target = src)) + return + visible_message("[user] picks up [src]!", \ + "[user] picks you up!") + if(buckled) + to_chat(user, "[src] is buckled to [buckled] and cannot be picked up!") + return + to_chat(user, "You pick [src] up.") + drop_all_held_items() + var/obj/item/clothing/head/mob_holder/drone/DH = new(get_turf(src), src) + user.put_in_hands(DH) /mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user) var/mob/dead/observer/G = get_ghost() diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm index dbaa8ab5fa..da8101ee6a 100644 --- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm +++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm @@ -166,7 +166,9 @@ ..() /mob/living/simple_animal/hostile/mushroom/attack_hand(mob/living/carbon/human/M) - ..() + . = ..() + if(.) // the attack was blocked + return if(M.a_intent == INTENT_HARM) Bruise() diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 2001c61e12..4deb62aac2 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -61,7 +61,7 @@ var/mood = "" // To show its face var/mutator_used = FALSE //So you can't shove a dozen mutators into a single slime var/force_stasis = FALSE - + do_footstep = TRUE var/static/regex/slime_name_regex = new("\\w+ (baby|adult) slime \\(\\d+\\)") @@ -320,9 +320,11 @@ attacked += 10 /mob/living/simple_animal/slime/attack_alien(mob/living/carbon/alien/humanoid/M) - if(..()) //if harm or disarm intent. - attacked += 10 - discipline_slime(M) + . = ..() + if(!.) // the attack was blocked or was help/grab intent + return + attacked += 10 + discipline_slime(M) /mob/living/simple_animal/slime/attackby(obj/item/W, mob/living/user, params) From bddb43787296906d763a31f5c59eab13490723f0 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Mon, 18 Nov 2019 18:30:46 +0100 Subject: [PATCH 004/148] It works now. --- code/game/objects/items/melee/misc.dm | 5 +- code/game/objects/items/robot/robot_items.dm | 8 +- code/game/objects/items/stunbaton.dm | 8 +- .../abductor/equipment/abduction_gear.dm | 8 +- .../mob/living/carbon/alien/alien_defense.dm | 25 ++--- .../carbon/alien/humanoid/caste/hunter.dm | 7 +- .../carbon/alien/humanoid/humanoid_defense.dm | 4 +- .../carbon/alien/larva/larva_defense.dm | 3 + .../mob/living/carbon/carbon_defense.dm | 44 ++++----- .../mob/living/carbon/human/human_defense.dm | 98 +++++++------------ .../mob/living/carbon/monkey/combat.dm | 21 ++-- .../living/carbon/monkey/monkey_defense.dm | 74 ++++++++------ code/modules/mob/living/living_defense.dm | 67 ++++++++++--- .../mob/living/silicon/robot/robot_defense.dm | 29 +++--- .../mob/living/silicon/silicon_defense.dm | 17 ++-- .../living/simple_animal/animal_defense.dm | 7 +- .../simple_animal/guardian/types/charger.dm | 6 +- .../mob/living/simple_animal/slime/slime.dm | 35 +++---- .../living/silicon/robot/dogborg_equipment.dm | 7 +- 19 files changed, 244 insertions(+), 229 deletions(-) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index d7c2f7f4f6..1120e1856d 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -216,10 +216,11 @@ return else if(last_hit < world.time) + if(target.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) + playsound(target, 'sound/weapons/genhit.ogg', 50, 1) + return if(ishuman(target)) var/mob/living/carbon/human/H = target - if (H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) - return if(check_martial_counter(H, user)) return playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 77bc7ed810..c09f5b1b65 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -11,11 +11,9 @@ var/charge_cost = 30 /obj/item/borg/stun/attack(mob/living/M, mob/living/user) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.check_shields(src, 0, "[M]'s [name]", MELEE_ATTACK)) - playsound(M, 'sound/weapons/genhit.ogg', 50, 1) - return FALSE + if(M.check_shields(src, 0, "[M]'s [name]", MELEE_ATTACK)) + playsound(M, 'sound/weapons/genhit.ogg', 50, 1) + return FALSE if(iscyborg(user)) var/mob/living/silicon/robot/R = user if(!R.cell.use(charge_cost)) diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index 47d9af2795..e1e599b1b6 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -168,11 +168,9 @@ /obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user) - if(ishuman(L)) - var/mob/living/carbon/human/H = L - if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that - playsound(L, 'sound/weapons/genhit.ogg', 50, 1) - return FALSE + if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that + playsound(L, 'sound/weapons/genhit.ogg', 50, 1) + return FALSE var/stunpwr = stunforce var/obj/item/stock_parts/cell/our_cell = get_cell() if(!our_cell) diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm index 37652d1887..ee5000a3b8 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm @@ -482,11 +482,9 @@ user.do_attack_animation(L) - if(ishuman(L)) - var/mob/living/carbon/human/H = L - if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) - playsound(L, 'sound/weapons/genhit.ogg', 50, 1) - return 0 + if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) + playsound(L, 'sound/weapons/genhit.ogg', 50, 1) + return 0 switch (mode) if(BATON_STUN) diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index 839239a888..bdc691ce49 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -17,8 +17,9 @@ In all, this is a lot like the monkey code. /N */ /mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M) . = ..() + if(!.) // the attack was blocked or was help/grab intent + return switch(M.a_intent) - if (INTENT_HELP) if(!recoveringstam) resting = 0 @@ -27,10 +28,7 @@ In all, this is a lot like the monkey code. /N AdjustUnconscious(-60) AdjustSleeping(-100) visible_message("[M.name] nuzzles [src] trying to wake [p_them()] up!") - if(INTENT_DISARM, INTENT_HARM) - if(!.) // the attack was blocked or was help/grab intent - return if(health > 0) M.do_attack_animation(src, ATTACK_EFFECT_BITE) playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) @@ -69,7 +67,8 @@ In all, this is a lot like the monkey code. /N /mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M) - if(..()) + . = ..() + if(.) //successful monkey bite. var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) apply_damage(rand(1, 3), BRUTE, affecting) @@ -93,13 +92,15 @@ In all, this is a lot like the monkey code. /N adjustStaminaLoss(damage) /mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime attack - var/damage = rand(5, 35) - if(M.is_adult) - damage = rand(10, 40) - adjustBruteLoss(damage) - log_combat(M, src, "attacked") - updatehealth() + . = ..() + if(!.) //unsuccessful slime attack + return + var/damage = rand(5, 35) + if(M.is_adult) + damage = rand(10, 40) + adjustBruteLoss(damage) + log_combat(M, src, "attacked") + updatehealth() /mob/living/carbon/alien/ex_act(severity, target, origin) if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src)) diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index fe682b5c99..d1ed09665b 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -63,12 +63,7 @@ if(A) if(isliving(A)) var/mob/living/L = A - var/blocked = FALSE - if(ishuman(A)) - var/mob/living/carbon/human/H = A - if(H.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK)) - blocked = TRUE - if(!blocked) + if(!L.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK)) L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") L.Knockdown(100) sleep(2)//Runtime prevention (infinite bump() calls on hulks) diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm index 468abf251a..1d613db07a 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm @@ -42,7 +42,7 @@ log_combat(M, src, "attacked") else playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to punch [src]!", \ + visible_message("[M] has attempted to punch [src]!", \ "[M] has attempted to punch [src]!", null, COMBAT_MESSAGE_RANGE) if (INTENT_DISARM) @@ -61,7 +61,7 @@ "[M] has disarmed [src]!", null, COMBAT_MESSAGE_RANGE) else playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to disarm [src]!",\ + visible_message("[M] has attempted to disarm [src]!",\ "[M] has attempted to disarm [src]!", null, COMBAT_MESSAGE_RANGE) /mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) diff --git a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm index 88c34f4387..7dabcf5abf 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm @@ -25,6 +25,9 @@ . = ..(user, TRUE) if(.) return + playsound(loc, "punch", 25, 1, -1) + visible_message("[user] has pummeled [src]!", \ + "[user] has pummeled [src]!", null, COMBAT_MESSAGE_RANGE) adjustBruteLoss(5 + rand(1,9)) new /datum/forced_movement(src, get_step_away(user,src, 30), 1) return 1 diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index d045e5361d..815b0a909b 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -62,10 +62,6 @@ throw_mode_off() return TRUE -/mob/living/carbon/can_embed(obj/item/I) - if(I.get_sharpness() || is_pointed(I) || is_type_in_typecache(I, GLOB.can_embed_types)) - return TRUE - /mob/living/carbon/embed_item(obj/item/I) throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) var/obj/item/bodypart/L = pick(bodyparts) @@ -170,7 +166,8 @@ help_shake_act(M) return 0 - if(..()) //successful monkey bite. + . = ..() + if(.) //successful monkey bite. for(var/thing in M.diseases) var/datum/disease/D = thing ForceContractDisease(D) @@ -178,26 +175,27 @@ /mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime attack - if(M.powerlevel > 0) - var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10 - if(prob(stunprob)) - M.powerlevel -= 3 - if(M.powerlevel < 0) - M.powerlevel = 0 + . = ..() + if(!.) + return + if(M.powerlevel > 0) + var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10 + if(prob(stunprob)) + M.powerlevel -= 3 + if(M.powerlevel < 0) + M.powerlevel = 0 - visible_message("The [M.name] has shocked [src]!", \ - "The [M.name] has shocked [src]!") + visible_message("The [M.name] has shocked [src]!", \ + "The [M.name] has shocked [src]!") - do_sparks(5, TRUE, src) - var/power = M.powerlevel + rand(0,3) - Knockdown(power*20) - if(stuttering < power) - stuttering = power - if (prob(stunprob) && M.powerlevel >= 8) - adjustFireLoss(M.powerlevel * rand(6,10)) - updatehealth() - return 1 + do_sparks(5, TRUE, src) + var/power = M.powerlevel + rand(0,3) + Knockdown(power*20) + if(stuttering < power) + stuttering = power + if (prob(stunprob) && M.powerlevel >= 8) + adjustFireLoss(M.powerlevel * rand(6,10)) + updatehealth() /mob/living/carbon/proc/dismembering_strike(mob/living/attacker, dam_zone) if(!attacker.limb_destroyer) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 7e7cb18d37..a8d1eb8180 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -61,40 +61,12 @@ P.setAngle(rand(0, 360))//SHING return FALSE - if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself - if(P.is_reflectable) - if(check_reflect(def_zone)) // Checks if you've passed a reflection% check - visible_message("The [P.name] gets reflected by [src]!", \ - "The [P.name] gets reflected by [src]!") - // Find a turf near or on the original location to bounce to - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/turf/curloc = get_turf(src) - - // redirect the projectile - P.original = locate(new_x, new_y, P.z) - P.starting = curloc - P.firer = src - P.yo = new_y - curloc.y - P.xo = new_x - curloc.x - var/new_angle_s = P.Angle + rand(120,240) - while(new_angle_s > 180) // Translate to regular projectile degrees - new_angle_s -= 360 - P.setAngle(new_angle_s) - - return -1 // complete projectile permutation - return ..() -/mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object - if(wear_suit) - if(wear_suit.IsReflect(def_zone) == 1) - return 1 - for(var/obj/item/I in held_items) - if(I.IsReflect(def_zone) == 1) - return 1 - return 0 +/mob/living/carbon/human/check_reflect(def_zone) + if(wear_suit?.IsReflect(def_zone)) + return TRUE + return ..() /mob/living/carbon/human/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0) . = ..() @@ -111,6 +83,11 @@ return TRUE return FALSE +/mob/living/carbon/human/can_embed(obj/item/I) + if(I.get_sharpness() || is_pointed(I) || is_type_in_typecache(I, GLOB.can_embed_types)) + return TRUE + return FALSE + /mob/living/carbon/human/proc/check_block() if(mind) if(mind.martial_art && prob(mind.martial_art.block_chance) && mind.martial_art.can_use(src) && in_throw_mode && !incapacitated(FALSE, TRUE)) @@ -179,8 +156,7 @@ if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST) if(M.a_intent == INTENT_HELP) - ..() //shaking - return 0 + return ..() //shaking if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stunned instead. var/obj/item/I = get_active_held_item() @@ -247,26 +223,23 @@ "[M] has tackled down [src]!") /mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L) - - if(..()) //successful larva bite. - var/damage = rand(1, 3) - if(check_shields(L, damage, "the [L.name]")) - return 0 - if(stat != DEAD) - L.amount_grown = min(L.amount_grown + damage, L.max_grown) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) - if(!affecting) - affecting = get_bodypart(BODY_ZONE_CHEST) - var/armor_block = run_armor_check(affecting, "melee") - apply_damage(damage, BRUTE, affecting, armor_block) + . = ..() + if(!.) //unsuccessful larva bite. + return + var/damage = rand(1, 3) + if(stat != DEAD) + L.amount_grown = min(L.amount_grown + damage, L.max_grown) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) + if(!affecting) + affecting = get_bodypart(BODY_ZONE_CHEST) + var/armor_block = run_armor_check(affecting, "melee") + apply_damage(damage, BRUTE, affecting, armor_block) /mob/living/carbon/human/attack_animal(mob/living/simple_animal/M) . = ..() if(.) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - if(check_shields(M, damage, "the [M.name]", MELEE_ATTACK, M.armour_penetration)) - return FALSE var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) if(!dam_zone) //Dismemberment successful return TRUE @@ -278,23 +251,22 @@ /mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime attack - var/damage = rand(5, 25) - if(M.is_adult) - damage = rand(10, 35) + . = ..() + if(!.) //unsuccessful slime attack + return + var/damage = rand(5, 25) + if(M.is_adult) + damage = rand(10, 35) - if(check_shields(M, damage, "the [M.name]")) - return 0 + var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) + if(!dam_zone) //Dismemberment successful + return 1 - var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) - if(!dam_zone) //Dismemberment successful - return 1 - - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) - if(!affecting) - affecting = get_bodypart(BODY_ZONE_CHEST) - var/armor_block = run_armor_check(affecting, "melee") - apply_damage(damage, BRUTE, affecting, armor_block) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) + if(!affecting) + affecting = get_bodypart(BODY_ZONE_CHEST) + var/armor_block = run_armor_check(affecting, "melee") + apply_damage(damage, BRUTE, affecting, armor_block) /mob/living/carbon/human/mech_melee_attack(obj/mecha/M) diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm index 59f694e0f6..30afa491c5 100644 --- a/code/modules/mob/living/carbon/monkey/combat.dm +++ b/code/modules/mob/living/carbon/monkey/combat.dm @@ -372,20 +372,15 @@ retaliate(M) return ..() +/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L) + if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB)) + retaliate(user) + return ..() + /mob/living/carbon/monkey/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) - if(user.a_intent == INTENT_HARM) - if(prob(MONKEY_RETALIATE_HARM_PROB)) - retaliate(user) - . = ..(user, TRUE) - if(.) - return - var/hulk_verb = pick("smash","pummel") - playsound(loc, user.dna.species.attack_sound, 25, 1, -1) - var/message = "[user] has [hulk_verb]ed [src]!" - visible_message("[message]", \ - "[message]") - adjustBruteLoss(15) - return 1 + if(user.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB)) + retaliate(user) + return ..() /mob/living/carbon/monkey/attack_paw(mob/living/L) if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB)) diff --git a/code/modules/mob/living/carbon/monkey/monkey_defense.dm b/code/modules/mob/living/carbon/monkey/monkey_defense.dm index 6d2d7bcbcf..32e3d21ee2 100644 --- a/code/modules/mob/living/carbon/monkey/monkey_defense.dm +++ b/code/modules/mob/living/carbon/monkey/monkey_defense.dm @@ -6,25 +6,41 @@ ..() /mob/living/carbon/monkey/attack_paw(mob/living/M) - if(..()) //successful monkey bite. - var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) - if(!affecting) - affecting = get_bodypart(BODY_ZONE_CHEST) - if(M.limb_destroyer) - dismembering_strike(M, affecting.body_zone) - var/dmg = rand(1, 5) - apply_damage(dmg, BRUTE, affecting) + . = ..() + if(!.) //unsuccessful monkey bite. + return + var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) + if(!affecting) + affecting = get_bodypart(BODY_ZONE_CHEST) + if(M.limb_destroyer) + dismembering_strike(M, affecting.body_zone) + var/dmg = rand(1, 5) + apply_damage(dmg, BRUTE, affecting) /mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L) - if(..()) //successful larva bite. - var/damage = rand(1, 3) - if(stat != DEAD) - L.amount_grown = min(L.amount_grown + damage, L.max_grown) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) - if(!affecting) - affecting = get_bodypart(BODY_ZONE_CHEST) - apply_damage(damage, BRUTE, affecting) + . = ..() + if(!.) //unsuccessful larva bite + return + var/damage = rand(1, 3) + if(stat != DEAD) + L.amount_grown = min(L.amount_grown + damage, L.max_grown) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) + if(!affecting) + affecting = get_bodypart(BODY_ZONE_CHEST) + apply_damage(damage, BRUTE, affecting) + +/mob/living/carbon/monkey/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + . = ..(user, TRUE) + if(.) + return + var/hulk_verb = pick("smash","pummel") + playsound(loc, user.dna.species.attack_sound, 25, 1, -1) + var/message = "[user] has [hulk_verb]ed [src]!" + visible_message("[message]", \ + "[message]") + adjustBruteLoss(15) + return TRUE /mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M) . = ..() @@ -135,17 +151,19 @@ apply_damage(damage, M.melee_damage_type, affecting) /mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime attack - var/damage = rand(5, 35) - if(M.is_adult) - damage = rand(20, 40) - var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) - if(!dam_zone) //Dismemberment successful - return 1 - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) - if(!affecting) - affecting = get_bodypart(BODY_ZONE_CHEST) - apply_damage(damage, BRUTE, affecting) + . = ..() + if(!.) //unsuccessful slime attack + return + var/damage = rand(5, 35) + if(M.is_adult) + damage = rand(20, 40) + var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) + if(!dam_zone) //Dismemberment successful + return 1 + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) + if(!affecting) + affecting = get_bodypart(BODY_ZONE_CHEST) + apply_damage(damage, BRUTE, affecting) /mob/living/carbon/monkey/acid_act(acidpwr, acid_volume, bodyzone_hit) . = 1 diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index d4f07e531e..e95e994734 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -45,10 +45,41 @@ return TRUE return FALSE +/mob/living/proc/check_reflect(def_zone) //Reflection checks for anything in your hands, based on the reflection chance of the object(s) + for(var/obj/item/I in held_items) + if(I.IsReflect(def_zone)) + return TRUE + return FALSE + +/mob/living/proc/reflect_bullet_check(obj/item/projectile/P, def_zone) + if(P.is_reflectable && check_reflect(def_zone)) // Checks if you've passed a reflection% check + visible_message("The [P.name] gets reflected by [src]!", \ + "The [P.name] gets reflected by [src]!") + // Find a turf near or on the original location to bounce to + if(P.starting) + var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) + var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) + var/turf/curloc = get_turf(src) + // redirect the projectile + P.original = locate(new_x, new_y, P.z) + P.starting = curloc + P.firer = src + P.yo = new_y - curloc.y + P.xo = new_x - curloc.x + var/new_angle_s = P.Angle + rand(120,240) + while(new_angle_s > 180) // Translate to regular projectile degrees + new_angle_s -= 360 + P.setAngle(new_angle_s) + return TRUE + return FALSE + /mob/living/bullet_act(obj/item/projectile/P, def_zone) - if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration)) - P.on_hit(src, 100, def_zone) - return 2 + if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself + if(reflect_bullet_check(P, def_zone)) + return -1 // complete projectile permutation + if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration)) + P.on_hit(src, 100, def_zone) + return 2 var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null) if(!P.nodamage) apply_damage(P.damage, P.damage_type, def_zone, armor) @@ -279,6 +310,12 @@ to_chat(M, "You don't want to hurt anyone!") return FALSE + var/damage = rand(5, 35) + if(M.is_adult) + damage = rand(20, 40) + if(check_shields(M, damage, "the [M.name]")) + return FALSE + if (stat != DEAD) log_combat(M, src, "attacked") M.do_attack_animation(src) @@ -295,7 +332,8 @@ if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE - + if(check_shields(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", MELEE_ATTACK, M.armour_penetration)) + return FALSE if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) M.do_attack_animation(src) @@ -306,10 +344,6 @@ /mob/living/attack_paw(mob/living/carbon/monkey/M) - if(isturf(loc) && istype(loc.loc, /area/start)) - to_chat(M, "No attacking people at spawn, you jackass.") - return FALSE - if (M.a_intent == INTENT_HARM) if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") @@ -334,15 +368,16 @@ /mob/living/attack_larva(mob/living/carbon/alien/larva/L) switch(L.a_intent) - if("help") + if(INTENT_HELP) visible_message("[L.name] rubs its head against [src].") return FALSE else if(HAS_TRAIT(L, TRAIT_PACIFISM)) to_chat(L, "You don't want to hurt anyone!") - return - + return FALSE + if(L != src && check_shields(L, rand(1, 3), "the [L.name]")) + return FALSE L.do_attack_animation(src) if(prob(90)) log_combat(L, src, "attacked") @@ -353,7 +388,6 @@ else visible_message("[L.name] has attempted to bite [src]!", \ "[L.name] has attempted to bite [src]!", null, COMBAT_MESSAGE_RANGE) - return FALSE /mob/living/attack_alien(mob/living/carbon/alien/humanoid/M) if((M != src) && M.a_intent != INTENT_HELP && check_shields(M, 0, "the [M.name]")) @@ -361,7 +395,8 @@ return FALSE switch(M.a_intent) if (INTENT_HELP) - visible_message("[M] caresses [src] with its scythe like arm.") + if(!isalien(src)) //I know it's ugly, but the alien vs alien attack_alien behaviour is a bit different. + visible_message("[M] caresses [src] with its scythe like arm.") return FALSE if (INTENT_GRAB) grabbedby(M) @@ -370,10 +405,12 @@ if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE - M.do_attack_animation(src) + if(!isalien(src)) + M.do_attack_animation(src) return TRUE if(INTENT_DISARM) - M.do_attack_animation(src, ATTACK_EFFECT_DISARM) + if(!isalien(src)) + M.do_attack_animation(src, ATTACK_EFFECT_DISARM) return TRUE /mob/living/ex_act(severity, target, origin) diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index ddf2da2343..7e06c66eff 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -13,6 +13,15 @@ spark_system.start() return ..() +/mob/living/silicon/robot/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + . = ..() + if(.) + spark_system.start() + spawn(0) + step_away(src,user,15) + sleep(3) + step_away(src,user,15) + /mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M) . = ..() if(!.) // the attack was blocked or was help/grab intent @@ -35,19 +44,17 @@ playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1) /mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime shock - flash_act() - var/stunprob = M.powerlevel * 7 + 10 - if(prob(stunprob) && M.powerlevel >= 8) - adjustBruteLoss(M.powerlevel * rand(6,10)) - - var/damage = rand(1, 3) - + . = ..() + if(!.) //unsuccessful slime shock + return + var/stunprob = M.powerlevel * 7 + 10 + var/damage = M.powerlevel * rand(6,10) + if(prob(stunprob) && M.powerlevel >= 8) + flash_act(affect_silicon = TRUE) //my borg eyes! if(M.is_adult) - damage = rand(20, 40) + damage += rand(10, 20) else - damage = rand(5, 35) - damage = round(damage / 2) // borgs receive half damage + damage += rand(2, 17) adjustBruteLoss(damage) updatehealth() diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 80a5058ed4..ca8ad25713 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -52,10 +52,6 @@ /mob/living/silicon/attack_paw(mob/living/user) return attack_hand(user) -/mob/living/silicon/attack_larva(mob/living/carbon/alien/larva/L) - if(L.a_intent == INTENT_HELP) - visible_message("[L.name] rubs its head against [src].") - /mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) if(user.a_intent == INTENT_HARM) . = ..(user, TRUE) @@ -65,8 +61,8 @@ playsound(loc, "punch", 25, 1, -1) visible_message("[user] has punched [src]!", \ "[user] has punched [src]!") - return 1 - return 0 + return TRUE + return FALSE /mob/living/silicon/attack_hand(mob/living/carbon/human/M) . = ..() @@ -115,9 +111,12 @@ flash_act(affect_silicon = 1) /mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone) - if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration)) - P.on_hit(src, 100, def_zone) - return 2 + if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself + if(reflect_bullet_check(P, def_zone)) + return -1 // complete projectile permutation + if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration)) + P.on_hit(src, 100, def_zone) + return 2 if((P.damage_type == BRUTE || P.damage_type == BURN)) adjustBruteLoss(P.damage) if(prob(P.damage*1.5)) diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index 4542f140d4..0dfa126e79 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -41,7 +41,8 @@ return TRUE /mob/living/simple_animal/attack_paw(mob/living/carbon/monkey/M) - if(..()) //successful monkey bite. + . = ..() + if(.) //successful larva bite var/damage = rand(1, 3) attack_threshold_check(damage) return 1 @@ -50,7 +51,6 @@ visible_message("[M.name] [response_help] [src].") playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - /mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M) . = ..() if(!.) // the attack was blocked or was help/grab intent @@ -83,7 +83,8 @@ return attack_threshold_check(damage, M.melee_damage_type) /mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime attack + . = ..() + if(.) //successful slime shock var/damage = rand(15, 25) if(M.is_adult) damage = rand(20, 35) diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm index 3ece5d4e27..3719861d63 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm @@ -54,10 +54,8 @@ var/blocked = FALSE if(hasmatchingsummoner(A)) //if the summoner matches don't hurt them blocked = TRUE - if(ishuman(A)) - var/mob/living/carbon/human/H = A - if(H.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK)) - blocked = TRUE + if(L.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK)) + blocked = TRUE if(!blocked) L.drop_all_held_items() L.visible_message("[src] slams into [L]!", "[src] slams into you!") diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 4deb62aac2..affb476534 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -252,33 +252,34 @@ return /mob/living/simple_animal/slime/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime attack - if(M == src) - return - if(buckled) - Feedstop(silent = TRUE) - visible_message("[M] pulls [src] off!") - return - attacked += 5 - if(nutrition >= 100) //steal some nutrition. negval handled in life() - nutrition -= (50 + (40 * M.is_adult)) - M.add_nutrition(50 + (40 * M.is_adult)) - if(health > 0) - M.adjustBruteLoss(-10 + (-10 * M.is_adult)) - M.updatehealth() + . = ..() + if(!. || M == src) //unsuccessful slime shock + return + if(buckled) + Feedstop(silent = TRUE) + visible_message("[M] pulls [src] off!") + return + attacked += 5 + if(nutrition >= 100) //steal some nutrition. negval handled in life() + nutrition -= (50 + (40 * M.is_adult)) + M.add_nutrition(50 + (40 * M.is_adult)) + if(health > 0) + M.adjustBruteLoss(-10 + (-10 * M.is_adult)) + M.updatehealth() /mob/living/simple_animal/slime/attack_animal(mob/living/simple_animal/M) . = ..() if(.) attacked += 10 - /mob/living/simple_animal/slime/attack_paw(mob/living/carbon/monkey/M) - if(..()) //successful monkey bite. + . = ..() + if(.)//successful monkey bite. attacked += 10 /mob/living/simple_animal/slime/attack_larva(mob/living/carbon/alien/larva/L) - if(..()) //successful larva bite. + . = ..() + if(.) //successful larva bite. attacked += 10 /mob/living/simple_animal/slime/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm index 99ba9ad3e2..6f73d5ae84 100644 --- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm +++ b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm @@ -400,12 +400,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm ! if(A) if(isliving(A)) var/mob/living/L = A - var/blocked = 0 - if(ishuman(A)) - var/mob/living/carbon/human/H = A - if(H.check_shields(0, "the [name]", src, attack_type = LEAP_ATTACK)) - blocked = 1 - if(!blocked) + if(!L.check_shields(0, "the [name]", src, attack_type = LEAP_ATTACK)) L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") L.Knockdown(iscarbon(L) ? 60 : 45, override_stamdmg = CLAMP(pounce_stamloss, 0, pounce_stamloss_cap-L.getStaminaLoss())) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice. playsound(src, 'sound/weapons/Egloves.ogg', 50, 1) From d5e7f77c13ca0f86828783ccbbc68de06c7f9758 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Mon, 18 Nov 2019 18:47:34 +0100 Subject: [PATCH 005/148] A --- code/modules/mob/living/carbon/monkey/combat.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm index 30afa491c5..0a21994145 100644 --- a/code/modules/mob/living/carbon/monkey/combat.dm +++ b/code/modules/mob/living/carbon/monkey/combat.dm @@ -374,7 +374,7 @@ /mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L) if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB)) - retaliate(user) + retaliate(L) return ..() /mob/living/carbon/monkey/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) From ccd966ed28ccf7bcfaa6994aa34cde005e6afdb3 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Wed, 4 Dec 2019 20:32:25 +0100 Subject: [PATCH 006/148] Update, fix. --- code/modules/mob/living/living_defense.dm | 2 +- code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 82ebb6e763..39c8435076 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -282,7 +282,7 @@ /mob/living/attack_hand(mob/user) ..() //Ignoring parent return value here. - SEND_SIGNAL(user, COMSIG_MOB_ATTACK_HAND, user, src) + SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user) if((user != src) && user.a_intent != INTENT_HELP && check_shields(user, 0, user.name, attack_type = UNARMED_ATTACK)) log_combat(user, src, "attempted to touch") visible_message("[user] attempted to touch [src]!") diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm index 8c304d8a2b..56c50078c1 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm @@ -26,10 +26,9 @@ Contents: /obj/item/clothing/suit/space/space_ninja/proc/enable_signals() if(!affecting) return - RegisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE), .proc/reduce_stealth) + RegisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE), .proc/reduce_stealth) RegisterSignal(affecting, COMSIG_MOVABLE_BUMP, .proc/bumping_stealth) - /obj/item/clothing/suit/space/space_ninja/proc/reduce_stealth(datum/source) affecting.alpha = min(affecting.alpha + 40, 100) @@ -42,7 +41,7 @@ Contents: return FALSE stealth = !stealth stealth_cooldown = world.time + 5 SECONDS - UnregisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE)) + UnregisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE)) animate(affecting, alpha = 255, time = 3 SECONDS) affecting.visible_message("[affecting.name] appears from thin air!", \ "You are now visible.") From e1f0c52b96f0cf90fb95f9fa7343617c10809660 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 14:13:23 -0800 Subject: [PATCH 007/148] that's storytellers. time for voting --- code/game/gamemodes/dynamic/dynamic.dm | 3 +- .../gamemodes/dynamic/dynamic_rulesets.dm | 2 + .../dynamic/dynamic_rulesets_events.dm | 19 ++++ .../dynamic/dynamic_rulesets_latejoin.dm | 3 + .../dynamic/dynamic_rulesets_midround.dm | 12 +++ .../dynamic/dynamic_rulesets_roundstart.dm | 14 +++ .../storytellers/dynamic_storytellers.dm | 93 +++++++++++++++++++ 7 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index cd9500284b..6566d41e21 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -60,7 +60,8 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) announce_text = "Dynamic mode!" // This needs to be changed maybe reroll_friendly = FALSE; - + // Current storyteller + var/datum/dynamic_storyteller/storyteller = null // Threat logging vars /// The "threat cap", threat shouldn't normally go above this and is used in ruleset calculations var/threat_level = 0 diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets.dm b/code/game/gamemodes/dynamic/dynamic_rulesets.dm index 0c8ec0a2b8..e26eaa03c4 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets.dm @@ -80,6 +80,8 @@ /// Delay for when execute will get called from the time of post_setup (roundstart) or process (midround/latejoin). /// Make sure your ruleset works with execute being called during the game when using this, and that the clean_up proc reverts it properly in case of faliure. var/delay = 0 + /// List of tags for use in storytellers. + var/list/property_weights = list() /datum/dynamic_ruleset/New() ..() diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm index 4ac8cc91d3..0c0dbee820 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm @@ -46,6 +46,7 @@ cost = 10 blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear) requirements = list(70,60,50,50,40,40,40,30,20,15) + property_weights = list("story_potential" = 1, "trust" = 1, "chaos" = 1) high_population_requirement = 15 /datum/dynamic_ruleset/event/pirates/ready(forced = FALSE) @@ -69,6 +70,7 @@ cost = 10 requirements = list(70,60,50,50,40,40,40,30,20,15) high_population_requirement = 15 + property_weights = list("chaos" = 1, "valid" = 1) ////////////////////////////////////////////// // // @@ -88,6 +90,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) // yes, can happen on fake-extended high_population_requirement = 5 repeatable = TRUE + property_weights = list("chaos" = 1, "extended" = 2) /datum/dynamic_ruleset/event/ventclog/ready() if(mode.threat_level > 30 && mode.threat >= 5 && prob(20)) @@ -125,6 +128,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("story_potential" = 5, "extended" = 1) ////////////////////////////////////////////// // // @@ -143,6 +147,7 @@ repeatable_weight_decrease = 2 requirements = list(60,50,40,30,30,30,30,30,30,30) high_population_requirement = 30 + property_weights = list("extended" = -2) /datum/dynamic_ruleset/event/meteor_wave/ready() if(mode.threat_level > 40 && mode.threat >= 25 && prob(20)) @@ -174,6 +179,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/anomaly_flux name = "Anomaly: Hyper-Energetic Flux" @@ -187,6 +193,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/anomaly_gravitational name = "Anomaly: Gravitational" @@ -198,6 +205,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/anomaly_pyroclastic name = "Anomaly: Pyroclastic" @@ -211,6 +219,7 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/anomaly_vortex name = "Anomaly: Vortex" @@ -224,6 +233,7 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = 1) ////////////////////////////////////////////// // // @@ -243,6 +253,7 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = -1, "chaos" = 1) /datum/dynamic_ruleset/event/carp_migration name = "Carp Migration" @@ -254,6 +265,7 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/communications_blackout name = "Communications Blackout" @@ -267,6 +279,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1, "chaos" = 1) /datum/dynamic_ruleset/event/processor_overload name = "Processor Overload" @@ -280,6 +293,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1, "chaos" = 1) /datum/dynamic_ruleset/event/space_dust name = "Minor Space Dust" @@ -293,6 +307,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/major_dust name = "Major Space Dust" @@ -306,6 +321,7 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/electrical_storm name = "Electrical Storm" @@ -319,6 +335,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/heart_attack name = "Random Heart Attack" @@ -332,6 +349,7 @@ requirements = list(101,101,101,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/radiation_storm name = "Radiation Storm" @@ -343,3 +361,4 @@ required_enemies = list(1,1,1,1,1,1,1,1,1,1) requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 + property_weights = list("extended" = 1,"chaos" = 1) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index 5810fd0ae0..8d9d14b473 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -69,6 +69,8 @@ high_population_requirement = 15 repeatable = TRUE flags = TRAITOR_RULESET + property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1) + ////////////////////////////////////////////// // // @@ -93,6 +95,7 @@ requirements = list(101,101,70,40,40,40,40,40,40,40) high_population_requirement = 40 flags = HIGHLANDER_RULESET + property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2) var/required_heads_of_staff = 3 var/finished = FALSE var/datum/team/revolution/revolution diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 8cda402ebf..1c077aec55 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -189,6 +189,7 @@ repeatable = TRUE high_population_requirement = 15 flags = TRAITOR_RULESET + property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1) /datum/dynamic_ruleset/midround/autotraitor/acceptable(population = 0, threat = 0) var/player_count = mode.current_players[CURRENT_LIVING_PLAYERS].len @@ -245,6 +246,7 @@ requirements = list(101,101,70,50,50,50,40,30,30,30) high_population_requirement = 30 required_type = /mob/living/silicon/ai + property_weights = list("story_potential" = 2, "trust" = 1, "chaos" = 3) var/ion_announce = 33 var/removeDontImproveChance = 10 @@ -297,6 +299,7 @@ requirements = list(90,90,70,50,50,50,50,40,30,30) high_population_requirement = 30 repeatable = TRUE + property_weights = list("story_potential" = 5, "trust" = 1, "chaos" = 3, "extended" = -2) var/datum/mind/wizard /datum/dynamic_ruleset/midround/from_ghosts/wizard/ready(forced = FALSE) @@ -344,6 +347,7 @@ cost = 35 requirements = list(90,90,90,80,70,60,50,40,40,40) high_population_requirement = 40 + property_weights = list("story_potential" = 3, "trust" = 5, "chaos" = 2, "extended" = -5, "valid" = 10) var/operative_cap = list(2,2,3,3,4,5,5,5,5,5) var/datum/team/nuclear/nuke_team flags = HIGHLANDER_RULESET @@ -396,6 +400,7 @@ requirements = list(101,101,101,80,60,50,50,50,50,50) high_population_requirement = 50 repeatable = TRUE + property_weights = list("story_potential" = -1, "trust" = 5, "chaos" = 3, "extended" = -5, "valid" = 4) /datum/dynamic_ruleset/midround/from_ghosts/blob/ready(forced = FALSE) if (required_candidates > (dead_players.len + list_observers.len)) @@ -426,6 +431,7 @@ high_population_requirement = 50 repeatable_weight_decrease = 2 repeatable = TRUE + property_weights = list("story_potential" = -1, "trust" = 5, "chaos" = 2, "extended" = -2, "valid" = 2) var/list/vents = list() /datum/dynamic_ruleset/midround/from_ghosts/xenomorph/ready(forced = FALSE) @@ -480,6 +486,7 @@ high_population_requirement = 50 repeatable_weight_decrease = 2 repeatable = TRUE + property_weights = list("story_potential" = 1, "trust" = 1, "extended" = 1, "valid" = 2, "integrity" = 5) var/list/spawn_locs = list() /datum/dynamic_ruleset/midround/from_ghosts/nightmare/execute() @@ -525,6 +532,7 @@ weight = 4 cost = 5 requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"! + property_weights = list("story_potential" = 3, "extended" = 5, "valid" = -5, "integrity" = 2) high_population_requirement = 5 /datum/dynamic_ruleset/midround/from_ghosts/sentient_disease/ready(forced = FALSE) @@ -558,6 +566,7 @@ cost = 5 requirements = list(30,30,30,30,20,15,15,15,15,15) high_population_requirement = 15 + property_weights = list("story_potential" = -3, "extended" = 5, "integrity" = 5) var/list/spawn_locs = list() /datum/dynamic_ruleset/midround/from_ghosts/revenant/ready(forced = FALSE) @@ -609,6 +618,7 @@ weight = 4 cost = 15 requirements = list(101,101,101,90,80,70,60,50,40,30) + property_weights = list("story_potential" = -3, "extended" = -5, "integrity" = 5, "valid" = 5, "trust" = 3) high_population_requirement = 30 var/list/spawn_locs = list() @@ -660,6 +670,7 @@ blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear) high_population_requirement = 15 var/datum/team/abductor_team/team + property_weights = list("story_potential" = 10, "extended" = 1, "valid" = 1, "trust" = -3) repeatable_weight_decrease = 4 repeatable = TRUE @@ -699,6 +710,7 @@ cost = 15 requirements = list(101,101,101,90,80,70,60,50,40,30) high_population_requirement = 30 + property_weights = list("story_potential" = 1, "extended" = -3, "valid" = 3) var/list/spawn_locs = list() var/spawn_loc diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 56b02a1364..0a5fead01b 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -21,6 +21,7 @@ requirements = list(50,50,50,50,50,50,50,50,50,50) high_population_requirement = 40 antag_cap = list(1,1,1,1,2,2,2,2,3,3) + property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1, "valid" = 1) var/autotraitor_cooldown = 450 // 15 minutes (ticks once per 2 sec) /datum/dynamic_ruleset/roundstart/traitor/pre_execute() @@ -60,6 +61,7 @@ requirements = list(101,101,101,101,101,101,101,101,101,101) high_population_requirement = 101 antag_cap = list(2,2,2,2,2,2,2,2,2,2) // Can pick 3 per team, but rare enough it doesn't matter. + property_weights = list("story_potential" = 1, "trust" = -1, "extended" = 1, "valid" = 1) var/list/datum/team/brother_team/pre_brother_teams = list() var/const/min_team_size = 2 @@ -107,6 +109,7 @@ cost = 15 scaling_cost = 15 requirements = list(101,101,101,101,101,101,101,101,101,101) + property_weights = list("trust" = -2, "valid" = 3) high_population_requirement = 10 antag_cap = list(1,1,1,1,1,2,2,2,2,3) var/team_mode_probability = 30 @@ -159,6 +162,7 @@ cost = 30 requirements = list(101,101,101,60,50,50,50,50,50,50) high_population_requirement = 50 + property_weights = list("story_potential" = 5, "trust" = 1, "chaos" = 3, "extended" = -2, "valid" = 10) var/list/roundstart_wizards = list() /datum/dynamic_ruleset/roundstart/wizard/acceptable(population=0, threat=0) @@ -221,6 +225,7 @@ weight = 3 cost = 30 requirements = list(101,101,101,80,70,60,50,50,50,50) + property_weights = list("story_potential" = -1, "trust" = -1, "chaos" = 1, "conversion" = 1, "extended" = -5, "valid" = 5) high_population_requirement = 50 flags = HIGHLANDER_RULESET antag_cap = list(2,2,2,3,3,4,4,4,4,4) @@ -282,6 +287,7 @@ high_population_requirement = 50 flags = HIGHLANDER_RULESET antag_cap = list(1,1,2,3,4,5,5,5,5,5) + property_weights = list("story_potential" = 3, "trust" = 5, "chaos" = 2, "extended" = -5, "valid" = 10) var/datum/team/nuclear/nuke_team /datum/dynamic_ruleset/roundstart/nuclear/ready(forced = FALSE) @@ -372,6 +378,7 @@ flags = HIGHLANDER_RULESET // I give up, just there should be enough heads with 35 players... minimum_players = 35 + property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2) var/datum/team/revolution/revolution var/finished = FALSE @@ -489,6 +496,7 @@ weight = 3 cost = 0 requirements = list(101,101,101,101,101,101,101,101,101,101) + property_weights = list("extended" = 1000) high_population_requirement = 101 /datum/dynamic_ruleset/roundstart/extended/pre_execute() @@ -516,6 +524,7 @@ high_population_requirement = 50 flags = HIGHLANDER_RULESET antag_cap = list(2,3,3,4,4,4,4,4,4,4) + property_weights = list("trust" = 3, "chaos" = 5, "extended" = -5, "conversion" = 1, "valid" = 10) var/ark_time /datum/dynamic_ruleset/roundstart/clockcult/pre_execute() @@ -615,6 +624,8 @@ antag_leader_datum = /datum/antagonist/nukeop/leader/clownop requirements = list(101,101,101,101,101,101,101,101,101,101) high_population_requirement = 101 + property_weights = list("trust" = 5, "chaos" = 5, "extended" = -5, "story_potential" = 10, "valid" = 10) + /datum/dynamic_ruleset/roundstart/nuclear/clown_ops/pre_execute() . = ..() @@ -646,6 +657,7 @@ requirements = list(101,101,101,101,101,101,101,101,101,101) high_population_requirement = 101 antag_cap = list(1,1,1,2,2,2,3,3,3,4) + property_weights = list("extended" = 1) /datum/dynamic_ruleset/roundstart/devil/pre_execute() var/num_devils = antag_cap[indice_pop] @@ -697,6 +709,7 @@ cost = 0 requirements = list(101,101,101,101,101,101,101,101,101,101) high_population_requirement = 101 + property_weights = list("extended" = -10, "chaos" = 5, "conversion" = 1, "valid" = 10) var/players_per_carrier = 30 var/monkeys_to_win = 1 var/escaped_monkeys = 0 @@ -758,6 +771,7 @@ cost = 0 requirements = list(101,101,101,101,101,101,101,101,101,101) high_population_requirement = 101 + property_weights = list("extended" = -10, "chaos" = 5, "trust" = 5) var/meteordelay = 2000 var/nometeors = 0 var/rampupdelta = 5 diff --git a/code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm new file mode 100644 index 0000000000..c0a943a87e --- /dev/null +++ b/code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm @@ -0,0 +1,93 @@ +/datum/dynamic_storyteller + var/name = "none" + var/desc = "A coder's idiocy." + var/list/property_weights = list() + var/datum/game_mode/dynamic/mode = null + +/** +Property weights are: +"story_potential" -- essentially how many different ways the antag can be played. +"trust" -- How much it makes the crew trust each other. Negative values means they're suspicious. Team antags are like this. +"chaos" -- How chaotic it makes the round. Has some overlap with "valid" and somewhat contradicts "extended". +"valid" -- How likely the non-antag-enemy crew are to get involved, e.g. nukies encouraging the warden to + let everyone into the armory, wizard moving around and being a nuisance, nightmare busting lights. +"extended" -- How much the antag is conducive to a long round. Nukies and cults are bad for this; Wizard is less bad; and so on. +"conversion" -- Basically a bool. Conversion antags, well, convert. It's its own class for a good reason. +*/ + +/datum/dynamic_storyteller/New() + ..() + if (istype(SSticker.mode, /datum/game_mode/dynamic)) + mode = SSticker.mode + else if (GLOB.master_mode != "dynamic") + qdel(src) + +/datum/dynamic_storyteller/proc/do_process() + continue + +/datum/dynamic_storyteller/proc/midround_draft() + var/list/drafted_rules = list() + for (var/datum/dynamic_ruleset/midround/rule in mode.midround_rules) + // if there are antags OR the rule is an antag rule, antag_acceptable will be true. + if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost) + // Classic secret : only autotraitor/minor roles + if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))) + continue + rule.trim_candidates() + if (rule.ready()) + var/property_weight = 0 + for(var/property in property_weights) + if(property in rule.property_weights) // just treat it as 0 if it's not in there + property_weight += rule.property_weight[property] * property_weights[property] + drafted_rules[rule] = rule.get_weight() + property_weight + return drafted_rules + +/datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer) + var/list/drafted_rules = list() + for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules) + if (rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost) + // Classic secret : only autotraitor/minor roles + if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))) + continue + // No stacking : only one round-ender, unless threat level > stacking_limit. + if (mode.threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking) + if(rule.flags & HIGHLANDER_RULESET && highlander_executed) + continue + + rule.candidates = list(newPlayer) + rule.trim_candidates() + if (rule.ready()) + var/property_weight = 0 + for(var/property in property_weights) + if(property in rule.property_weights) // just treat it as 0 if it's not in there + property_weight += rule.property_weight[property] * property_weights[property] + drafted_rules[rule] = rule.get_weight() + property_weight + +/datum/dynamic_storyteller/team + name = "Teamwork" + desc = "Rules that are likely to get the crew to work together against a common enemy." + property_weights = list("valid" = 3, "trust" = 5) + +/datum/dynamic_storyteller/liteextended + name = "Extended-lite" + desc = "Rules that are likely to lead to rounds that reach their finish at the shuttle autocall." + property_weights = list("extended" = 5, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10) + +/datum/dynamic_storyteller/memes + name = "Story" + desc = "Rules that might lead to fun stories to tell." + property_weights = list("story_potential" = 10) + +/datum/dynamic_storyteller/cowabunga + name = "Cowabunga" + desc = "The most chaotic rules only. A validhunter's dream." + property_weights = list("extended" = -1, "chaos" = 10) + +/datum/dynamic_storyteller/suspicion + name = "Intrigue" + desc = "Rules that lead the crew to distrust one another." + property_weights = list("trust" = -5, "valid" = -1) + +/datum/dynamic_storyteller/classic + name = "Classic" + desc = "Uses default dynamic weights and nothing else. The most variety." From 0deaebc4ca9c9ad5d4bee056465983b3de1331a5 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 14:16:02 -0800 Subject: [PATCH 008/148] voting makes everything dumb --- code/game/gamemodes/dynamic/dynamic.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 6566d41e21..72a6457b96 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -52,6 +52,8 @@ GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset) // Forced threat level, setting this to zero or higher forces the roundstart threat to the value. GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) +GLOBAL_VAR_INIT(dynamic_storyteller, /datum/dynamic_storyteller/classic) + /datum/game_mode/dynamic name = "dynamic mode" config_tag = "dynamic" @@ -60,8 +62,6 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) announce_text = "Dynamic mode!" // This needs to be changed maybe reroll_friendly = FALSE; - // Current storyteller - var/datum/dynamic_storyteller/storyteller = null // Threat logging vars /// The "threat cap", threat shouldn't normally go above this and is used in ruleset calculations var/threat_level = 0 From 967bcce38ee534c9ea7f4571d3d20a6e8b3a7f2b Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 14:17:05 -0800 Subject: [PATCH 009/148] actually i still need this --- code/game/gamemodes/dynamic/dynamic.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 72a6457b96..65c8cb347e 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -52,7 +52,7 @@ GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset) // Forced threat level, setting this to zero or higher forces the roundstart threat to the value. GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) -GLOBAL_VAR_INIT(dynamic_storyteller, /datum/dynamic_storyteller/classic) +GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) /datum/game_mode/dynamic name = "dynamic mode" @@ -62,6 +62,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller, /datum/dynamic_storyteller/classic) announce_text = "Dynamic mode!" // This needs to be changed maybe reroll_friendly = FALSE; + // Current storyteller + var/datum/dynamic_storyteller/storyteller = null // Threat logging vars /// The "threat cap", threat shouldn't normally go above this and is used in ruleset calculations var/threat_level = 0 From b96d36e7192001897a51757d7a24a30bf9ffc8ca Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 20:01:30 -0800 Subject: [PATCH 010/148] alright that's that --- .../configuration/configuration.dm | 11 +++ code/controllers/subsystem/ticker.dm | 2 +- code/game/gamemodes/dynamic/dynamic.dm | 54 +++---------- .../dynamic_storytellers.dm | 78 +++++++++++++------ tgstation.dme | 1 + 5 files changed, 78 insertions(+), 68 deletions(-) rename code/game/gamemodes/dynamic/{storytellers => }/dynamic_storytellers.dm (55%) diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index a5d27819b8..14954524fa 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -14,6 +14,7 @@ var/list/modes // allowed modes var/list/gamemode_cache var/list/votable_modes // votable modes + var/list/storyteller_cache var/list/mode_names var/list/mode_reports var/list/mode_false_report_weight @@ -37,6 +38,7 @@ CRASH("/datum/controller/configuration/Load() called more than once!") InitEntries() LoadModes() + storyteller_cache = typecacheof(/datum/dynamic_storyteller, TRUE) if(fexists("[directory]/config.txt") && LoadEntries("config.txt") <= 1) var/list/legacy_configs = list("game_options.txt", "dbconfig.txt", "comms.txt") for(var/I in legacy_configs) @@ -227,6 +229,7 @@ for(var/T in gamemode_cache) // I wish I didn't have to instance the game modes in order to look up // their information, but it is the only way (at least that I know of). + // for future reference: just use initial() lol var/datum/game_mode/M = new T() if(M.config_tag) @@ -317,6 +320,14 @@ return new T return new /datum/game_mode/extended() +/datum/controller/configuration/proc/pick_storyteller(storyteller_name) + for(var/T in storyteller_cache) + var/datum/dynamic_storyteller/S = T + var/name = initial(S.name) + if(name && name == storyteller_name) + return T + return /datum/dynamic_storyteller/classic + /datum/controller/configuration/proc/get_runnable_modes() var/list/datum/game_mode/runnable_modes = new var/list/probabilities = Get(/datum/config_entry/keyed_list/probability) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 6f619fef0b..baaa78e56f 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -480,7 +480,7 @@ SUBSYSTEM_DEF(ticker) SSticker.timeLeft = 900 SSticker.modevoted = TRUE var/dynamic = CONFIG_GET(flag/dynamic_voting) - SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE) + SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE,dynamic) /datum/controller/subsystem/ticker/Recover() current_state = SSticker.current_state diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 65c8cb347e..ea780d47fe 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -52,7 +52,7 @@ GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset) // Forced threat level, setting this to zero or higher forces the roundstart threat to the value. GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) -GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) +GLOBAL_VAR_INIT(dynamic_storyteller_type, null) /datum/game_mode/dynamic name = "dynamic mode" @@ -373,6 +373,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) if("Event") if(ruleset.weight) events += ruleset + storyteller = new GLOB.dynamic_storyteller_type for(var/mob/dead/new_player/player in GLOB.player_list) if(player.ready == PLAYER_READY_TO_PLAY && player.mind) roundstart_pop_ready++ @@ -422,13 +423,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) if (GLOB.dynamic_forced_extended) log_game("DYNAMIC: Starting a round of forced extended.") return TRUE - var/list/drafted_rules = list() - for (var/datum/dynamic_ruleset/roundstart/rule in roundstart_rules) - if (rule.acceptable(roundstart_pop_ready, threat_level) && threat >= rule.cost) // If we got the population and threat required - rule.candidates = candidates.Copy() - rule.trim_candidates() - if (rule.ready() && rule.candidates.len > 0) - drafted_rules[rule] = rule.weight + var/list/drafted_rules = storyteller.roundstart_draft() if(!drafted_rules.len) message_admins("Not enough threat level for roundstart antags!") log_game("DYNAMIC: Not enough threat level for roundstart antags!") @@ -655,7 +650,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) for (var/datum/dynamic_ruleset/rule in current_rules) if(rule.rule_process() == RULESET_STOP_PROCESSING) // If rule_process() returns 1 (RULESET_STOP_PROCESSING), stop processing. current_rules -= rule - + + storyteller.do_process() + if (midround_injection_cooldown < world.time) if (GLOB.dynamic_forced_extended) return @@ -673,21 +670,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) update_playercounts() if (get_injection_chance()) - var/cur_threat_frac = threat/threat_level - var/list/drafted_rules = list() - var/antag_num = current_players[CURRENT_LIVING_ANTAGS].len - for (var/datum/dynamic_ruleset/midround/rule in midround_rules) - // if there are antags OR the rule is an antag rule, antag_acceptable will be true. - if (rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost) - // Classic secret : only autotraitor/minor roles - if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))) - continue - rule.trim_candidates() - if (rule.ready()) - if(!antag_num) - drafted_rules[rule] = round(rule.get_weight() + (rule.cost * cur_threat_frac)) - else - drafted_rules[rule] = rule.get_weight() + var/list/drafted_rules = storyteller.midround_draft() if (drafted_rules.len > 0) picking_midround_latejoin_rule(drafted_rules) else @@ -699,11 +682,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) message_admins("DYNAMIC: Doing event injection.") log_game("DYNAMIC: Doing event injection.") update_playercounts() - var/list/drafted_rules = list() - for(var/datum/dynamic_ruleset/event/rule in events) - if(rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost) - if(rule.ready()) - drafted_rules[rule] = rule.get_weight() + var/list/drafted_rules = storyteller.event_draft() if(drafted_rules.len > 0) picking_midround_latejoin_rule(drafted_rules) @@ -795,22 +774,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) forced_latejoin_rule = null else if (latejoin_injection_cooldown < world.time && prob(get_injection_chance())) - var/list/drafted_rules = list() - for (var/datum/dynamic_ruleset/latejoin/rule in latejoin_rules) - if (rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost) - // Classic secret : only autotraitor/minor roles - if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))) - continue - // No stacking : only one round-ender, unless threat level > stacking_limit. - if (threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking) - if(rule.flags & HIGHLANDER_RULESET && highlander_executed) - continue - - rule.candidates = list(newPlayer) - rule.trim_candidates() - if (rule.ready()) - drafted_rules[rule] = rule.get_weight() - + var/list/drafted_rules = storyteller.latejoin_draft(newPlayer) if (drafted_rules.len > 0 && picking_midround_latejoin_rule(drafted_rules)) var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_latejoin_delay_max + GLOB.dynamic_latejoin_delay_min) latejoin_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_latejoin_delay_min, GLOB.dynamic_latejoin_delay_max)) + world.time diff --git a/code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm similarity index 55% rename from code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm rename to code/game/gamemodes/dynamic/dynamic_storytellers.dm index c0a943a87e..de15c03080 100644 --- a/code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -2,6 +2,8 @@ var/name = "none" var/desc = "A coder's idiocy." var/list/property_weights = list() + var/curve_centre = 0 + var/curve_width = 1.8 var/datum/game_mode/dynamic/mode = null /** @@ -19,11 +21,23 @@ Property weights are: ..() if (istype(SSticker.mode, /datum/game_mode/dynamic)) mode = SSticker.mode - else if (GLOB.master_mode != "dynamic") - qdel(src) /datum/dynamic_storyteller/proc/do_process() - continue + return + +/datum/dynamic_storyteller/proc/roundstart_draft() + var/list/drafted_rules = list() + for (var/datum/dynamic_ruleset/roundstart/rule in mode.roundstart_rules) + if (rule.acceptable(mode.roundstart_pop_ready, mode.threat_level) && mode.threat >= rule.cost) // If we got the population and threat required + rule.candidates = mode.candidates.Copy() + rule.trim_candidates() + if (rule.ready() && rule.candidates.len > 0) + var/property_weight = 0 + for(var/property in property_weights) + if(property in rule.property_weights) // just treat it as 0 if it's not in there + property_weight += rule.property_weights[property] * property_weights[property] + drafted_rules[rule] = rule.get_weight() + property_weight + return drafted_rules /datum/dynamic_storyteller/proc/midround_draft() var/list/drafted_rules = list() @@ -37,55 +51,75 @@ Property weights are: if (rule.ready()) var/property_weight = 0 for(var/property in property_weights) - if(property in rule.property_weights) // just treat it as 0 if it's not in there - property_weight += rule.property_weight[property] * property_weights[property] + if(property in rule.property_weights) + property_weight += rule.property_weights[property] * property_weights[property] drafted_rules[rule] = rule.get_weight() + property_weight return drafted_rules /datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer) - var/list/drafted_rules = list() - for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules) - if (rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost) - // Classic secret : only autotraitor/minor roles - if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))) + var/list/drafted_rules = list() + for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules) + if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost) + // Classic secret : only autotraitor/minor roles + if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))) + continue + // No stacking : only one round-ender, unless threat level > stacking_limit. + if (mode.threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking) + if(rule.flags & HIGHLANDER_RULESET && mode.highlander_executed) continue - // No stacking : only one round-ender, unless threat level > stacking_limit. - if (mode.threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking) - if(rule.flags & HIGHLANDER_RULESET && highlander_executed) - continue - rule.candidates = list(newPlayer) - rule.trim_candidates() - if (rule.ready()) - var/property_weight = 0 - for(var/property in property_weights) - if(property in rule.property_weights) // just treat it as 0 if it's not in there - property_weight += rule.property_weight[property] * property_weights[property] - drafted_rules[rule] = rule.get_weight() + property_weight + rule.candidates = list(newPlayer) + rule.trim_candidates() + if (rule.ready()) + var/property_weight = 0 + for(var/property in property_weights) + if(property in rule.property_weights) + property_weight += rule.property_weights[property] * property_weights[property] + drafted_rules[rule] = rule.get_weight() + property_weight + return drafted_rules + +/datum/dynamic_storyteller/proc/event_draft() + var/list/drafted_rules = list() + for(var/datum/dynamic_ruleset/event/rule in mode.events) + if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost) + if(rule.ready()) + var/property_weight = 0 + for(var/property in property_weights) + if(property in rule.property_weights) + property_weight += rule.property_weights[property] * property_weights[property] + drafted_rules[rule] = rule.get_weight() + property_weight + return drafted_rules /datum/dynamic_storyteller/team name = "Teamwork" desc = "Rules that are likely to get the crew to work together against a common enemy." + curve_centre = 2 + curve_width = 1.5 property_weights = list("valid" = 3, "trust" = 5) /datum/dynamic_storyteller/liteextended name = "Extended-lite" desc = "Rules that are likely to lead to rounds that reach their finish at the shuttle autocall." + curve_centre = -5 + curve_width = 0.5 property_weights = list("extended" = 5, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10) /datum/dynamic_storyteller/memes name = "Story" desc = "Rules that might lead to fun stories to tell." + curve_width = 4 property_weights = list("story_potential" = 10) /datum/dynamic_storyteller/cowabunga name = "Cowabunga" + curve_centre = 10 desc = "The most chaotic rules only. A validhunter's dream." property_weights = list("extended" = -1, "chaos" = 10) /datum/dynamic_storyteller/suspicion name = "Intrigue" desc = "Rules that lead the crew to distrust one another." + curve_width = 4 property_weights = list("trust" = -5, "valid" = -1) /datum/dynamic_storyteller/classic diff --git a/tgstation.dme b/tgstation.dme index 4c7e29739f..98a998b2e2 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -573,6 +573,7 @@ #include "code\game\gamemodes\dynamic\dynamic_rulesets_latejoin.dm" #include "code\game\gamemodes\dynamic\dynamic_rulesets_midround.dm" #include "code\game\gamemodes\dynamic\dynamic_rulesets_roundstart.dm" +#include "code\game\gamemodes\dynamic\dynamic_storytellers.dm" #include "code\game\gamemodes\extended\extended.dm" #include "code\game\gamemodes\meteor\meteor.dm" #include "code\game\gamemodes\meteor\meteors.dm" From 74e4391cee917bfc672fc3e40361b74576deb01a Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 20:01:38 -0800 Subject: [PATCH 011/148] uh, vote changes necessary too --- code/controllers/subsystem/vote.dm | 106 ++++++++++++++++------------- 1 file changed, 57 insertions(+), 49 deletions(-) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index dee10e4998..9c2f4814ac 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -1,3 +1,6 @@ +#define PLURALITY 0 +#define APPROVAL 1 + SUBSYSTEM_DEF(vote) name = "Vote" wait = 10 @@ -10,8 +13,10 @@ SUBSYSTEM_DEF(vote) var/started_time = null var/time_remaining = 0 var/mode = null + var/vote_system = PLURALITY var/question = null var/list/choices = list() + var/list/choice_descs = list() // optional descriptions var/list/voted = list() var/list/voting = list() var/list/generated_actions = list() @@ -124,9 +129,6 @@ SUBSYSTEM_DEF(vote) message_admins(admintext) return . -#define PEACE "calm" -#define CHAOS "chaotic" - /datum/controller/subsystem/vote/proc/result() . = announce_result() var/restart = 0 @@ -153,32 +155,15 @@ SUBSYSTEM_DEF(vote) if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started. return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.") GLOB.master_mode = "dynamic" - if("extended" in choices) - if(. == "extended") - GLOB.dynamic_forced_extended = TRUE // we still do the rest of the stuff - choices[PEACE] += choices["extended"] - var/mean = 0 - var/voters = 0 - for(var/client/c in GLOB.clients) - var/vote = c.prefs.preferred_chaos - if(vote) - voters += 1 - switch(vote) - if(CHAOS_NONE) - mean -= 0.1 - if(CHAOS_LOW) - mean -= 0.05 - if(CHAOS_HIGH) - mean += 0.05 - if(CHAOS_MAX) - mean += 0.1 - mean/=voters - if(voted.len != 0) - mean += (choices[PEACE]*-1+choices[CHAOS])/voted.len - GLOB.dynamic_curve_centre = mean*20 - GLOB.dynamic_curve_width = CLAMP(2-abs(mean*5),0.5,4) - to_chat(world,"Dynamic curve centre set to [GLOB.dynamic_curve_centre] and width set to [GLOB.dynamic_curve_width].") - log_admin("Dynamic curve centre set to [GLOB.dynamic_curve_centre] and width set to [GLOB.dynamic_curve_width]") + if(. == "extended") + GLOB.dynamic_forced_extended = TRUE // we still do the rest of the stuff + GLOB.dynamic_storyteller_type = /datum/dynamic_storyteller/liteextended + GLOB.dynamic_forced_threat_level = 15 + else + var/datum/dynamic_storyteller/S = config.pick_storyteller(.) + GLOB.dynamic_storyteller_type = S + GLOB.dynamic_curve_centre = initial(S.curve_centre) + GLOB.dynamic_curve_width = initial(S.curve_width) if("map") var/datum/map_config/VM = config.maplist[.] message_admins("The map has been voted for and will change to: [VM.map_name]") @@ -203,20 +188,36 @@ SUBSYSTEM_DEF(vote) if(mode) if(CONFIG_GET(flag/no_dead_vote) && usr.stat == DEAD && !usr.client.holder) return 0 - if(!(usr.ckey in voted)) - if(vote && 1<=vote && vote<=choices.len) - voted += usr.ckey - voted[usr.ckey] = vote - choices[choices[vote]]++ //check this - return vote - else if(vote && 1<=vote && vote<=choices.len) - choices[choices[voted[usr.ckey]]]-- - voted[usr.ckey] = vote - choices[choices[vote]]++ - return vote + if(vote && vote >= 1 && vote <= choices.len) + switch(vote_system) + if(PLURALITY) + if(usr.ckey in voted) + choices[choices[voted[usr.ckey]]]-- + voted[usr.ckey] = vote + choices[choices[vote]]++ + return vote + else + voted += usr.ckey + voted[usr.ckey] = vote + choices[choices[vote]]++ //check this + return vote + if(APPROVAL) + if(usr.ckey in voted) + if(vote in voted[usr.ckey]) + voted[usr.ckey] -= vote + choices[choices[vote]]-- + else + voted[usr.ckey].Add(vote) + choices[choices[vote]]++ + else + voted += usr.ckey + voted[usr.ckey] = list(vote) + choices[choices[vote]]++ + return vote return 0 -/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes +/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults, votesystem = PLURALITY)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes + vote_system = votesystem if(!mode) if(started_time) var/next_allowed_time = (started_time + CONFIG_GET(number/vote_delay)) @@ -259,9 +260,11 @@ SUBSYSTEM_DEF(vote) if("dynamic") var/saved_threats = SSpersistence.saved_threat_levels if((saved_threats[1]+saved_threats[2]+saved_threats[3])>150) - choices.Add("extended",PEACE,CHAOS) - else - choices.Add(PEACE,CHAOS) + choices.Add("extended") + for(var/T in config.storyteller_cache) + var/datum/dynamic_storyteller/S = T + choices.Add(initial(S.name)) + choice_descs.Add(initial(S.desc)) if("custom") question = stripped_input(usr,"What is the vote for?") if(!question) @@ -311,13 +314,21 @@ SUBSYSTEM_DEF(vote) . += "

Vote: '[question]'

" else . += "

Vote: [capitalize(mode)]

" + . += "

Vote [vote_system == PLURALITY ? "your top choice" : "all that apply"].

" . += "Time Left: [time_remaining] s
    " for(var/i=1,i<=choices.len,i++) var/votes = choices[choices[i]] - var/ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i) ? TRUE : FALSE) + var/ivotedforthis = FALSE + switch(vote_system) + if(PLURALITY) + ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i)) + if(APPROVAL) + ivotedforthis = ((C.ckey in voted) && (i in voted[C.ckey])) if(!votes) votes = 0 . += "
  • [ivotedforthis ? "" : ""][choices[i]] ([obfuscated ? (admin ? "??? ([votes])" : "???") : votes] votes)[ivotedforthis ? "" : ""]
  • " // CIT CHANGE - adds obfuscated votes + if(choice_descs.len >= i) + . += "
  • [choice_descs[i]]
  • " . += "

" if(admin) . += "(Cancel Vote) " @@ -392,7 +403,7 @@ SUBSYSTEM_DEF(vote) set category = "OOC" set name = "Vote" - var/datum/browser/popup = new(src, "vote", "Voting Panel") + var/datum/browser/popup = new(src, "vote", "Voting Panel",nwidth=600,nheight=600) popup.set_window_options("can_close=0") popup.set_content(SSvote.interface(client)) popup.open(0) @@ -419,6 +430,3 @@ SUBSYSTEM_DEF(vote) var/datum/player_details/P = GLOB.player_details[owner.ckey] if(P) P.player_actions -= src - -#undef PEACE -#undef CHAOS From e44566038b9e949a92a40f208cb8a15dc89c7c04 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 20:32:34 -0800 Subject: [PATCH 012/148] linter is correct --- code/controllers/subsystem/vote.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 9c2f4814ac..b34713254d 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -207,7 +207,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] -= vote choices[choices[vote]]-- else - voted[usr.ckey].Add(vote) + voted[usr.ckey] += vote choices[choices[vote]]++ else voted += usr.ckey From f943bcb3b573bce3aa1f7090cd4ce48d1968cef7 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 15 Dec 2019 12:17:07 -0800 Subject: [PATCH 013/148] make cowabunga description less, uh, bad --- code/game/gamemodes/dynamic/dynamic_storytellers.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm index de15c03080..8e33c94a24 100644 --- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -113,7 +113,7 @@ Property weights are: /datum/dynamic_storyteller/cowabunga name = "Cowabunga" curve_centre = 10 - desc = "The most chaotic rules only. A validhunter's dream." + desc = "The most chaotic rules are weighted heavily here. Rounds are nasty, brutish and short." property_weights = list("extended" = -1, "chaos" = 10) /datum/dynamic_storyteller/suspicion From 3d0d1de94c912eaaa01ea47faf4aaa1d62942a72 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 15 Dec 2019 14:49:32 -0800 Subject: [PATCH 014/148] Added bloodsucker weights. --- .../dynamic/dynamic_rulesets_midround.dm | 37 ++++++++++--------- .../dynamic/dynamic_rulesets_roundstart.dm | 1 + 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index be497b3cce..84d33ce669 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -754,23 +754,24 @@ ////////////////////////////////////////////// /datum/dynamic_ruleset/latejoin/bloodsucker - name = "Bloodsucker Infiltrator" - config_tag = "latejoin_bloodsucker" - antag_datum = ANTAG_DATUM_BLOODSUCKER - antag_flag = ROLE_TRAITOR - restricted_roles = list("AI", "Cyborg") - protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") - required_candidates = 1 - weight = 3 - cost = 10 - requirements = list(90,80,70,60,55,50,45,40,35,30) - high_population_requirement = 30 - repeatable = TRUE + name = "Bloodsucker Infiltrator" + config_tag = "latejoin_bloodsucker" + antag_datum = ANTAG_DATUM_BLOODSUCKER + antag_flag = ROLE_TRAITOR + restricted_roles = list("AI", "Cyborg") + protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") + required_candidates = 1 + weight = 3 + cost = 10 + property_weights = list("extended" = 2, "chaos" = -1, "trust" = -3, "story_potential" = -2, "conversion" = 1, "valid" = 1) + requirements = list(90,80,70,60,55,50,45,40,35,30) + high_population_requirement = 30 + repeatable = TRUE /datum/dynamic_ruleset/latejoin/bloodsucker/execute() - var/mob/M = pick(candidates) - assigned += M.mind - M.mind.special_role = antag_flag - if(mode.make_bloodsucker(M.mind)) - mode.bloodsuckers += M - return TRUE + var/mob/M = pick(candidates) + assigned += M.mind + M.mind.special_role = antag_flag + if(mode.make_bloodsucker(M.mind)) + mode.bloodsuckers += M + return TRUE diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 80146b8657..1abdcef3f1 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -812,6 +812,7 @@ weight = 2 cost = 15 scaling_cost = 10 + property_weights = list("extended" = 2, "chaos" = -1, "trust" = -3, "story_potential" = -2, "conversion" = 1) requirements = list(90,80,70,60,50,50,50,50,50,50) high_population_requirement = 50 antag_cap = list(1,1,1,1,1,2,2,2,2,2) From 138f2d05f06410c5f2f534d2c9140f720dcde01c Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 15 Dec 2019 14:49:43 -0800 Subject: [PATCH 015/148] Made intrigue not care about valid. --- code/game/gamemodes/dynamic/dynamic_storytellers.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm index 8e33c94a24..1f0abc7312 100644 --- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -120,7 +120,7 @@ Property weights are: name = "Intrigue" desc = "Rules that lead the crew to distrust one another." curve_width = 4 - property_weights = list("trust" = -5, "valid" = -1) + property_weights = list("trust" = -5) /datum/dynamic_storyteller/classic name = "Classic" From f244ac84b21a6bbf9a2cf53b4b265d2fa0aa1b27 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 15 Dec 2019 15:25:47 -0800 Subject: [PATCH 016/148] whoops --- code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 84d33ce669..6b03bb3fb3 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -773,5 +773,5 @@ assigned += M.mind M.mind.special_role = antag_flag if(mode.make_bloodsucker(M.mind)) - mode.bloodsuckers += M + mode.bloodsuckers += M return TRUE From 5bf252a58c408b8b5f9a70acd6b70bdcc1e81766 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Tue, 17 Dec 2019 01:57:56 +0100 Subject: [PATCH 017/148] Ports "Fixes ChangeTurf CHANGETURF_INHERIT_AIR flag and add it to all calls." --- code/game/mecha/equipment/tools/work_tools.dm | 6 +- .../effects/effect_system/effects_foam.dm | 2 +- code/game/objects/items/stacks/stack.dm | 9 ++- code/game/objects/items/twohanded.dm | 2 +- code/game/objects/structures/lattice.dm | 2 +- code/game/objects/structures/stairs.dm | 4 +- code/game/turfs/change_turf.dm | 15 ++-- code/game/turfs/closed.dm | 2 +- code/game/turfs/open.dm | 2 +- code/game/turfs/openspace/openspace.dm | 2 +- code/game/turfs/simulated/chasm.dm | 4 +- code/game/turfs/simulated/floor.dm | 22 +++--- code/game/turfs/simulated/floor/plating.dm | 12 +-- .../game/turfs/simulated/floor/reinf_floor.dm | 14 ++-- code/game/turfs/simulated/lava.dm | 2 +- code/game/turfs/space/space.dm | 4 +- code/game/turfs/turf.dm | 4 +- .../clock_items/replica_fabricator.dm | 2 +- .../clockcult/clock_structures/wall_gear.dm | 2 +- .../antagonists/cult/cult_structures.dm | 4 +- code/modules/buildmode/submodes/basic.dm | 6 +- .../mining/lavaland/necropolis_chests.dm | 4 +- .../mob/living/simple_animal/bot/floorbot.dm | 8 +- .../hostile/megafauna/colossus.dm | 5 +- .../hostile/mining_mobs/necropolis_tendril.dm | 2 +- code/modules/projectiles/projectile/magic.dm | 2 +- .../chemistry/reagents/other_reagents.dm | 77 ++++--------------- .../reagents/pyrotechnic_reagents.dm | 2 +- .../ruins/objects_and_mobs/sin_ruins.dm | 2 +- code/modules/spells/spell_types/conjure.dm | 2 +- code/modules/spells/spell_types/devil.dm | 4 +- .../reagents/chemistry/reagents/astrogen.dm | 2 +- 32 files changed, 91 insertions(+), 141 deletions(-) diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index 36708fcf90..ca8e8cecd9 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -262,14 +262,14 @@ occupant_message("Deconstructing [W]...") if(do_after_cooldown(W)) chassis.spark_system.start() - W.ScrapeAway() + W.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) playsound(W, 'sound/items/deconstruct.ogg', 50, 1) else if(isfloorturf(target)) var/turf/open/floor/F = target occupant_message("Deconstructing [F]...") if(do_after_cooldown(target)) chassis.spark_system.start() - F.ScrapeAway() + F.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) playsound(F, 'sound/items/deconstruct.ogg', 50, 1) else if (istype(target, /obj/machinery/door/airlock)) occupant_message("Deconstructing [target]...") @@ -282,7 +282,7 @@ var/turf/open/space/S = target occupant_message("Building Floor...") if(do_after_cooldown(S)) - S.PlaceOnTop(/turf/open/floor/plating) + S.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) playsound(S, 'sound/items/deconstruct.ogg', 50, 1) chassis.spark_system.start() else if(isfloorturf(target)) diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index 10ee73915c..b6deaa1d06 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -123,7 +123,7 @@ if(metal) var/turf/T = get_turf(src) if(isspaceturf(T)) //Block up any exposed space - T.PlaceOnTop(/turf/open/floor/plating/foam) + T.PlaceOnTop(/turf/open/floor/plating/foam, flags = CHANGETURF_INHERIT_AIR) for(var/direction in GLOB.cardinals) var/turf/cardinal_turf = get_step(T, direction) if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf! diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index e8bd50f19b..d2ddd493b2 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -192,9 +192,14 @@ var/obj/O if(R.max_res_amount > 1) //Is it a stack? O = new R.result_type(usr.drop_location(), R.res_amount * multiplier) - else + else if(ispath(R.result_type, /turf)) + var/turf/T = usr.drop_location() + if(!isturf(T)) + return + T.PlaceOnTop(R.result_type, flags = CHANGETURF_INHERIT_AIR) O = new R.result_type(usr.drop_location()) - O.setDir(usr.dir) + if(O) + O.setDir(usr.dir) use(R.req_amount * multiplier) //START: oh fuck i'm so sorry diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index dd7d46d0d7..d7891feaa0 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -872,7 +872,7 @@ user.visible_message("[user] blasts \the [target] with \the [src]!") playsound(target, 'sound/magic/disintegrate.ogg', 100, 1) W.break_wall() - W.ScrapeAway() + W.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return //HF blade diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index b946a06432..a7eaea0d16 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -60,7 +60,7 @@ to_chat(user, "You build a floor.") var/turf/T = src.loc if(isspaceturf(T)) - T.PlaceOnTop(/turf/open/floor/plating) + T.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) qdel(src) return TRUE return FALSE diff --git a/code/game/objects/structures/stairs.dm b/code/game/objects/structures/stairs.dm index bd657fe1e8..f2c4e628e0 100644 --- a/code/game/objects/structures/stairs.dm +++ b/code/game/objects/structures/stairs.dm @@ -102,13 +102,13 @@ /obj/structure/stairs/proc/force_open_above() var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP) if(T && !istype(T)) - T.ChangeTurf(/turf/open/openspace) + T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR) /obj/structure/stairs/proc/on_multiz_new(turf/source, dir) if(dir == UP) var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP) if(T && !istype(T)) - T.ChangeTurf(/turf/open/openspace) + T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR) /obj/structure/stairs/intercept_zImpact(atom/movable/AM, levels = 1) . = ..() diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 6a055bbd35..990ec91eeb 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -128,16 +128,15 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( /turf/open/ChangeTurf(path, list/new_baseturfs, flags) if ((flags & CHANGETURF_INHERIT_AIR) && ispath(path, /turf/open)) SSair.remove_from_active(src) - var/stashed_air = air - air = null // so that it doesn't get deleted + var/datum/gas_mixture/stashed_air = new() + stashed_air.copy_from(air) . = ..() - if (!. || . == src) // changeturf failed or didn't do anything - air = stashed_air + if (!.) // changeturf failed or didn't do anything + QDEL_NULL(stashed_air) return var/turf/open/newTurf = . - if (!istype(newTurf.air, /datum/gas_mixture/immutable/space)) - QDEL_NULL(newTurf.air) - newTurf.air = stashed_air + newTurf.air.copy_from(stashed_air) + QDEL_NULL(stashed_air) SSair.add_to_active(newTurf) else if(ispath(path,/turf/closed)) @@ -315,5 +314,5 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( SSair.add_to_active(src) /turf/proc/ReplaceWithLattice() - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) new /obj/structure/lattice(locate(x, y, z)) diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index 6297cadc63..9e593cafce 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -23,7 +23,7 @@ icon = 'icons/turf/walls.dmi' explosion_block = 50 -/turf/closed/indestructible/TerraformTurf(path, defer_change = FALSE, ignore_air = FALSE) +/turf/closed/indestructible/TerraformTurf(path, new_baseturf, flags, defer_change = FALSE, ignore_air = FALSE) return /turf/closed/indestructible/acid_act(acidpwr, acid_volume, acid_id) diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 4bdb13effc..577c45a7f0 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -58,7 +58,7 @@ /turf/open/indestructible/singularity_act() return -/turf/open/indestructible/TerraformTurf(path, defer_change = FALSE, ignore_air = FALSE) +/turf/open/indestructible/TerraformTurf(path, new_baseturf, flags, defer_change = FALSE, ignore_air = FALSE) return /turf/open/indestructible/sound diff --git a/code/game/turfs/openspace/openspace.dm b/code/game/turfs/openspace/openspace.dm index e68aabcd08..66507e7053 100644 --- a/code/game/turfs/openspace/openspace.dm +++ b/code/game/turfs/openspace/openspace.dm @@ -106,7 +106,7 @@ qdel(L) playsound(src, 'sound/weapons/genhit.ogg', 50, 1) to_chat(user, "You build a floor.") - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else to_chat(user, "You need one floor tile to build a floor!") else diff --git a/code/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm index 0a7b507488..dab0c1c376 100644 --- a/code/game/turfs/simulated/chasm.dm +++ b/code/game/turfs/simulated/chasm.dm @@ -38,7 +38,7 @@ switch(passed_mode) if(RCD_FLOORWALL) to_chat(user, "You build a floor.") - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) return TRUE return FALSE @@ -70,7 +70,7 @@ playsound(src, 'sound/weapons/genhit.ogg', 50, 1) to_chat(user, "You build a floor.") // Create a floor, which has this chasm underneath it - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else to_chat(user, "You need one floor tile to build a floor!") else diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 194014b61a..4973e68a68 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -62,29 +62,29 @@ if(severity != 1 && shielded && target != src) return if(target == src) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return if(target != null) severity = 3 switch(severity) if(1) - ScrapeAway(2) + ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR) if(2) switch(pick(1,2;75,3)) if(1) if(!length(baseturfs) || !ispath(baseturfs[baseturfs.len-1], /turf/open/floor)) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) ReplaceWithLattice() else - ScrapeAway(2) + ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR) if(prob(33)) new /obj/item/stack/sheet/metal(src) if(2) - ScrapeAway(2) + ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR) if(3) if(prob(80)) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) else break_tile() hotspot_expose(1000,CELL_VOLUME) @@ -135,7 +135,7 @@ burnt = 1 /turf/open/floor/proc/make_plating() - return ScrapeAway() + return ScrapeAway(flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/ChangeTurf(path, new_baseturf, flags) if(!isfloorturf(src)) @@ -213,15 +213,15 @@ /turf/open/floor/narsie_act(force, ignore_mobs, probability = 20) . = ..() if(.) - ChangeTurf(/turf/open/floor/engine/cult) + ChangeTurf(/turf/open/floor/engine/cult, flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/ratvar_act(force, ignore_mobs) . = ..() if(.) - ChangeTurf(/turf/open/floor/clockwork) + ChangeTurf(/turf/open/floor/clockwork, flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/acid_melt() - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) switch(the_rcd.mode) @@ -267,7 +267,7 @@ A.autoclose = TRUE return TRUE if(RCD_DECONSTRUCT) - if(ScrapeAway() == src) + if(ScrapeAway(flags = CHANGETURF_INHERIT_AIR) == src) return FALSE to_chat(user, "You deconstruct [src].") return TRUE diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index ae67edf073..a6d8ec5db2 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -61,7 +61,7 @@ to_chat(user, "You begin reinforcing the floor...") if(do_after(user, 30, target = src)) if (R.get_amount() >= 2 && !istype(src, /turf/open/floor/engine)) - PlaceOnTop(/turf/open/floor/engine) + PlaceOnTop(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR) playsound(src, 'sound/items/deconstruct.ogg', 80, 1) R.use(2) to_chat(user, "You reinforce the floor.") @@ -76,7 +76,7 @@ var/obj/item/stack/tile/W = C if(!W.use(1)) return - var/turf/open/floor/T = PlaceOnTop(W.turf_type) + var/turf/open/floor/T = PlaceOnTop(W.turf_type, flags = CHANGETURF_INHERIT_AIR) if(istype(W, /obj/item/stack/tile/light)) //TODO: get rid of this ugly check somehow var/obj/item/stack/tile/light/L = W var/turf/open/floor/light/F = T @@ -117,7 +117,7 @@ qdel(L) to_chat(user, "You reinforce the foamed plating with tiling.") playsound(src, 'sound/weapons/Genhit.ogg', 50, TRUE) - ChangeTurf(/turf/open/floor/plating) + ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else playsound(src, 'sound/weapons/tap.ogg', 100, TRUE) //The attack sound is muffled by the foam itself user.changeNext_move(CLICK_CD_MELEE) @@ -125,7 +125,7 @@ if(prob(I.force * 20 - 25)) user.visible_message("[user] smashes through [src]!", \ "You smash through [src] with [I]!") - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) else to_chat(user, "You hit [src], to no effect!") @@ -136,13 +136,13 @@ /turf/open/floor/plating/foam/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) if(passed_mode == RCD_FLOORWALL) to_chat(user, "You build a floor.") - ChangeTurf(/turf/open/floor/plating) + ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) return TRUE return FALSE /turf/open/floor/plating/foam/ex_act() ..() - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/plating/foam/tool_act(mob/living/user, obj/item/I, tool_type) return diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm index b04f89f8be..28ffbbd1ff 100644 --- a/code/game/turfs/simulated/floor/reinf_floor.dm +++ b/code/game/turfs/simulated/floor/reinf_floor.dm @@ -43,7 +43,7 @@ return TRUE if(floor_tile) new floor_tile(src, 2) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return TRUE /turf/open/floor/engine/acid_act(acidpwr, acid_volume) @@ -56,23 +56,23 @@ if(severity != 1 && shielded && target != src) return if(target == src) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return switch(severity) if(1) if(prob(80)) if(!length(baseturfs) || !ispath(baseturfs[baseturfs.len-1], /turf/open/floor)) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) ReplaceWithLattice() else - ScrapeAway(2) + ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR) else if(prob(50)) - ScrapeAway(2) + ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR) else - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) if(2) if(prob(50)) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/engine/singularity_pull(S, current_size) ..() diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index 362b410cbb..2f8ae0cb93 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -54,7 +54,7 @@ switch(passed_mode) if(RCD_FLOORWALL) to_chat(user, "You build a floor.") - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) return TRUE return FALSE diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index f38f13e657..5278374abd 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -125,7 +125,7 @@ qdel(L) playsound(src, 'sound/weapons/genhit.ogg', 50, 1) to_chat(user, "You build a floor.") - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else to_chat(user, "You need one floor tile to build a floor!") else @@ -212,7 +212,7 @@ switch(passed_mode) if(RCD_FLOORWALL) to_chat(user, "You build a floor.") - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) return TRUE return FALSE diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index d618e457b0..81757ab7f5 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -391,7 +391,7 @@ continue if(O.invisibility == INVISIBILITY_MAXIMUM) O.singularity_act() - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return(2) /turf/proc/can_have_cabling() @@ -564,4 +564,4 @@ //Whatever happens after high temperature fire dies out or thermite reaction works. //Should return new turf /turf/proc/Melt() - return ScrapeAway() + return ScrapeAway(flags = CHANGETURF_INHERIT_AIR) diff --git a/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm b/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm index 0365ae63af..501bcdc1c4 100644 --- a/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm +++ b/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm @@ -139,7 +139,7 @@ var/new_thing_type = fabrication_values["new_obj_type"] if(isturf(target)) //if our target is a turf, we're just going to ChangeTurf it and assume it'll work out. var/turf/T = target - T.ChangeTurf(new_thing_type) + T.ChangeTurf(new_thing_type, flags = CHANGETURF_INHERIT_AIR) else if(new_thing_type) if(fabrication_values["dir_in_new"]) diff --git a/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm b/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm index 32b1b61dd1..d823f19d4a 100644 --- a/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm +++ b/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm @@ -59,7 +59,7 @@ if(anchored) T.PlaceOnTop(/turf/closed/wall/clockwork) else - T.PlaceOnTop(/turf/open/floor/clockwork) + T.PlaceOnTop(/turf/open/floor/clockwork, flags = CHANGETURF_INHERIT_AIR) new /obj/structure/falsewall/brass(T) qdel(src) else diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm index f38f379abe..6f340b9271 100644 --- a/code/modules/antagonists/cult/cult_structures.dm +++ b/code/modules/antagonists/cult/cult_structures.dm @@ -239,9 +239,9 @@ var/turf/T = safepick(validturfs) if(T) if(istype(T, /turf/open/floor/plating)) - T.PlaceOnTop(/turf/open/floor/engine/cult) + T.PlaceOnTop(/turf/open/floor/engine/cult, flags = CHANGETURF_INHERIT_AIR) else - T.ChangeTurf(/turf/open/floor/engine/cult) + T.ChangeTurf(/turf/open/floor/engine/cult, flags = CHANGETURF_INHERIT_AIR) else var/turf/open/floor/engine/cult/F = safepick(cultturfs) if(F) diff --git a/code/modules/buildmode/submodes/basic.dm b/code/modules/buildmode/submodes/basic.dm index 4f7b176691..fe3d831d81 100644 --- a/code/modules/buildmode/submodes/basic.dm +++ b/code/modules/buildmode/submodes/basic.dm @@ -22,9 +22,9 @@ if(istype(object,/turf) && left_click && !alt_click && !ctrl_click) var/turf/T = object if(isspaceturf(object)) - T.PlaceOnTop(/turf/open/floor/plating) + T.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else if(isplatingturf(object)) - T.PlaceOnTop(/turf/open/floor/plasteel) + T.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR) else if(isfloorturf(object)) T.PlaceOnTop(/turf/closed/wall) else if(iswallturf(object)) @@ -35,7 +35,7 @@ log_admin("Build Mode: [key_name(c)] deleted [object] at [AREACOORD(object)]") if(isturf(object)) var/turf/T = object - T.ScrapeAway() + T.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) else if(isobj(object)) qdel(object) return diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index ab3b20ac9f..7bef9b652a 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -926,7 +926,7 @@ timer = world.time + create_delay + 1 if(do_after(user, create_delay, target = T)) var/old_name = T.name - if(T.TerraformTurf(turf_type)) + if(T.TerraformTurf(turf_type, flags = CHANGETURF_INHERIT_AIR)) user.visible_message("[user] turns \the [old_name] into [transform_string]!") message_admins("[ADMIN_LOOKUPFLW(user)] fired the lava staff at [ADMIN_VERBOSEJMP(T)]") log_game("[key_name(user)] fired the lava staff at [AREACOORD(T)].") @@ -937,7 +937,7 @@ qdel(L) else var/old_name = T.name - if(T.TerraformTurf(reset_turf_type)) + if(T.TerraformTurf(reset_turf_type, flags = CHANGETURF_INHERIT_AIR)) user.visible_message("[user] turns \the [old_name] into [reset_string]!") timer = world.time + reset_cooldown playsound(T,'sound/magic/fireball.ogg', 200, 1) diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index 396c6de166..cae707ce46 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -318,9 +318,9 @@ sleep(50) if(mode == BOT_REPAIRING && src.loc == target_turf) if(autotile) //Build the floor and include a tile. - target_turf.PlaceOnTop(/turf/open/floor/plasteel) + target_turf.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR) else //Build a hull plating without a floor tile. - target_turf.PlaceOnTop(/turf/open/floor/plating) + target_turf.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else var/turf/open/floor/F = target_turf @@ -334,7 +334,7 @@ if(mode == BOT_REPAIRING && F && src.loc == F) F.broken = 0 F.burnt = 0 - F.PlaceOnTop(/turf/open/floor/plasteel) + F.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR) if(replacetiles && F.type != initial(tiletype.turf_type) && specialtiles && !isplatingturf(F)) anchored = TRUE @@ -345,7 +345,7 @@ if(mode == BOT_REPAIRING && F && src.loc == F) F.broken = 0 F.burnt = 0 - F.PlaceOnTop(initial(tiletype.turf_type)) + F.PlaceOnTop(initial(tiletype.turf_type), flags = CHANGETURF_INHERIT_AIR) specialtiles -= 1 if(specialtiles == 0) speak("Requesting refill of custom floortiles to continue replacing.") diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 51a9d8d62b..c2c9f5a71f 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -486,10 +486,7 @@ Difficulty: Very Hard if(isturf(Stuff)) var/turf/T = Stuff if((isspaceturf(T) || isfloorturf(T)) && NewTerrainFloors) - var/turf/open/O = T.ChangeTurf(NewTerrainFloors) - if(O.air) - var/datum/gas_mixture/G = O.air - G.copy_from_turf(O) + var/turf/open/O = T.ChangeTurf(NewTerrainFloors, flags = CHANGETURF_INHERIT_AIR) if(prob(florachance) && NewFlora.len && !is_blocked_turf(O, TRUE)) var/atom/Picked = pick(NewFlora) new Picked(O) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm index e3c81b2639..27ebb71c0e 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm @@ -91,5 +91,5 @@ visible_message("The tendril falls inward, the ground around it widening into a yawning chasm!") for(var/turf/T in range(2,src)) if(!T.density) - T.TerraformTurf(/turf/open/chasm/lavaland, /turf/open/chasm/lavaland) + T.TerraformTurf(/turf/open/chasm/lavaland, /turf/open/chasm/lavaland, flags = CHANGETURF_INHERIT_AIR) qdel(src) diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 173d9721a9..791db320a2 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -93,7 +93,7 @@ /obj/item/projectile/magic/door/proc/CreateDoor(turf/T) var/door_type = pick(door_types) var/obj/structure/mineral_door/D = new door_type(T) - T.ChangeTurf(/turf/open/floor/plating) + T.ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) D.Open() /obj/item/projectile/magic/door/proc/OpenDoor(var/obj/machinery/door/D) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index eceb1cdd29..7aae6cc3a5 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1870,133 +1870,82 @@ reagent_state = LIQUID color = "#b51d05" taste_description = "carpet" // Your tounge feels furry. + var/carpet_type = /turf/open/floor/carpet /datum/reagent/carpet/reaction_turf(turf/T, reac_volume) if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet) + F.PlaceOnTop(carpet_type, flags = CHANGETURF_INHERIT_AIR) ..() /datum/reagent/carpet/black name = "Liquid Black Carpet" id = "blackcarpet" color = "#363636" - -/datum/reagent/carpet/black/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/black) - ..() + carpet_type = /turf/open/floor/carpet/black /datum/reagent/carpet/blackred name = "Liquid Red Black Carpet" id = "blackredcarpet" color = "#342125" - -/datum/reagent/carpet/blackred/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/blackred) - ..() + carpet_type = /turf/open/floor/carpet/blackred /datum/reagent/carpet/monochrome name = "Liquid Monochrome Carpet" id = "monochromecarpet" color = "#b4b4b4" - -/datum/reagent/carpet/monochrome/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/monochrome) - ..() + carpet_type = /turf/open/floor/carpet/monochrome /datum/reagent/carpet/blue name = "Liquid Blue Carpet" id = "bluecarpet" color = "#1256ff" - -/datum/reagent/carpet/blue/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/blue) - ..() + carpet_type = /turf/open/floor/carpet/blue /datum/reagent/carpet/cyan name = "Liquid Cyan Carpet" id = "cyancarpet" color = "#3acfb9" - -/datum/reagent/carpet/cyan/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/cyan) - ..() + carpet_type = /turf/open/floor/carpet/cyan /datum/reagent/carpet/green name = "Liquid Green Carpet" id = "greencarpet" color = "#619b62" - -/datum/reagent/carpet/green/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/green) - ..() + carpet_type = /turf/open/floor/carpet/green /datum/reagent/carpet/orange name = "Liquid Orange Carpet" id = "orangecarpet" color = "#cc7900" - -/datum/reagent/carpet/orange/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/orange) - ..() + carpet_type = /turf/open/floor/carpet/orange /datum/reagent/carpet/purple name = "Liquid Purple Carpet" id = "purplecarpet" color = "#6d3392" + carpet_type = /turf/open/floor/carpet/purple -/datum/reagent/carpet/purple/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/purple) - ..() /datum/reagent/carpet/red name = "Liquid Red Carpet" id = "redcarpet" color = "#871515" + carpet_type = /turf/open/floor/carpet/red -/datum/reagent/carpet/red/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/red) - ..() /datum/reagent/carpet/royalblack name = "Liquid Royal Black Carpet" id = "royalblackcarpet" color = "#483d05" + carpet_type = /turf/open/floor/carpet/royalblack -/datum/reagent/carpet/royalblack/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/royalblack) - ..() /datum/reagent/carpet/royalblue name = "Liquid Royal Blue Carpet" id = "royalbluecarpet" color = "#24227e" - -/datum/reagent/carpet/royalblue/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/royalblue) - ..() + carpet_type = /turf/open/floor/carpet/royalblue // Virology virus food chems. diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm index c170858d98..36621aa662 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm @@ -53,7 +53,7 @@ if(isplatingturf(T)) var/turf/open/floor/plating/F = T if(prob(10 + F.burnt + 5*F.broken)) //broken or burnt plating is more susceptible to being destroyed - F.ScrapeAway() + F.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) if(isfloorturf(T)) var/turf/open/floor/F = T if(prob(reac_volume)) diff --git a/code/modules/ruins/objects_and_mobs/sin_ruins.dm b/code/modules/ruins/objects_and_mobs/sin_ruins.dm index caa2ca7adf..76897b5276 100644 --- a/code/modules/ruins/objects_and_mobs/sin_ruins.dm +++ b/code/modules/ruins/objects_and_mobs/sin_ruins.dm @@ -108,7 +108,7 @@ if (levels.len) dest = locate(T.x, T.y, pick(levels)) - T.ChangeTurf(/turf/open/chasm) + T.ChangeTurf(/turf/open/chasm, flags = CHANGETURF_INHERIT_AIR) var/turf/open/chasm/C = T C.set_target(dest) C.drop(user) diff --git a/code/modules/spells/spell_types/conjure.dm b/code/modules/spells/spell_types/conjure.dm index 3ebded7487..38a2d5bddd 100644 --- a/code/modules/spells/spell_types/conjure.dm +++ b/code/modules/spells/spell_types/conjure.dm @@ -31,7 +31,7 @@ if(ispath(summoned_object_type, /turf)) var/turf/O = spawn_place var/N = summoned_object_type - O.ChangeTurf(N) + O.ChangeTurf(N, flags = CHANGETURF_INHERIT_AIR) else var/atom/summoned_object = new summoned_object_type(spawn_place) diff --git a/code/modules/spells/spell_types/devil.dm b/code/modules/spells/spell_types/devil.dm index 8b8328abbe..d97d466e4d 100644 --- a/code/modules/spells/spell_types/devil.dm +++ b/code/modules/spells/spell_types/devil.dm @@ -234,7 +234,7 @@ dancefloor_exists = FALSE for(var/i in 1 to dancefloor_turfs.len) var/turf/T = dancefloor_turfs[i] - T.ChangeTurf(dancefloor_turfs_types[i]) + T.ChangeTurf(dancefloor_turfs_types[i], flags = CHANGETURF_INHERIT_AIR) else var/list/funky_turfs = RANGE_TURFS(1, user) for(var/turf/closed/solid in funky_turfs) @@ -248,7 +248,7 @@ var/turf/T = t dancefloor_turfs[i] = T dancefloor_turfs_types[i] = T.type - T.ChangeTurf((i % 2 == 0) ? /turf/open/floor/light/colour_cycle/dancefloor_a : /turf/open/floor/light/colour_cycle/dancefloor_b) + T.ChangeTurf((i % 2 == 0) ? /turf/open/floor/light/colour_cycle/dancefloor_a : /turf/open/floor/light/colour_cycle/dancefloor_b, flags = CHANGETURF_INHERIT_AIR) i++ /datum/effect_system/smoke_spread/transparent/dancefloor_devil diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm index d7ff42a9eb..7e094eddda 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm @@ -54,7 +54,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die /datum/reagent/fermi/astral/reaction_turf(turf/T, reac_volume) if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/fakespace) + F.PlaceOnTop(/turf/open/floor/fakespace, flags = CHANGETURF_INHERIT_AIR) ..() /datum/reagent/fermi/astral/reaction_obj(obj/O, reac_volume) From 9f21fca798df0aac5e5b3d62422b12c1d366c049 Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 14:18:13 -0800 Subject: [PATCH 018/148] workin on IRV --- code/__DEFINES/citadel_defines.dm | 5 ++ code/controllers/subsystem/ticker.dm | 2 +- code/controllers/subsystem/vote.dm | 77 +++++++++++++++++++++------- 3 files changed, 65 insertions(+), 19 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index e3cafd4613..f954abf453 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -119,3 +119,8 @@ //belly sound pref things #define NORMIE_HEARCHECK 4 + +// Voting stuff (move this somewhere else eventually probs) +#define PLURALITY 0 +#define APPROVAL 1 +#define IRV 2 diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index baaa78e56f..9ca252b1dc 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -480,7 +480,7 @@ SUBSYSTEM_DEF(ticker) SSticker.timeLeft = 900 SSticker.modevoted = TRUE var/dynamic = CONFIG_GET(flag/dynamic_voting) - SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE,dynamic) + SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE,dynamic ? PLURALITY : IRV) /datum/controller/subsystem/ticker/Recover() current_state = SSticker.current_state diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index b34713254d..8daf140121 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -1,6 +1,3 @@ -#define PLURALITY 0 -#define APPROVAL 1 - SUBSYSTEM_DEF(vote) name = "Vote" wait = 10 @@ -89,8 +86,23 @@ SUBSYSTEM_DEF(vote) . += option return . +/datum/controller/subsystem/vote/proc/get_result_runoff() + for(var/i in 1 to choices.len) // if it takes more than this something REALLY wrong happened + for(var/ckey in voted) + choices[voted[ckey][1]]++ + var/least_vote = 100000 + var/least_voted + for(var/option in choices) + if(choices[option] > voted.len/2) + return option + else if(choices[option] < least_vote) + least_vote = choices[option] + least_voted = option + for(var/ckey in voted) + voted[ckey] -= least_voted + /datum/controller/subsystem/vote/proc/announce_result() - var/list/winners = get_result() + var/list/winners = vote_system == IRV ? get_result_runoff() : get_result() var/text var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic" if(winners.len > 0) @@ -214,6 +226,14 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list(vote) choices[choices[vote]]++ return vote + if(IRV) + if(usr.ckey in voted) + if(vote in voted[usr.ckey]) + voted[usr.ckey] -= vote + else + voted += usr.ckey + voted[usr.ckey] = list() + voted[usr.ckey] += vote return 0 /datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults, votesystem = PLURALITY)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes @@ -314,21 +334,42 @@ SUBSYSTEM_DEF(vote) . += "

Vote: '[question]'

" else . += "

Vote: [capitalize(mode)]

" - . += "

Vote [vote_system == PLURALITY ? "your top choice" : "all that apply"].

" + switch(vote_system) + if(PLURALITY) + . += "

Vote one.

" + if(APPROVAL) + . += "

Vote any number of choices.

" + if(IRV) + . += "

Vote by order of preference. Revoting will demote to the bottom.

" . += "Time Left: [time_remaining] s
    " - for(var/i=1,i<=choices.len,i++) - var/votes = choices[choices[i]] - var/ivotedforthis = FALSE - switch(vote_system) - if(PLURALITY) - ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i)) - if(APPROVAL) - ivotedforthis = ((C.ckey in voted) && (i in voted[C.ckey])) - if(!votes) - votes = 0 - . += "
  • [ivotedforthis ? "" : ""][choices[i]] ([obfuscated ? (admin ? "??? ([votes])" : "???") : votes] votes)[ivotedforthis ? "" : ""]
  • " // CIT CHANGE - adds obfuscated votes - if(choice_descs.len >= i) - . += "
  • [choice_descs[i]]
  • " + switch(vote_system) + if(PLURALITY, APPROVAL) + for(var/i=1,i<=choices.len,i++) + var/votes = choices[choices[i]] + var/ivotedforthis = FALSE + switch(vote_system) + if(PLURALITY) + ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i)) + if(APPROVAL) + ivotedforthis = ((C.ckey in voted) && (i in voted[C.ckey])) + if(!votes) + votes = 0 + . += "
  • [ivotedforthis ? "" : ""][choices[i]] ([obfuscated ? (admin ? "??? ([votes])" : "???") : votes] votes)[ivotedforthis ? "" : ""]
  • " // CIT CHANGE - adds obfuscated votes + if(choice_descs.len >= i) + . += "
  • [choice_descs[i]]
  • " + if(IRV) + var/list/display_choices = choices.Copy() + if(C.ckey in voted) + for(var/vote in voted[C.ckey]) + display_choices.Cut(vote,vote+1) + . += "
  • [choices[vote]]
  • " // no reasonable way to show votes with IRV + if(choice_descs.len >= vote) + . += "
  • [choice_descs[vote]]
  • " + for(var/choice in display_choices) + var/index = choices.Find(choice) + . += "
  • [choices[index]]
  • " + if(choice_descs.len >= index) + . += "
  • [choice_descs[index]]
  • " . += "

" if(admin) . += "(Cancel Vote) " From 04f82f3153b4eb4f98ed04b28172b50cf9d00314 Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 15:48:28 -0800 Subject: [PATCH 019/148] it works --- code/__DEFINES/citadel_defines.dm | 6 +-- code/controllers/subsystem/ticker.dm | 5 ++- code/controllers/subsystem/vote.dm | 65 +++++++++++++++------------- 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index f954abf453..7cad6b5be7 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -121,6 +121,6 @@ #define NORMIE_HEARCHECK 4 // Voting stuff (move this somewhere else eventually probs) -#define PLURALITY 0 -#define APPROVAL 1 -#define IRV 2 +#define PLURALITY_VOTING 0 +#define APPROVAL_VOTING 1 +#define INSTANT_RUNOFF_VOTING 2 diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index d676b2df40..cbd7dfdd52 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -480,7 +480,10 @@ SUBSYSTEM_DEF(ticker) SSticker.timeLeft = 900 SSticker.modevoted = TRUE var/dynamic = CONFIG_GET(flag/dynamic_voting) - SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE,dynamic ? PLURALITY : IRV) + if(dynamic) + SSvote.initiate_vote("dynamic","server",TRUE,INSTANT_RUNOFF_VOTING) + else + SSvote.initiate_vote("roundtype","server",TRUE,PLURALITY_VOTING) /datum/controller/subsystem/ticker/Recover() current_state = SSticker.current_state diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 8daf140121..6ea13c832d 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -10,7 +10,7 @@ SUBSYSTEM_DEF(vote) var/started_time = null var/time_remaining = 0 var/mode = null - var/vote_system = PLURALITY + var/vote_system = PLURALITY_VOTING var/question = null var/list/choices = list() var/list/choice_descs = list() // optional descriptions @@ -87,22 +87,29 @@ SUBSYSTEM_DEF(vote) return . /datum/controller/subsystem/vote/proc/get_result_runoff() - for(var/i in 1 to choices.len) // if it takes more than this something REALLY wrong happened + var/already_lost_runoff = list() + for(var/n in 1 to choices.len) // if it takes more than this something REALLY wrong happened for(var/ckey in voted) - choices[voted[ckey][1]]++ + choices[choices[voted[ckey][1]]]++ // jesus christ how horrifying var/least_vote = 100000 var/least_voted - for(var/option in choices) + for(var/i in 1 to choices.len) + var/option = choices[i] if(choices[option] > voted.len/2) - return option - else if(choices[option] < least_vote) + message_admins("[option] has a majority, returning...") + return list(option) + else if(choices[option] < least_vote && !(option in already_lost_runoff)) least_vote = choices[option] - least_voted = option + least_voted = i + message_admins("[choices[least_voted]] lost the runoff, running again...") + already_lost_runoff += choices[least_voted] for(var/ckey in voted) voted[ckey] -= least_voted + for(var/option in choices) + choices[option] = 0 /datum/controller/subsystem/vote/proc/announce_result() - var/list/winners = vote_system == IRV ? get_result_runoff() : get_result() + var/list/winners = vote_system == INSTANT_RUNOFF_VOTING ? get_result_runoff() : get_result() var/text var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic" if(winners.len > 0) @@ -202,7 +209,7 @@ SUBSYSTEM_DEF(vote) return 0 if(vote && vote >= 1 && vote <= choices.len) switch(vote_system) - if(PLURALITY) + if(PLURALITY_VOTING) if(usr.ckey in voted) choices[choices[voted[usr.ckey]]]-- voted[usr.ckey] = vote @@ -213,7 +220,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = vote choices[choices[vote]]++ //check this return vote - if(APPROVAL) + if(APPROVAL_VOTING) if(usr.ckey in voted) if(vote in voted[usr.ckey]) voted[usr.ckey] -= vote @@ -226,7 +233,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list(vote) choices[choices[vote]]++ return vote - if(IRV) + if(INSTANT_RUNOFF_VOTING) if(usr.ckey in voted) if(vote in voted[usr.ckey]) voted[usr.ckey] -= vote @@ -236,7 +243,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] += vote return 0 -/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults, votesystem = PLURALITY)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes +/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults, votesystem = PLURALITY_VOTING)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes vote_system = votesystem if(!mode) if(started_time) @@ -335,41 +342,37 @@ SUBSYSTEM_DEF(vote) else . += "

Vote: [capitalize(mode)]

" switch(vote_system) - if(PLURALITY) + if(PLURALITY_VOTING) . += "

Vote one.

" - if(APPROVAL) + if(APPROVAL_VOTING) . += "

Vote any number of choices.

" - if(IRV) + if(INSTANT_RUNOFF_VOTING) . += "

Vote by order of preference. Revoting will demote to the bottom.

" . += "Time Left: [time_remaining] s
    " switch(vote_system) - if(PLURALITY, APPROVAL) + if(PLURALITY_VOTING, APPROVAL_VOTING) for(var/i=1,i<=choices.len,i++) var/votes = choices[choices[i]] var/ivotedforthis = FALSE switch(vote_system) - if(PLURALITY) + if(PLURALITY_VOTING) ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i)) - if(APPROVAL) + if(APPROVAL_VOTING) ivotedforthis = ((C.ckey in voted) && (i in voted[C.ckey])) if(!votes) votes = 0 . += "
  • [ivotedforthis ? "" : ""][choices[i]] ([obfuscated ? (admin ? "??? ([votes])" : "???") : votes] votes)[ivotedforthis ? "" : ""]
  • " // CIT CHANGE - adds obfuscated votes if(choice_descs.len >= i) . += "
  • [choice_descs[i]]
  • " - if(IRV) - var/list/display_choices = choices.Copy() - if(C.ckey in voted) - for(var/vote in voted[C.ckey]) - display_choices.Cut(vote,vote+1) - . += "
  • [choices[vote]]
  • " // no reasonable way to show votes with IRV - if(choice_descs.len >= vote) - . += "
  • [choice_descs[vote]]
  • " - for(var/choice in display_choices) - var/index = choices.Find(choice) - . += "
  • [choices[index]]
  • " - if(choice_descs.len >= index) - . += "
  • [choice_descs[index]]
  • " + if(INSTANT_RUNOFF_VOTING) + for(var/i=1,i<=choices.len,i++) + var/vote = ((C.ckey in voted) ? (voted[C.ckey].Find(i)) : 0) + if(vote) + . += "
  • [choices[i]] ([vote])
  • " + else + . += "
  • [choices[i]]
  • " + if(choice_descs.len >= i) + . += "
  • [choice_descs[i]]
  • " . += "

" if(admin) . += "(Cancel Vote) " From 5ef7d9cbf736865999dfc167d2dfc5db72d7786b Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 16:09:40 -0800 Subject: [PATCH 020/148] why did i not have revs as conversion --- code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm | 2 +- code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index 8d9d14b473..f014504a68 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -95,7 +95,7 @@ requirements = list(101,101,70,40,40,40,40,40,40,40) high_population_requirement = 40 flags = HIGHLANDER_RULESET - property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2) + property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2, "conversion" = 1) var/required_heads_of_staff = 3 var/finished = FALSE var/datum/team/revolution/revolution diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 1abdcef3f1..f7cf9cd78e 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -378,7 +378,7 @@ flags = HIGHLANDER_RULESET // I give up, just there should be enough heads with 35 players... minimum_players = 35 - property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2) + property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2, "conversion" = 1) var/datum/team/revolution/revolution var/finished = FALSE From f25d75fed9c205c178382ca1f1f80fe3b292503e Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 16:29:24 -0800 Subject: [PATCH 021/148] thanks linter --- code/controllers/subsystem/vote.dm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 6ea13c832d..ed589ca3c8 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -366,7 +366,12 @@ SUBSYSTEM_DEF(vote) . += "
  • [choice_descs[i]]
  • " if(INSTANT_RUNOFF_VOTING) for(var/i=1,i<=choices.len,i++) - var/vote = ((C.ckey in voted) ? (voted[C.ckey].Find(i)) : 0) + var/vote = 0 + //linter yells at me if i use Find here + if(C.ckey in voted) + for(var/n=1,n<=voted[C.ckey].len,n++) + if(voted[C.ckey][n] == i) + vote = n if(vote) . += "
  • [choices[i]] ([vote])
  • " else From 94b7a48bbcec4bace70b962f8302f3ed938e3251 Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 18:29:49 -0800 Subject: [PATCH 022/148] aaa --- code/controllers/subsystem/vote.dm | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index ed589ca3c8..b8068215cf 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -365,13 +365,9 @@ SUBSYSTEM_DEF(vote) if(choice_descs.len >= i) . += "
  • [choice_descs[i]]
  • " if(INSTANT_RUNOFF_VOTING) + var/list/myvote = voted[C.ckey] for(var/i=1,i<=choices.len,i++) - var/vote = 0 - //linter yells at me if i use Find here - if(C.ckey in voted) - for(var/n=1,n<=voted[C.ckey].len,n++) - if(voted[C.ckey][n] == i) - vote = n + var/vote = (myvote ? (myvote.Find(i)) : 0) if(vote) . += "
  • [choices[i]] ([vote])
  • " else From fab65a3dbc41accdd4782dfb67ac92544563ce11 Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 20:12:23 -0800 Subject: [PATCH 023/148] actually condorcet not IRV --- code/__DEFINES/citadel_defines.dm | 2 +- code/controllers/subsystem/ticker.dm | 2 +- code/controllers/subsystem/vote.dm | 41 +++++++++++----------------- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 7cad6b5be7..55526eabc1 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -123,4 +123,4 @@ // Voting stuff (move this somewhere else eventually probs) #define PLURALITY_VOTING 0 #define APPROVAL_VOTING 1 -#define INSTANT_RUNOFF_VOTING 2 +#define RANKED_CHOICE_VOTING 2 diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index cbd7dfdd52..cad5798a4c 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -481,7 +481,7 @@ SUBSYSTEM_DEF(ticker) SSticker.modevoted = TRUE var/dynamic = CONFIG_GET(flag/dynamic_voting) if(dynamic) - SSvote.initiate_vote("dynamic","server",TRUE,INSTANT_RUNOFF_VOTING) + SSvote.initiate_vote("dynamic","server",TRUE,RANKED_CHOICE_VOTING) else SSvote.initiate_vote("roundtype","server",TRUE,PLURALITY_VOTING) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index b8068215cf..42bd00d4af 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -86,30 +86,21 @@ SUBSYSTEM_DEF(vote) . += option return . -/datum/controller/subsystem/vote/proc/get_result_runoff() - var/already_lost_runoff = list() - for(var/n in 1 to choices.len) // if it takes more than this something REALLY wrong happened - for(var/ckey in voted) - choices[choices[voted[ckey][1]]]++ // jesus christ how horrifying - var/least_vote = 100000 - var/least_voted - for(var/i in 1 to choices.len) - var/option = choices[i] - if(choices[option] > voted.len/2) - message_admins("[option] has a majority, returning...") - return list(option) - else if(choices[option] < least_vote && !(option in already_lost_runoff)) - least_vote = choices[option] - least_voted = i - message_admins("[choices[least_voted]] lost the runoff, running again...") - already_lost_runoff += choices[least_voted] - for(var/ckey in voted) - voted[ckey] -= least_voted - for(var/option in choices) - choices[option] = 0 +/datum/controller/subsystem/vote/proc/calculate_condorcet_votes() + for(var/ckey in voted) + var/list/this_vote = voted[ckey] + for(var/a in 1 to choices.len) + for(var/b in a+1 to choices.len) + var/vote_sgn = SIGN(this_vote.Find(a)-this_vote.Find(b)) + if(vote_sgn==-1) + choices[choices[a]]++ + else if(vote_sgn==1) + choices[choices[b]]++ /datum/controller/subsystem/vote/proc/announce_result() - var/list/winners = vote_system == INSTANT_RUNOFF_VOTING ? get_result_runoff() : get_result() + if(vote_system == RANKED_CHOICE_VOTING) + calculate_condorcet_votes() + var/list/winners = get_result() var/text var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic" if(winners.len > 0) @@ -233,7 +224,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list(vote) choices[choices[vote]]++ return vote - if(INSTANT_RUNOFF_VOTING) + if(RANKED_CHOICE_VOTING) if(usr.ckey in voted) if(vote in voted[usr.ckey]) voted[usr.ckey] -= vote @@ -346,7 +337,7 @@ SUBSYSTEM_DEF(vote) . += "

    Vote one.

    " if(APPROVAL_VOTING) . += "

    Vote any number of choices.

    " - if(INSTANT_RUNOFF_VOTING) + if(RANKED_CHOICE_VOTING) . += "

    Vote by order of preference. Revoting will demote to the bottom.

    " . += "Time Left: [time_remaining] s