Conflict fixes
This commit is contained in:
@@ -21,14 +21,13 @@ Doesn't work on other aliens/AI.*/
|
||||
. = ..()
|
||||
action = new(src)
|
||||
|
||||
/obj/effect/proc_holder/alien/Click()
|
||||
if(!iscarbon(usr))
|
||||
return 1
|
||||
var/mob/living/carbon/user = usr
|
||||
if(cost_check(check_turf,user))
|
||||
/obj/effect/proc_holder/alien/Trigger(mob/living/carbon/user, skip_cost_check)
|
||||
if(!istype(user))
|
||||
return TRUE
|
||||
if(!skip_cost_check || cost_check(check_turf,user))
|
||||
if(fire(user) && user) // Second check to prevent runtimes when evolving
|
||||
user.adjustPlasma(-plasma_cost)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/alien/on_gain(mob/living/carbon/user)
|
||||
return
|
||||
|
||||
@@ -63,13 +63,13 @@
|
||||
if(hit_atom)
|
||||
if(isliving(hit_atom))
|
||||
var/mob/living/L = hit_atom
|
||||
if(!L.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
|
||||
if(L.run_block(src, 0, "the [name]", ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS)
|
||||
DefaultCombatKnockdown(40, 1, 1)
|
||||
else
|
||||
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
|
||||
L.DefaultCombatKnockdown(100)
|
||||
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
|
||||
step_towards(src,L)
|
||||
else
|
||||
DefaultCombatKnockdown(40, 1, 1)
|
||||
|
||||
toggle_leap(0)
|
||||
else if(hit_atom.density && !hit_atom.CanPass(src))
|
||||
|
||||
@@ -430,7 +430,6 @@
|
||||
else
|
||||
dropItemToGround(I)
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/get_standard_pixel_y_offset(lying = 0)
|
||||
if(lying)
|
||||
@@ -984,14 +983,121 @@
|
||||
|
||||
/mob/living/carbon/vv_get_dropdown()
|
||||
. = ..()
|
||||
. += "---"
|
||||
.["Make AI"] = "?_src_=vars;[HrefToken()];makeai=[REF(src)]"
|
||||
.["Modify bodypart"] = "?_src_=vars;[HrefToken()];editbodypart=[REF(src)]"
|
||||
.["Modify organs"] = "?_src_=vars;[HrefToken()];editorgans=[REF(src)]"
|
||||
.["Hallucinate"] = "?_src_=vars;[HrefToken()];hallucinate=[REF(src)]"
|
||||
.["Give martial arts"] = "?_src_=vars;[HrefToken()];givemartialart=[REF(src)]"
|
||||
.["Give brain trauma"] = "?_src_=vars;[HrefToken()];givetrauma=[REF(src)]"
|
||||
.["Cure brain traumas"] = "?_src_=vars;[HrefToken()];curetraumas=[REF(src)]"
|
||||
VV_DROPDOWN_OPTION("", "---------")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MAKE_AI, "Make AI")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MODIFY_BODYPART, "Modify bodypart")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MODIFY_ORGANS, "Modify organs")
|
||||
VV_DROPDOWN_OPTION(VV_HK_HALLUCINATION, "Hallucinate")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MARTIAL_ART, "Give Martial Arts")
|
||||
VV_DROPDOWN_OPTION(VV_HK_GIVE_TRAUMA, "Give Brain Trauma")
|
||||
VV_DROPDOWN_OPTION(VV_HK_CURE_TRAUMA, "Cure Brain Traumas")
|
||||
|
||||
/mob/living/carbon/vv_do_topic(list/href_list)
|
||||
. = ..()
|
||||
if(href_list[VV_HK_MODIFY_BODYPART])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
var/edit_action = input(usr, "What would you like to do?","Modify Body Part") as null|anything in list("add","remove", "augment")
|
||||
if(!edit_action)
|
||||
return
|
||||
var/list/limb_list = list()
|
||||
if(edit_action == "remove" || edit_action == "augment")
|
||||
for(var/obj/item/bodypart/B in bodyparts)
|
||||
limb_list += B.body_zone
|
||||
if(edit_action == "remove")
|
||||
limb_list -= BODY_ZONE_CHEST
|
||||
else
|
||||
limb_list = list(BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
for(var/obj/item/bodypart/B in bodyparts)
|
||||
limb_list -= B.body_zone
|
||||
var/result = input(usr, "Please choose which body part to [edit_action]","[capitalize(edit_action)] Body Part") as null|anything in limb_list
|
||||
if(result)
|
||||
var/obj/item/bodypart/BP = get_bodypart(result)
|
||||
switch(edit_action)
|
||||
if("remove")
|
||||
if(BP)
|
||||
BP.drop_limb()
|
||||
else
|
||||
to_chat(usr, "[src] doesn't have such bodypart.")
|
||||
if("add")
|
||||
if(BP)
|
||||
to_chat(usr, "[src] already has such bodypart.")
|
||||
else
|
||||
if(!regenerate_limb(result))
|
||||
to_chat(usr, "[src] cannot have such bodypart.")
|
||||
if("augment")
|
||||
if(ishuman(src))
|
||||
if(BP)
|
||||
BP.change_bodypart_status(BODYPART_ROBOTIC, TRUE, TRUE)
|
||||
else
|
||||
to_chat(usr, "[src] doesn't have such bodypart.")
|
||||
else
|
||||
to_chat(usr, "Only humans can be augmented.")
|
||||
admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [src]")
|
||||
if(href_list[VV_HK_MAKE_AI])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
|
||||
return
|
||||
usr.client.holder.Topic("vv_override", list("makeai"=href_list[VV_HK_TARGET]))
|
||||
if(href_list[VV_HK_MODIFY_ORGANS])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
usr.client.manipulate_organs(src)
|
||||
if(href_list[VV_HK_MARTIAL_ART])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
var/list/artpaths = subtypesof(/datum/martial_art)
|
||||
var/list/artnames = list()
|
||||
for(var/i in artpaths)
|
||||
var/datum/martial_art/M = i
|
||||
artnames[initial(M.name)] = M
|
||||
var/result = input(usr, "Choose the martial art to teach","JUDO CHOP") as null|anything in artnames
|
||||
if(!usr)
|
||||
return
|
||||
if(QDELETED(src))
|
||||
to_chat(usr, "Mob doesn't exist anymore")
|
||||
return
|
||||
if(result)
|
||||
var/chosenart = artnames[result]
|
||||
var/datum/martial_art/MA = new chosenart
|
||||
MA.teach(src)
|
||||
log_admin("[key_name(usr)] has taught [MA] to [key_name(src)].")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has taught [MA] to [key_name_admin(src)].</span>")
|
||||
if(href_list[VV_HK_GIVE_TRAUMA])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
var/list/traumas = subtypesof(/datum/brain_trauma)
|
||||
var/result = input(usr, "Choose the brain trauma to apply","Traumatize") as null|anything in traumas
|
||||
if(!usr)
|
||||
return
|
||||
if(QDELETED(src))
|
||||
to_chat(usr, "Mob doesn't exist anymore")
|
||||
return
|
||||
if(!result)
|
||||
return
|
||||
var/datum/brain_trauma/BT = gain_trauma(result)
|
||||
if(BT)
|
||||
log_admin("[key_name(usr)] has traumatized [key_name(src)] with [BT.name]")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has traumatized [key_name_admin(src)] with [BT.name].</span>")
|
||||
if(href_list[VV_HK_CURE_TRAUMA])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
cure_all_traumas(TRAUMA_RESILIENCE_ABSOLUTE)
|
||||
log_admin("[key_name(usr)] has cured all traumas from [key_name(src)].")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has cured all traumas from [key_name_admin(src)].</span>")
|
||||
if(href_list[VV_HK_HALLUCINATION])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
var/list/hallucinations = subtypesof(/datum/hallucination)
|
||||
var/result = input(usr, "Choose the hallucination to apply","Send Hallucination") as null|anything in hallucinations
|
||||
if(!usr)
|
||||
return
|
||||
if(QDELETED(src))
|
||||
to_chat(usr, "Mob doesn't exist anymore")
|
||||
return
|
||||
if(result)
|
||||
new result(src, TRUE)
|
||||
|
||||
/mob/living/carbon/can_resist()
|
||||
return bodyparts.len > 2 && ..()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses
|
||||
var/obj/item/clothing/glasses/GFP = src.glasses
|
||||
number += GFP.flash_protect
|
||||
|
||||
|
||||
if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask
|
||||
var/obj/item/clothing/mask/MFP = src.wear_mask
|
||||
number += MFP.flash_protect
|
||||
@@ -86,13 +86,10 @@
|
||||
if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
|
||||
totitemdamage *= 1.5
|
||||
//CIT CHANGES END HERE
|
||||
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
|
||||
var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected)
|
||||
if((user != src) && (run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone) & BLOCK_SUCCESS))
|
||||
return FALSE
|
||||
var/obj/item/bodypart/affecting
|
||||
if(user == src)
|
||||
affecting = get_bodypart(check_zone(user.zone_selected)) //we're self-mutilating! yay!
|
||||
else
|
||||
affecting = get_bodypart(ran_zone(user.zone_selected))
|
||||
var/obj/item/bodypart/affecting = get_bodypart(impacting_zone)
|
||||
if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest)
|
||||
affecting = bodyparts[1]
|
||||
SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
|
||||
@@ -278,6 +275,8 @@
|
||||
|
||||
if(health >= 0 && !(HAS_TRAIT(src, TRAIT_FAKEDEATH)))
|
||||
var/friendly_check = FALSE
|
||||
if(run_block(M, 0, M.name, ATTACK_TYPE_UNARMED))
|
||||
return
|
||||
if(lying)
|
||||
if(buckled)
|
||||
to_chat(M, "<span class='warning'>You need to unbuckle [src] first to do that!")
|
||||
|
||||
@@ -849,15 +849,95 @@
|
||||
|
||||
/mob/living/carbon/human/vv_get_dropdown()
|
||||
. = ..()
|
||||
. += "---"
|
||||
.["Make monkey"] = "?_src_=vars;[HrefToken()];makemonkey=[REF(src)]"
|
||||
.["Set Species"] = "?_src_=vars;[HrefToken()];setspecies=[REF(src)]"
|
||||
.["Make cyborg"] = "?_src_=vars;[HrefToken()];makerobot=[REF(src)]"
|
||||
.["Make alien"] = "?_src_=vars;[HrefToken()];makealien=[REF(src)]"
|
||||
.["Make slime"] = "?_src_=vars;[HrefToken()];makeslime=[REF(src)]"
|
||||
.["Toggle Purrbation"] = "?_src_=vars;[HrefToken()];purrbation=[REF(src)]"
|
||||
.["Copy outfit"] = "?_src_=vars;[HrefToken()];copyoutfit=[REF(src)]"
|
||||
.["Add/Remove Quirks"] = "?_src_=vars;[HrefToken()];modquirks=[REF(src)]"
|
||||
VV_DROPDOWN_OPTION("", "---------")
|
||||
VV_DROPDOWN_OPTION(VV_HK_COPY_OUTFIT, "Copy Outfit")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MOD_QUIRKS, "Add/Remove Quirks")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MAKE_MONKEY, "Make Monkey")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MAKE_CYBORG, "Make Cyborg")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MAKE_SLIME, "Make Slime")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MAKE_ALIEN, "Make Alien")
|
||||
VV_DROPDOWN_OPTION(VV_HK_SET_SPECIES, "Set Species")
|
||||
VV_DROPDOWN_OPTION(VV_HK_PURRBATION, "Toggle Purrbation")
|
||||
|
||||
/mob/living/carbon/human/vv_do_topic(list/href_list)
|
||||
. = ..()
|
||||
if(href_list[VV_HK_COPY_OUTFIT])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
copy_outfit()
|
||||
if(href_list[VV_HK_MOD_QUIRKS])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
|
||||
var/list/options = list("Clear"="Clear")
|
||||
for(var/x in subtypesof(/datum/quirk))
|
||||
var/datum/quirk/T = x
|
||||
var/qname = initial(T.name)
|
||||
options[has_quirk(T) ? "[qname] (Remove)" : "[qname] (Add)"] = T
|
||||
|
||||
var/result = input(usr, "Choose quirk to add/remove","Quirk Mod") as null|anything in options
|
||||
if(result)
|
||||
if(result == "Clear")
|
||||
for(var/datum/quirk/q in roundstart_quirks)
|
||||
remove_quirk(q.type)
|
||||
else
|
||||
var/T = options[result]
|
||||
if(has_quirk(T))
|
||||
remove_quirk(T)
|
||||
else
|
||||
add_quirk(T,TRUE)
|
||||
if(href_list[VV_HK_MAKE_MONKEY])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
|
||||
return
|
||||
usr.client.holder.Topic("vv_override", list("monkeyone"=href_list[VV_HK_TARGET]))
|
||||
if(href_list[VV_HK_MAKE_CYBORG])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
|
||||
return
|
||||
usr.client.holder.Topic("vv_override", list("makerobot"=href_list[VV_HK_TARGET]))
|
||||
if(href_list[VV_HK_MAKE_ALIEN])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
|
||||
return
|
||||
usr.client.holder.Topic("vv_override", list("makealien"=href_list[VV_HK_TARGET]))
|
||||
if(href_list[VV_HK_MAKE_SLIME])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
|
||||
return
|
||||
usr.client.holder.Topic("vv_override", list("makeslime"=href_list[VV_HK_TARGET]))
|
||||
if(href_list[VV_HK_SET_SPECIES])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
var/result = input(usr, "Please choose a new species","Species") as null|anything in GLOB.species_list
|
||||
if(result)
|
||||
var/newtype = GLOB.species_list[result]
|
||||
admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [src] to [result]")
|
||||
set_species(newtype)
|
||||
if(href_list[VV_HK_PURRBATION])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
if(!ishumanbasic(src))
|
||||
to_chat(usr, "This can only be done to the basic human species at the moment.")
|
||||
return
|
||||
var/success = purrbation_toggle(src)
|
||||
if(success)
|
||||
to_chat(usr, "Put [src] on purrbation.")
|
||||
log_admin("[key_name(usr)] has put [key_name(src)] on purrbation.")
|
||||
var/msg = "<span class='notice'>[key_name_admin(usr)] has put [key_name(src)] on purrbation.</span>"
|
||||
message_admins(msg)
|
||||
admin_ticket_log(src, msg)
|
||||
|
||||
else
|
||||
to_chat(usr, "Removed [src] from purrbation.")
|
||||
log_admin("[key_name(usr)] has removed [key_name(src)] from purrbation.")
|
||||
var/msg = "<span class='notice'>[key_name_admin(usr)] has removed [key_name(src)] from purrbation.</span>"
|
||||
message_admins(msg)
|
||||
admin_ticket_log(src, msg)
|
||||
|
||||
/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user)
|
||||
if(pulling == target && grab_state >= GRAB_AGGRESSIVE && stat == CONSCIOUS)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/mob/living/carbon/human/get_blocking_items()
|
||||
. = ..()
|
||||
if(wear_suit)
|
||||
. += wear_suit
|
||||
if(w_uniform)
|
||||
. += w_uniform
|
||||
if(wear_neck)
|
||||
. += wear_neck
|
||||
@@ -52,36 +52,12 @@
|
||||
return martial_art_result
|
||||
return ..()
|
||||
|
||||
/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)
|
||||
. = ..()
|
||||
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 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 TRUE
|
||||
if(wear_neck)
|
||||
var/final_block_chance = wear_neck.block_chance - (CLAMP((armour_penetration-wear_neck.armour_penetration)/2,0,100)) + block_chance_modifier
|
||||
if(wear_neck.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
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()
|
||||
/mob/living/carbon/human/proc/check_martial_melee_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))
|
||||
return TRUE
|
||||
|
||||
@@ -893,7 +893,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
accessory_overlay.icon_state = "m_ears_none_[layertext]"
|
||||
if(bodypart == "tail")
|
||||
accessory_overlay.icon_state = "m_tail_husk_[layertext]"
|
||||
if(MATRIXED)
|
||||
if(S.color_src == MATRIXED)
|
||||
var/list/husklist = list()
|
||||
husklist += ReadRGB("#a3a3a3")
|
||||
husklist += ReadRGB("#a3a3a3")
|
||||
@@ -1437,7 +1437,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
to_chat(user, "<span class='notice'>You do not breathe, so you cannot perform CPR.</span>")
|
||||
|
||||
/datum/species/proc/grab(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
|
||||
if(target.check_block())
|
||||
if(target.check_martial_melee_block())
|
||||
target.visible_message("<span class='warning'>[target] blocks [user]'s grab attempt!</span>")
|
||||
return 0
|
||||
if(attacker_style && attacker_style.grab_act(user,target))
|
||||
@@ -1453,9 +1453,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if(IS_STAMCRIT(user)) //CITADEL CHANGE - makes it impossible to punch while in stamina softcrit
|
||||
to_chat(user, "<span class='warning'>You're too exhausted.</span>") //CITADEL CHANGE - ditto
|
||||
return FALSE //CITADEL CHANGE - ditto
|
||||
if(target.check_block())
|
||||
if(target.check_martial_melee_block())
|
||||
target.visible_message("<span class='warning'>[target] blocks [user]'s attack!</span>")
|
||||
return FALSE
|
||||
|
||||
if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes punching cause staminaloss but funny martial artist types get a discount
|
||||
user.adjustStaminaLossBuffered(1.5)
|
||||
else
|
||||
user.adjustStaminaLossBuffered(3.5)
|
||||
|
||||
if(attacker_style && attacker_style.harm_act(user,target))
|
||||
return TRUE
|
||||
else
|
||||
@@ -1474,13 +1480,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
else
|
||||
user.do_attack_animation(target, ATTACK_EFFECT_PUNCH)
|
||||
|
||||
user.adjustStaminaLossBuffered(5) //CITADEL CHANGE - makes punching cause staminaloss
|
||||
|
||||
var/damage = rand(user.dna.species.punchdamagelow, user.dna.species.punchdamagehigh)
|
||||
var/puncherstam = user.getStaminaLoss()
|
||||
var/puncherbrute = user.getBruteLoss()
|
||||
var/punchedstam = target.getStaminaLoss()
|
||||
var/punchedbrute = target.getBruteLoss()
|
||||
|
||||
//CITADEL CHANGES - makes resting and disabled combat mode reduce punch damage, makes being out of combat mode result in you taking more damage
|
||||
if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && damage < user.dna.species.punchstunthreshold)
|
||||
damage = user.dna.species.punchstunthreshold - 1
|
||||
if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
|
||||
damage *= 1.5
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
|
||||
damage *= 0.5
|
||||
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
|
||||
@@ -1494,7 +1502,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if(atk_verb == ATTACK_EFFECT_KICK) //kicks never miss (provided your species deals more than 0 damage)
|
||||
miss_chance = 0
|
||||
else
|
||||
miss_chance = min((user.dna.species.punchdamagehigh/user.dna.species.punchdamagelow) + user.getStaminaLoss() + (user.getBruteLoss()*0.5), 100) //old base chance for a miss + various damage. capped at 100 to prevent weirdness in prob()
|
||||
miss_chance = min(10 + ((puncherstam + puncherbrute)*0.5), 100) //probability of miss has a base of 10, and modified based on half your stamina and brute total. Capped at max 100 and min 0 to prevent weirdness in prob()
|
||||
|
||||
if(!damage || !affecting || prob(miss_chance))//future-proofing for species that have 0 damage/weird cases where no zone is targeted
|
||||
playsound(target.loc, user.dna.species.miss_sound, 25, TRUE, -1)
|
||||
@@ -1529,13 +1537,25 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
log_combat(user, target, "punched")
|
||||
|
||||
if((target.stat != DEAD) && damage >= user.dna.species.punchstunthreshold)
|
||||
target.visible_message("<span class='danger'>[user] knocks [target] down!</span>", \
|
||||
"<span class='userdanger'>You're knocked down by [user]!</span>", "<span class='hear'>You hear aggressive shuffling followed by a loud thud!</span>", COMBAT_MESSAGE_RANGE, user)
|
||||
to_chat(user, "<span class='danger'>You knock [target] down!</span>")
|
||||
var/knockdown_duration = 40 + (target.getStaminaLoss() + (target.getBruteLoss()*0.5))*0.8 - armor_block
|
||||
target.DefaultCombatKnockdown(knockdown_duration)
|
||||
target.forcesay(GLOB.hit_appends)
|
||||
log_combat(user, target, "got a stun punch with their previous punch")
|
||||
if((punchedstam > 50) && prob(punchedstam*0.5)) //If our punch victim has been hit above the threshold, and they have more than 50 stamina damage, roll for stun, probability of 1% per 2 stamina damage
|
||||
|
||||
target.visible_message("<span class='danger'>[user] knocks [target] down!</span>", \
|
||||
"<span class='userdanger'>You're knocked down by [user]!</span>", "<span class='hear'>You hear aggressive shuffling followed by a loud thud!</span>", COMBAT_MESSAGE_RANGE, user)
|
||||
to_chat(user, "<span class='danger'>You knock [target] down!</span>")
|
||||
|
||||
var/knockdown_duration = 40 + (punchedstam + (punchedbrute*0.5))*0.8 - armor_block
|
||||
target.DefaultCombatKnockdown(knockdown_duration)
|
||||
target.forcesay(GLOB.hit_appends)
|
||||
log_combat(user, target, "got a stun punch with their previous punch")
|
||||
|
||||
if(HAS_TRAIT(user, TRAIT_KI_VAMPIRE) && !HAS_TRAIT(target, TRAIT_NOBREATH) && (punchedbrute < 100)) //If we're a ki vampire we also sap them of lifeforce, but only if they're not too beat up. Also living organics only.
|
||||
user.adjustBruteLoss(-5)
|
||||
user.adjustFireLoss(-5)
|
||||
user.adjustStaminaLoss(-20)
|
||||
|
||||
target.adjustCloneLoss(10)
|
||||
target.adjustBruteLoss(10)
|
||||
|
||||
else if(!(target.mobility_flags & MOBILITY_STAND))
|
||||
target.forcesay(GLOB.hit_appends)
|
||||
|
||||
@@ -1552,6 +1572,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/aim_for_groin = user.zone_selected == "groin"
|
||||
var/target_aiming_for_groin = target.zone_selected == "groin"
|
||||
|
||||
if(target.check_martial_melee_block()) //END EDIT
|
||||
target.visible_message("<span class='warning'>[target] blocks [user]'s disarm attempt!</span>")
|
||||
return FALSE
|
||||
if(IS_STAMCRIT(user))
|
||||
to_chat(user, "<span class='warning'>You're too exhausted!</span>")
|
||||
return FALSE
|
||||
@@ -1680,9 +1703,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
|
||||
// Allows you to put in item-specific reactions based on species
|
||||
if(user != H)
|
||||
if(H.check_shields(I, I.force, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
|
||||
if(H.run_block(I, I.force, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone) & BLOCK_SUCCESS)
|
||||
return 0
|
||||
if(H.check_block())
|
||||
if(H.check_martial_melee_block())
|
||||
H.visible_message("<span class='warning'>[H] blocks [I]!</span>")
|
||||
return 0
|
||||
|
||||
@@ -1798,7 +1821,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
return TRUE
|
||||
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))
|
||||
if((M != H) && M.a_intent != INTENT_HELP && (H.run_block(M, 0, "[M]", ATTACK_TYPE_UNARMED, 0, M, M.zone_selected) & BLOCK_SUCCESS))
|
||||
log_combat(M, H, "attempted to touch")
|
||||
H.visible_message("<span class='warning'>[M] attempted to touch [H]!</span>")
|
||||
return TRUE
|
||||
@@ -1836,7 +1859,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if(IS_STAMCRIT(user))
|
||||
to_chat(user, "<span class='warning'>You're too exhausted.</span>")
|
||||
return FALSE
|
||||
if(target.check_block())
|
||||
if(target.check_martial_melee_block())
|
||||
target.visible_message("<span class='warning'>[target] blocks [user]'s shoving attempt!</span>")
|
||||
return FALSE
|
||||
if(attacker_style && attacker_style.disarm_act(user,target))
|
||||
|
||||
@@ -92,6 +92,8 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
|
||||
//These count in on_life ticks which should be 2 seconds per every increment of 1 in a perfect world.
|
||||
var/dwarf_filth_ticker = 0 //Currently set =< 4, that means this will fire the proc around every 4-8 seconds.
|
||||
var/dwarf_eth_ticker = 0 //Currently set =< 1, that means this will fire the proc around every 2 seconds
|
||||
var/last_filth_spam
|
||||
var/last_alcohol_spam
|
||||
|
||||
/obj/item/organ/dwarfgland/prepare_eat()
|
||||
var/obj/S = ..()
|
||||
@@ -136,40 +138,39 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
|
||||
filth_counter += 10 //Dwarves could technically chainstun each other in a vomit tantrum spiral.
|
||||
switch(filth_counter)
|
||||
if(11 to 25)
|
||||
if(prob(25))
|
||||
to_chat(owner, "<span class = 'danger'>Someone should really clean up in here!</span>")
|
||||
if(last_filth_spam + 40 SECONDS < world.time)
|
||||
to_chat(owner, "<span class = 'warning'>Someone should really clean up in here!</span>")
|
||||
last_filth_spam = world.time
|
||||
if(26 to 50)
|
||||
if(prob(30)) //Probability the message appears
|
||||
if(prob(6)) //And then the probability they vomit along with it.
|
||||
to_chat(owner, "<span class = 'danger'>The stench makes you queasy.</span>")
|
||||
if(prob(20)) //And then the probability they vomit along with it.
|
||||
owner.vomit(20) //I think vomit should stay over a disgust adjustment.
|
||||
owner.vomit(10) //I think vomit should stay over a disgust adjustment.
|
||||
if(51 to 75)
|
||||
if(prob(35))
|
||||
if(prob(9))
|
||||
to_chat(owner, "<span class = 'danger'>By Armok! You won't be able to keep alcohol down at all!</span>")
|
||||
if(prob(25))
|
||||
owner.vomit(20) //Its more funny
|
||||
owner.vomit(20) //Its more funny
|
||||
if(76 to 100)
|
||||
if(prob(40))
|
||||
if(prob(11))
|
||||
to_chat(owner, "<span class = 'userdanger'>You can't live in such FILTH!</span>")
|
||||
if(prob(25))
|
||||
owner.adjustToxLoss(10) //Now they start dying.
|
||||
owner.vomit(20)
|
||||
owner.adjustToxLoss(10) //Now they start dying.
|
||||
owner.vomit(20)
|
||||
if(101 to INFINITY) //Now they will really start dying
|
||||
if(prob(40))
|
||||
if(last_filth_spam + 12 SECONDS < world.time)
|
||||
to_chat(owner, "<span class = 'userdanger'> THERES TOO MUCH FILTH, OH GODS THE FILTH!</span>")
|
||||
last_filth_spam = world.time
|
||||
if(prob(40))
|
||||
owner.adjustToxLoss(15)
|
||||
owner.vomit(40)
|
||||
owner.vomit(30)
|
||||
CHECK_TICK //Check_tick right here, its motherfuckin magic. (To me at least)
|
||||
|
||||
//Handles the dwarf alcohol cycle tied to on_life, it ticks in dwarf_cycle_ticker.
|
||||
/obj/item/organ/dwarfgland/proc/dwarf_eth_cycle()
|
||||
//BOOZE POWER
|
||||
var/init_stored_alcohol = stored_alcohol
|
||||
for(var/datum/reagent/R in owner.reagents.reagent_list)
|
||||
if(istype(R, /datum/reagent/consumable/ethanol))
|
||||
var/datum/reagent/consumable/ethanol/E = R
|
||||
stored_alcohol += (E.boozepwr / 50)
|
||||
if(stored_alcohol > max_alcohol) //Dwarves technically start at 250 alcohol stored.
|
||||
stored_alcohol = max_alcohol
|
||||
stored_alcohol = CLAMP(stored_alcohol + E.boozepwr / 50, 0, max_alcohol)
|
||||
var/heal_amt = heal_rate
|
||||
stored_alcohol -= alcohol_rate //Subtracts alcohol_Rate from stored alcohol so EX: 250 - 0.25 per each loop that occurs.
|
||||
if(stored_alcohol > 400) //If they are over 400 they start regenerating
|
||||
@@ -177,16 +178,27 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
|
||||
owner.adjustFireLoss(-heal_amt) //Unless they drink casually all the time.
|
||||
owner.adjustOxyLoss(-heal_amt)
|
||||
owner.adjustCloneLoss(-heal_amt) //Also they will probably get brain damage if thats a thing here.
|
||||
if(prob(25))
|
||||
switch(stored_alcohol)
|
||||
if(0 to 24)
|
||||
if(init_stored_alcohol + 0.5 < stored_alcohol) //recovering stored alcohol at a steady rate of +0.75, no spam.
|
||||
return
|
||||
switch(stored_alcohol)
|
||||
if(0 to 24)
|
||||
if(last_alcohol_spam + 8 SECONDS < world.time)
|
||||
to_chat(owner, "<span class='userdanger'>DAMNATION INCARNATE, WHY AM I CURSED WITH THIS DRY-SPELL? I MUST DRINK.</span>")
|
||||
owner.adjustToxLoss(35)
|
||||
if(25 to 50)
|
||||
last_alcohol_spam = world.time
|
||||
owner.adjustToxLoss(10)
|
||||
if(25 to 50)
|
||||
if(last_alcohol_spam + 20 SECONDS < world.time)
|
||||
to_chat(owner, "<span class='danger'>Oh DAMN, I need some brew!</span>")
|
||||
if(51 to 75)
|
||||
last_alcohol_spam = world.time
|
||||
if(51 to 75)
|
||||
if(last_alcohol_spam + 35 SECONDS < world.time)
|
||||
to_chat(owner, "<span class='warning'>Your body aches, you need to get ahold of some booze...</span>")
|
||||
if(76 to 100)
|
||||
last_alcohol_spam = world.time
|
||||
if(76 to 100)
|
||||
if(last_alcohol_spam + 40 SECONDS < world.time)
|
||||
to_chat(owner, "<span class='notice'>A pint of anything would really hit the spot right now.</span>")
|
||||
if(101 to 150)
|
||||
last_alcohol_spam = world.time
|
||||
if(101 to 150)
|
||||
if(last_alcohol_spam + 50 SECONDS < world.time)
|
||||
to_chat(owner, "<span class='notice'>You feel like you could use a good brew.</span>")
|
||||
last_alcohol_spam = world.time
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
siemens_coeff = 0
|
||||
punchdamagelow = 5
|
||||
punchdamagehigh = 14
|
||||
punchstunthreshold = 11 //about 40% chance to stun
|
||||
punchstunthreshold = 10
|
||||
no_equip = list(SLOT_WEAR_MASK, SLOT_WEAR_SUIT, SLOT_GLOVES, SLOT_SHOES, SLOT_W_UNIFORM, SLOT_S_STORE)
|
||||
nojumpsuit = 1
|
||||
sexes = 1
|
||||
@@ -168,7 +168,7 @@
|
||||
name = "Silver Golem"
|
||||
id = "silver golem"
|
||||
fixed_mut_color = "ddd"
|
||||
punchstunthreshold = 9 //60% chance, from 40%
|
||||
punchstunthreshold = 9
|
||||
meat = /obj/item/stack/ore/silver
|
||||
info_text = "As a <span class='danger'>Silver Golem</span>, your attacks have a higher chance of stunning. Being made of silver, your body is immune to most types of magic."
|
||||
prefix = "Silver"
|
||||
@@ -190,7 +190,7 @@
|
||||
stunmod = 0.4
|
||||
punchdamagelow = 12
|
||||
punchdamagehigh = 21
|
||||
punchstunthreshold = 18 //still 40% stun chance
|
||||
punchstunthreshold = 18
|
||||
speedmod = 4 //pretty fucking slow
|
||||
meat = /obj/item/stack/ore/iron
|
||||
info_text = "As a <span class='danger'>Plasteel Golem</span>, you are slower, but harder to stun, and hit very hard when punching."
|
||||
@@ -469,7 +469,7 @@
|
||||
var/cooldown = 150
|
||||
var/last_teleport = 0
|
||||
|
||||
/datum/action/innate/unstable_teleport/IsAvailable()
|
||||
/datum/action/innate/unstable_teleport/IsAvailable(silent = FALSE)
|
||||
if(..())
|
||||
if(world.time > last_teleport + cooldown)
|
||||
return 1
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
background_icon_state = "bg_alien"
|
||||
required_mobility_flags = NONE
|
||||
|
||||
/datum/action/innate/regenerate_limbs/IsAvailable()
|
||||
/datum/action/innate/regenerate_limbs/IsAvailable(silent = FALSE)
|
||||
if(..())
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/list/limbs_to_heal = H.get_missing_limbs()
|
||||
@@ -223,7 +223,7 @@
|
||||
icon_icon = 'icons/mob/actions/actions_slime.dmi'
|
||||
background_icon_state = "bg_alien"
|
||||
|
||||
/datum/action/innate/split_body/IsAvailable()
|
||||
/datum/action/innate/split_body/IsAvailable(silent = FALSE)
|
||||
if(..())
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
|
||||
@@ -776,7 +776,7 @@
|
||||
..()
|
||||
species = _species
|
||||
|
||||
/datum/action/innate/use_extract/IsAvailable()
|
||||
/datum/action/innate/use_extract/IsAvailable(silent = FALSE)
|
||||
if(..())
|
||||
if(species && species.current_extract && (world.time > species.extract_cooldown))
|
||||
return TRUE
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
inherent_traits = list(TRAIT_NOBREATH)
|
||||
speedmod = 1.5 //faster than golems but not by much
|
||||
|
||||
punchdamagelow = 6
|
||||
punchdamagehigh = 14
|
||||
punchstunthreshold = 14 //about 44% chance to stun
|
||||
punchdamagelow = 2
|
||||
punchdamagehigh = 12 //still better than humans
|
||||
punchstunthreshold = 10
|
||||
|
||||
no_equip = list(SLOT_WEAR_MASK, SLOT_WEAR_SUIT, SLOT_GLOVES, SLOT_SHOES, SLOT_W_UNIFORM)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
armor = 25
|
||||
punchdamagelow = 10
|
||||
punchdamagehigh = 19
|
||||
punchstunthreshold = 14 //about 50% chance to stun
|
||||
punchstunthreshold = 14
|
||||
disguise_fail_health = 50
|
||||
|
||||
/datum/species/synth/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
|
||||
|
||||
@@ -152,5 +152,7 @@
|
||||
if(transfer_name)
|
||||
H.name = caster.name
|
||||
|
||||
clothes_req = 0
|
||||
human_req = 0
|
||||
|
||||
clothes_req = NONE
|
||||
mobs_whitelist = null
|
||||
mobs_blacklist = null
|
||||
|
||||
@@ -118,17 +118,15 @@ There are several things that need to be remembered:
|
||||
return
|
||||
|
||||
|
||||
var/t_color = U.item_color
|
||||
if(!t_color)
|
||||
t_color = U.icon_state
|
||||
var/target_overlay = U.icon_state
|
||||
if(U.adjusted == ALT_STYLE)
|
||||
t_color = "[t_color]_d"
|
||||
target_overlay = "[target_overlay]_d"
|
||||
|
||||
var/alt_worn = U.alternate_worn_icon || 'icons/mob/uniform.dmi'
|
||||
var/alt_worn = U.mob_overlay_icon || 'icons/mob/clothing/uniform.dmi'
|
||||
var/variant_flag = NONE
|
||||
|
||||
if((DIGITIGRADE in dna.species.species_traits) && U.mutantrace_variation & STYLE_DIGITIGRADE)
|
||||
alt_worn = 'icons/mob/uniform_digi.dmi'
|
||||
alt_worn = 'icons/mob/clothing/uniform_digi.dmi'
|
||||
variant_flag |= STYLE_DIGITIGRADE
|
||||
|
||||
var/mutable_appearance/uniform_overlay
|
||||
@@ -136,10 +134,10 @@ There are several things that need to be remembered:
|
||||
if(dna && dna.species.sexes)
|
||||
var/G = (dna.features["body_model"] == FEMALE) ? "f" : "m"
|
||||
if(G == "f" && U.fitted != NO_FEMALE_UNIFORM)
|
||||
uniform_overlay = U.build_worn_icon(t_color, UNIFORM_LAYER, alt_worn, FALSE, U.fitted, variant_flag, FALSE)
|
||||
uniform_overlay = U.build_worn_icon(UNIFORM_LAYER, alt_worn, FALSE, U.fitted, target_overlay, variant_flag, FALSE)
|
||||
|
||||
if(!uniform_overlay)
|
||||
uniform_overlay = U.build_worn_icon(t_color, UNIFORM_LAYER, alt_worn, FALSE, NO_FEMALE_UNIFORM, variant_flag, FALSE)
|
||||
uniform_overlay = U.build_worn_icon( UNIFORM_LAYER, alt_worn, FALSE, NO_FEMALE_UNIFORM, target_overlay, variant_flag, FALSE)
|
||||
|
||||
|
||||
if(OFFSET_UNIFORM in dna.species.offset_features)
|
||||
@@ -167,7 +165,7 @@ There are several things that need to be remembered:
|
||||
update_observer_view(wear_id)
|
||||
|
||||
//TODO: add an icon file for ID slot stuff, so it's less snowflakey
|
||||
id_overlay = wear_id.build_worn_icon(state = wear_id.item_state, default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi')
|
||||
id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi', override_state = wear_id.item_state)
|
||||
if(OFFSET_ID in dna.species.offset_features)
|
||||
id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1]
|
||||
id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2]
|
||||
@@ -199,10 +197,7 @@ There are several things that need to be remembered:
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += gloves
|
||||
update_observer_view(gloves,1)
|
||||
var/t_state = gloves.item_state
|
||||
if(!t_state)
|
||||
t_state = gloves.icon_state
|
||||
overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(state = t_state, default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/hands.dmi')
|
||||
overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/clothing/hands.dmi')
|
||||
gloves_overlay = overlays_standing[GLOVES_LAYER]
|
||||
if(OFFSET_GLOVES in dna.species.offset_features)
|
||||
gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1]
|
||||
@@ -228,7 +223,7 @@ There are several things that need to be remembered:
|
||||
client.screen += glasses //Either way, add the item to the HUD
|
||||
update_observer_view(glasses,1)
|
||||
if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES)))
|
||||
overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(state = glasses.icon_state, default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/eyes.dmi')
|
||||
overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/clothing/eyes.dmi', override_state = glasses.icon_state)
|
||||
var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER]
|
||||
if(glasses_overlay)
|
||||
if(OFFSET_GLASSES in dna.species.offset_features)
|
||||
@@ -255,7 +250,7 @@ There are several things that need to be remembered:
|
||||
client.screen += ears //add it to the client's screen
|
||||
update_observer_view(ears,1)
|
||||
|
||||
overlays_standing[EARS_LAYER] = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi')
|
||||
overlays_standing[EARS_LAYER] = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi')
|
||||
var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
|
||||
if(OFFSET_EARS in dna.species.offset_features)
|
||||
ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1]
|
||||
@@ -282,16 +277,13 @@ There are several things that need to be remembered:
|
||||
client.screen += shoes //add it to client's screen
|
||||
update_observer_view(shoes,1)
|
||||
|
||||
var/alt_icon = S.alternate_worn_icon || 'icons/mob/feet.dmi'
|
||||
var/alt_icon = S.mob_overlay_icon || 'icons/mob/clothing/feet.dmi'
|
||||
var/variation_flag = NONE
|
||||
if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE)
|
||||
alt_icon = 'icons/mob/feet_digi.dmi'
|
||||
alt_icon = 'icons/mob/clothing/feet_digi.dmi'
|
||||
variation_flag |= STYLE_DIGITIGRADE
|
||||
|
||||
var/t_state = shoes.item_state
|
||||
if (!t_state)
|
||||
t_state = shoes.icon_state
|
||||
overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(t_state, SHOES_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, variation_flag, FALSE)
|
||||
overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(SHOES_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, variation_flag, FALSE)
|
||||
var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER]
|
||||
if(OFFSET_SHOES in dna.species.offset_features)
|
||||
shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1]
|
||||
@@ -314,7 +306,7 @@ There are several things that need to be remembered:
|
||||
var/t_state = s_store.item_state
|
||||
if(!t_state)
|
||||
t_state = s_store.icon_state
|
||||
overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.alternate_worn_icon) ? s_store.alternate_worn_icon : 'icons/mob/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER)
|
||||
overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.mob_overlay_icon) ? s_store.mob_overlay_icon : 'icons/mob/clothing/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER)
|
||||
var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_STORE_LAYER]
|
||||
if(OFFSET_S_STORE in dna.species.offset_features)
|
||||
s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1]
|
||||
@@ -324,12 +316,24 @@ There are several things that need to be remembered:
|
||||
|
||||
|
||||
/mob/living/carbon/human/update_inv_head()
|
||||
..()
|
||||
update_mutant_bodyparts()
|
||||
remove_overlay(HEAD_LAYER)
|
||||
|
||||
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
|
||||
return
|
||||
|
||||
if(client && hud_used)
|
||||
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
|
||||
inv.update_icon()
|
||||
|
||||
if(head)
|
||||
head.screen_loc = ui_head
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += head
|
||||
update_observer_view(head,1)
|
||||
remove_overlay(HEAD_LAYER)
|
||||
var/obj/item/clothing/head/H = head
|
||||
var/alt_icon = H.alternate_worn_icon || 'icons/mob/head.dmi'
|
||||
var/alt_icon = H.mob_overlay_icon || 'icons/mob/clothing/head.dmi'
|
||||
var/muzzled = FALSE
|
||||
var/variation_flag = NONE
|
||||
if(dna.species.mutant_bodyparts["mam_snouts"] && dna.features["mam_snouts"] != "None")
|
||||
@@ -337,10 +341,10 @@ There are several things that need to be remembered:
|
||||
else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None")
|
||||
muzzled = TRUE
|
||||
if(muzzled && H.mutantrace_variation & STYLE_MUZZLE)
|
||||
alt_icon = 'icons/mob/head_muzzled.dmi'
|
||||
alt_icon = 'icons/mob/clothing/head_muzzled.dmi'
|
||||
variation_flag |= STYLE_MUZZLE
|
||||
|
||||
overlays_standing[HEAD_LAYER] = H.build_worn_icon(H.icon_state, HEAD_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, variation_flag, FALSE)
|
||||
overlays_standing[HEAD_LAYER] = H.build_worn_icon(HEAD_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, H.icon_state, variation_flag, FALSE)
|
||||
var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER]
|
||||
|
||||
if(OFFSET_HEAD in dna.species.offset_features)
|
||||
@@ -348,6 +352,7 @@ There are several things that need to be remembered:
|
||||
head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2]
|
||||
overlays_standing[HEAD_LAYER] = head_overlay
|
||||
apply_overlay(HEAD_LAYER)
|
||||
update_mutant_bodyparts()
|
||||
|
||||
/mob/living/carbon/human/update_inv_belt()
|
||||
remove_overlay(BELT_LAYER)
|
||||
@@ -362,11 +367,7 @@ There are several things that need to be remembered:
|
||||
client.screen += belt
|
||||
update_observer_view(belt)
|
||||
|
||||
var/t_state = belt.item_state
|
||||
if(!t_state)
|
||||
t_state = belt.icon_state
|
||||
|
||||
overlays_standing[BELT_LAYER] = belt.build_worn_icon(state = t_state, default_layer = BELT_LAYER, default_icon_file = 'icons/mob/belt.dmi')
|
||||
overlays_standing[BELT_LAYER] = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = 'icons/mob/clothing/belt.dmi')
|
||||
var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER]
|
||||
if(OFFSET_BELT in dna.species.offset_features)
|
||||
belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1]
|
||||
@@ -390,7 +391,7 @@ There are several things that need to be remembered:
|
||||
client.screen += wear_suit
|
||||
update_observer_view(wear_suit,1)
|
||||
|
||||
var/worn_icon = wear_suit.alternate_worn_icon || 'icons/mob/suit.dmi'
|
||||
var/worn_icon = wear_suit.mob_overlay_icon || 'icons/mob/clothing/suit.dmi'
|
||||
var/center = FALSE
|
||||
var/dimension_x = 32
|
||||
var/dimension_y = 32
|
||||
@@ -405,20 +406,20 @@ There are several things that need to be remembered:
|
||||
variation_flag |= S.mutantrace_variation & T.taur_mode || S.mutantrace_variation & T.alt_taur_mode
|
||||
switch(variation_flag)
|
||||
if(STYLE_HOOF_TAURIC)
|
||||
worn_icon = 'icons/mob/taur_hooved.dmi'
|
||||
worn_icon = 'icons/mob/clothing/taur_hooved.dmi'
|
||||
if(STYLE_SNEK_TAURIC)
|
||||
worn_icon = 'icons/mob/taur_naga.dmi'
|
||||
worn_icon = 'icons/mob/clothing/taur_naga.dmi'
|
||||
if(STYLE_PAW_TAURIC)
|
||||
worn_icon = 'icons/mob/taur_canine.dmi'
|
||||
worn_icon = 'icons/mob/clothing/taur_canine.dmi'
|
||||
if(worn_icon != init_worn_icon) //worn icon sprite was changed, taur offsets will have to be applied.
|
||||
center = T.center
|
||||
dimension_x = T.dimension_x
|
||||
dimension_y = T.dimension_y
|
||||
else if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE) //not a taur, but digitigrade legs.
|
||||
worn_icon = 'icons/mob/suit_digi.dmi'
|
||||
worn_icon = 'icons/mob/clothing/suit_digi.dmi'
|
||||
variation_flag |= STYLE_DIGITIGRADE
|
||||
|
||||
overlays_standing[SUIT_LAYER] = S.build_worn_icon(wear_suit.icon_state, SUIT_LAYER, worn_icon, FALSE, NO_FEMALE_UNIFORM, variation_flag, FALSE)
|
||||
overlays_standing[SUIT_LAYER] = S.build_worn_icon(SUIT_LAYER, worn_icon, FALSE, NO_FEMALE_UNIFORM, wear_suit.icon_state, variation_flag, FALSE)
|
||||
var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER]
|
||||
if(OFFSET_SUIT in dna.species.offset_features)
|
||||
suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
|
||||
@@ -456,11 +457,24 @@ There are several things that need to be remembered:
|
||||
|
||||
|
||||
/mob/living/carbon/human/update_inv_wear_mask()
|
||||
..()
|
||||
remove_overlay(FACEMASK_LAYER)
|
||||
|
||||
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
|
||||
return
|
||||
|
||||
if(client && hud_used)
|
||||
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
|
||||
inv.update_icon()
|
||||
|
||||
if(wear_mask)
|
||||
wear_mask.screen_loc = ui_mask
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += wear_mask
|
||||
update_observer_view(wear_mask,1)
|
||||
var/obj/item/clothing/mask/M = wear_mask
|
||||
remove_overlay(FACEMASK_LAYER)
|
||||
var/alt_icon = M.alternate_worn_icon || 'icons/mob/mask.dmi'
|
||||
var/alt_icon = M.mob_overlay_icon || 'icons/mob/clothing/mask.dmi'
|
||||
var/muzzled = FALSE
|
||||
var/variation_flag = NONE
|
||||
if(head && (head.flags_inv & HIDEMASK))
|
||||
@@ -470,11 +484,10 @@ There are several things that need to be remembered:
|
||||
else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None")
|
||||
muzzled = TRUE
|
||||
if(muzzled && M.mutantrace_variation & STYLE_MUZZLE)
|
||||
alt_icon = 'icons/mob/mask_muzzled.dmi'
|
||||
alt_icon = 'icons/mob/clothing/mask_muzzled.dmi'
|
||||
variation_flag |= STYLE_MUZZLE
|
||||
|
||||
overlays_standing[FACEMASK_LAYER] = M.build_worn_icon(wear_mask.icon_state, FACEMASK_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, variation_flag, FALSE)
|
||||
var/mutable_appearance/mask_overlay = overlays_standing[FACEMASK_LAYER]
|
||||
var/mutable_appearance/mask_overlay = M.build_worn_icon(FACEMASK_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, wear_mask.icon_state, variation_flag, FALSE)
|
||||
|
||||
if(OFFSET_FACEMASK in dna.species.offset_features)
|
||||
mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1]
|
||||
@@ -512,22 +525,6 @@ There are several things that need to be remembered:
|
||||
|
||||
//human HUD updates for items in our inventory
|
||||
|
||||
//update whether our head item appears on our hud.
|
||||
/mob/living/carbon/human/update_hud_head(obj/item/I)
|
||||
I.screen_loc = ui_head
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += I
|
||||
update_observer_view(I,1)
|
||||
|
||||
//update whether our mask item appears on our hud.
|
||||
/mob/living/carbon/human/update_hud_wear_mask(obj/item/I)
|
||||
I.screen_loc = ui_mask
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += I
|
||||
update_observer_view(I,1)
|
||||
|
||||
//update whether our neck item appears on our hud.
|
||||
/mob/living/carbon/human/update_hud_neck(obj/item/I)
|
||||
I.screen_loc = ui_neck
|
||||
@@ -556,27 +553,32 @@ covers:
|
||||
|
||||
By Remie Richards (yes I'm taking credit because this just removed 90% of the copypaste in update_icons())
|
||||
|
||||
state: A string to use as the state, this is FAR too complex to solve in this proc thanks to shitty old code
|
||||
so it's specified as an argument instead.
|
||||
override_state: A string to use as the state, otherwise item_state or icon_state will be used.
|
||||
|
||||
default_layer: The layer to draw this on if no other layer is specified
|
||||
|
||||
default_icon_file: The icon file to draw states from if no other icon file is specified
|
||||
|
||||
isinhands: If true then alternate_worn_icon is skipped so that default_icon_file is used,
|
||||
isinhands: If true then mob_overlay_icon is skipped so that default_icon_file is used,
|
||||
in this situation default_icon_file is expected to match either the lefthand_ or righthand_ file var
|
||||
|
||||
femalueuniform: A value matching a uniform item's fitted var, if this is anything but NO_FEMALE_UNIFORM, we
|
||||
generate/load female uniform sprites matching all previously decided variables
|
||||
|
||||
style_flags: mutant race appearance flags, mostly used for worn_overlays()
|
||||
|
||||
use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if mob_overlay_icon is present.
|
||||
|
||||
*/
|
||||
/obj/item/proc/build_worn_icon(state = "", default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, style_flags = NONE, use_alt_icon = TRUE)
|
||||
/obj/item/proc/build_worn_icon(default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, override_state, style_flags = NONE, use_mob_overlay_icon = TRUE)
|
||||
|
||||
var/t_state
|
||||
t_state = override_state || item_state || icon_state
|
||||
|
||||
//Find a valid icon file from variables+arguments
|
||||
var/file2use
|
||||
if(!isinhands && alternate_worn_icon && use_alt_icon)
|
||||
file2use = alternate_worn_icon
|
||||
if(!isinhands && mob_overlay_icon && use_mob_overlay_icon)
|
||||
file2use = mob_overlay_icon
|
||||
if(!file2use)
|
||||
file2use = default_icon_file
|
||||
|
||||
@@ -589,13 +591,13 @@ generate/load female uniform sprites matching all previously decided variables
|
||||
|
||||
var/mutable_appearance/standing
|
||||
if(femaleuniform)
|
||||
standing = wear_female_version(state,file2use,layer2use,femaleuniform)
|
||||
standing = wear_female_version(t_state,file2use,layer2use,femaleuniform)
|
||||
if(!standing)
|
||||
standing = mutable_appearance(file2use, state, -layer2use)
|
||||
standing = mutable_appearance(file2use, t_state, -layer2use)
|
||||
|
||||
//Get the overlays for this item when it's being worn
|
||||
//eg: ammo counters, primed grenade flashes, etc.
|
||||
var/list/worn_overlays = worn_overlays(isinhands, file2use, style_flags)
|
||||
var/list/worn_overlays = worn_overlays(isinhands, file2use, t_state, style_flags)
|
||||
if(worn_overlays && worn_overlays.len)
|
||||
standing.overlays.Add(worn_overlays)
|
||||
|
||||
|
||||
@@ -28,10 +28,8 @@
|
||||
if(stat != DEAD)
|
||||
handle_brain_damage()
|
||||
|
||||
/* BUG_PROBABLE_CAUSE
|
||||
if(stat != DEAD)
|
||||
handle_liver()
|
||||
*/
|
||||
|
||||
if(stat == DEAD)
|
||||
stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
@@ -377,9 +375,15 @@
|
||||
|
||||
var/turf/open/miasma_turf = deceasedturf
|
||||
|
||||
var/list/cached_gases = miasma_turf.air.gases
|
||||
var/datum/gas_mixture/stank = new
|
||||
|
||||
cached_gases[/datum/gas/miasma] += 0.1
|
||||
stank.gases[/datum/gas/miasma] = 0.1
|
||||
|
||||
stank.temperature = BODYTEMP_NORMAL
|
||||
|
||||
miasma_turf.assume_air(stank)
|
||||
|
||||
miasma_turf.air_update_turf()
|
||||
|
||||
/mob/living/carbon/proc/handle_blood()
|
||||
return
|
||||
@@ -684,36 +688,17 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
|
||||
var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER)
|
||||
if((!dna && !liver) || (NOLIVER in dna.species.species_traits))
|
||||
return
|
||||
if(liver)
|
||||
if(liver.damage < liver.maxHealth)
|
||||
liver.organ_flags |= ORGAN_FAILING
|
||||
liver_failure()
|
||||
else
|
||||
if(!liver || liver.organ_flags & ORGAN_FAILING)
|
||||
liver_failure()
|
||||
|
||||
/mob/living/carbon/proc/undergoing_liver_failure()
|
||||
var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER)
|
||||
if(liver && liver.failing)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/proc/return_liver_damage()
|
||||
var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER)
|
||||
if(liver)
|
||||
return liver.damage
|
||||
|
||||
/mob/living/carbon/proc/applyLiverDamage(var/d)
|
||||
var/obj/item/organ/liver/L = getorganslot(ORGAN_SLOT_LIVER)
|
||||
if(L)
|
||||
L.damage += d
|
||||
|
||||
/mob/living/carbon/proc/liver_failure()
|
||||
reagents.end_metabolization(src, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs
|
||||
reagents.metabolize(src, can_overdose=FALSE, liverless = TRUE)
|
||||
if(HAS_TRAIT(src, TRAIT_STABLELIVER))
|
||||
return
|
||||
adjustToxLoss(4, TRUE, TRUE)
|
||||
if(prob(30))
|
||||
to_chat(src, "<span class='warning'>You feel a stabbing pain in your abdomen!</span>")
|
||||
if(prob(15))
|
||||
to_chat(src, "<span class='danger'>You feel a stabbing pain in your abdomen!</span>")
|
||||
|
||||
|
||||
////////////////
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
remove_overlay(LEGCUFF_LAYER)
|
||||
clear_alert("legcuffed")
|
||||
if(legcuffed)
|
||||
var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER)
|
||||
var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/clothing/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER)
|
||||
legcuffs.color = handcuffed.color
|
||||
legcuffs.pixel_y = 8
|
||||
|
||||
|
||||
@@ -42,15 +42,11 @@
|
||||
observers = null
|
||||
break
|
||||
|
||||
var/t_state = I.item_state
|
||||
if(!t_state)
|
||||
t_state = I.icon_state
|
||||
|
||||
var/icon_file = I.lefthand_file
|
||||
if(get_held_index_of_item(I) % 2 == 0)
|
||||
icon_file = I.righthand_file
|
||||
|
||||
hands += I.build_worn_icon(state = t_state, default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE)
|
||||
hands += I.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE)
|
||||
|
||||
overlays_standing[HANDS_LAYER] = hands
|
||||
apply_overlay(HANDS_LAYER)
|
||||
@@ -94,13 +90,13 @@
|
||||
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
|
||||
return
|
||||
|
||||
if(client && hud_used && hud_used.inv_slots[SLOT_WEAR_MASK])
|
||||
if(client && hud_used)
|
||||
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
|
||||
inv.update_icon()
|
||||
inv?.update_icon()
|
||||
|
||||
if(wear_mask)
|
||||
if(!(head && (head.flags_inv & HIDEMASK)))
|
||||
overlays_standing[FACEMASK_LAYER] = wear_mask.build_worn_icon(state = wear_mask.icon_state, default_layer = FACEMASK_LAYER, default_icon_file = 'icons/mob/mask.dmi')
|
||||
overlays_standing[FACEMASK_LAYER] = wear_mask.build_worn_icon(default_layer = FACEMASK_LAYER, default_icon_file = 'icons/mob/clothing/mask.dmi', override_state = wear_mask.icon_state)
|
||||
update_hud_wear_mask(wear_mask)
|
||||
|
||||
apply_overlay(FACEMASK_LAYER)
|
||||
@@ -114,7 +110,7 @@
|
||||
|
||||
if(wear_neck)
|
||||
if(!(head && (head.flags_inv & HIDENECK)))
|
||||
overlays_standing[NECK_LAYER] = wear_neck.build_worn_icon(state = wear_neck.icon_state, default_layer = NECK_LAYER, default_icon_file = 'icons/mob/neck.dmi')
|
||||
overlays_standing[NECK_LAYER] = wear_neck.build_worn_icon(default_layer = NECK_LAYER, default_icon_file = 'icons/mob/clothing/neck.dmi', override_state = wear_neck.icon_state)
|
||||
update_hud_neck(wear_neck)
|
||||
|
||||
apply_overlay(NECK_LAYER)
|
||||
@@ -122,12 +118,12 @@
|
||||
/mob/living/carbon/update_inv_back()
|
||||
remove_overlay(BACK_LAYER)
|
||||
|
||||
if(client && hud_used && hud_used.inv_slots[SLOT_BACK])
|
||||
if(client && hud_used)
|
||||
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BACK]
|
||||
inv.update_icon()
|
||||
inv?.update_icon()
|
||||
|
||||
if(back)
|
||||
overlays_standing[BACK_LAYER] = back.build_worn_icon(state = back.icon_state, default_layer = BACK_LAYER, default_icon_file = 'icons/mob/back.dmi')
|
||||
overlays_standing[BACK_LAYER] = back.build_worn_icon(default_layer = BACK_LAYER, default_icon_file = 'icons/mob/clothing/back.dmi', override_state = back.icon_state)
|
||||
update_hud_back(back)
|
||||
|
||||
apply_overlay(BACK_LAYER)
|
||||
@@ -138,12 +134,12 @@
|
||||
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
|
||||
return
|
||||
|
||||
if(client && hud_used && hud_used.inv_slots[SLOT_BACK])
|
||||
if(client && hud_used)
|
||||
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
|
||||
inv.update_icon()
|
||||
inv?.update_icon()
|
||||
|
||||
if(head)
|
||||
overlays_standing[HEAD_LAYER] = head.build_worn_icon(state = head.icon_state, default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/head.dmi')
|
||||
overlays_standing[HEAD_LAYER] = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/clothing/head.dmi', override_state = head.icon_state)
|
||||
update_hud_head(head)
|
||||
|
||||
apply_overlay(HEAD_LAYER)
|
||||
@@ -152,7 +148,7 @@
|
||||
/mob/living/carbon/update_inv_handcuffed()
|
||||
remove_overlay(HANDCUFF_LAYER)
|
||||
if(handcuffed)
|
||||
var/mutable_appearance/cuffs = mutable_appearance('icons/mob/restraints.dmi', handcuffed.item_state, -HANDCUFF_LAYER)
|
||||
var/mutable_appearance/cuffs = mutable_appearance('icons/mob/clothing/restraints.dmi', handcuffed.item_state, -HANDCUFF_LAYER)
|
||||
cuffs.color = handcuffed.color
|
||||
|
||||
overlays_standing[HANDCUFF_LAYER] = cuffs
|
||||
@@ -162,7 +158,7 @@
|
||||
remove_overlay(LEGCUFF_LAYER)
|
||||
clear_alert("legcuffed")
|
||||
if(legcuffed)
|
||||
var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER)
|
||||
var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/clothing/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER)
|
||||
legcuffs.color = legcuffed.color
|
||||
|
||||
overlays_standing[LEGCUFF_LAYER] = legcuffs
|
||||
@@ -195,15 +191,6 @@
|
||||
/mob/living/carbon/proc/update_hud_back(obj/item/I)
|
||||
return
|
||||
|
||||
|
||||
|
||||
//Overlays for the worn overlay so you can overlay while you overlay
|
||||
//eg: ammo counters, primed grenade flashing, etc.
|
||||
//"icon_file" is used automatically for inhands etc. to make sure it gets the right inhand file
|
||||
/obj/item/proc/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
|
||||
. = list()
|
||||
|
||||
|
||||
/mob/living/carbon/update_body()
|
||||
update_body_parts()
|
||||
|
||||
|
||||
@@ -1198,3 +1198,19 @@
|
||||
gender = ngender
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/vv_get_header()
|
||||
. = ..()
|
||||
var/refid = REF(src)
|
||||
. += {"
|
||||
<br><font size='1'>[VV_HREF_TARGETREF_1V(refid, VV_HK_BASIC_EDIT, "[ckey || "no ckey"]", NAMEOF(src, ckey))] / [VV_HREF_TARGETREF_1V(refid, VV_HK_BASIC_EDIT, "[real_name || "no real name"]", NAMEOF(src, real_name))]</font>
|
||||
<br><font size='1'>
|
||||
BRUTE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brute' id='brute'>[getBruteLoss()]</a>
|
||||
FIRE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=fire' id='fire'>[getFireLoss()]</a>
|
||||
TOXIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=toxin' id='toxin'>[getToxLoss()]</a>
|
||||
OXY:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=oxygen' id='oxygen'>[getOxyLoss()]</a>
|
||||
CLONE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=clone' id='clone'>[getCloneLoss()]</a>
|
||||
BRAIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brain' id='brain'>[getOrganLoss(ORGAN_SLOT_BRAIN)]</a>
|
||||
STAMINA:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=stamina' id='stamina'>[getStaminaLoss()]</a>
|
||||
</font>
|
||||
"}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
// This file has a weird name, but it's for anything related to the checks for shields, blocking, dodging, and similar "stop this attack before it actually impacts the target" as opposed to "defend once it has hit".
|
||||
|
||||
/*
|
||||
/// Bitflags for check_block() and handle_block(). Meant to be combined. You can be hit and still reflect, for example, if you do not use BLOCK_SUCCESS.
|
||||
/// Attack was not blocked
|
||||
#define BLOCK_NONE NONE
|
||||
/// Attack was blocked, do not do damage. THIS FLAG MUST BE THERE FOR DAMAGE/EFFECT PREVENTION!
|
||||
#define BLOCK_SUCCESS (1<<1)
|
||||
|
||||
/// The below are for "metadata" on "how" the attack was blocked.
|
||||
|
||||
/// Attack was and should be reflected (NOTE: the SHOULD here is important, as it says "the thing blocking isn't handling the reflecting for you so do it yourself"!)
|
||||
#define BLOCK_SHOULD_REFLECT (1<<2)
|
||||
/// Attack was manually redirected (including reflected) by any means by the defender. For when YOU are handling the reflection, rather than the thing hitting you. (see sleeping carp)
|
||||
#define BLOCK_REDIRECTED (1<<3)
|
||||
/// Attack was blocked by something like a shield.
|
||||
#define BLOCK_PHYSICAL_EXTERNAL (1<<4)
|
||||
/// Attack was blocked by something worn on you.
|
||||
#define BLOCK_PHYSICAL_INTERNAL (1<<5)
|
||||
/// Attack should pass through. Like SHOULD_REFLECT but for.. well, passing through harmlessly.
|
||||
#define BLOCK_SHOULD_PASSTHROUGH (1<<6)
|
||||
/// Attack outright missed because the target dodged. Should usually be combined with SHOULD_PASSTHROUGH or something (see martial arts)
|
||||
#define BLOCK_TARGET_DODGED (1<<7)
|
||||
*/
|
||||
|
||||
///Check whether or not we can block, without "triggering" a block. Basically run checks without effects like depleting shields. Wrapper for do_run_block(). The arguments on that means the same as for this.
|
||||
/mob/living/proc/check_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list)
|
||||
return do_run_block(FALSE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list)
|
||||
|
||||
/// Runs a block "sequence", effectively checking and then doing effects if necessary. Wrapper for do_run_block(). The arguments on that means the same as for this.
|
||||
/mob/living/proc/run_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list)
|
||||
return do_run_block(TRUE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list)
|
||||
|
||||
/** The actual proc for block checks. DO NOT USE THIS DIRECTLY UNLESS YOU HAVE VERY GOOD REASON TO. To reduce copypaste for differences between handling for real attacks and virtual checks.
|
||||
* Automatically checks all held items for /obj/item/proc/run_block() with the same parameters.
|
||||
* @params
|
||||
* real_attack - If this attack is real. This one is quirky; If it's real, run_block is called. If it's not, check_block is called and none of the regular checks happen, and this is effectively only useful
|
||||
* for populating return_list with blocking metadata.
|
||||
* object - Whatever /atom is actually hitting us, in essence. For example, projectile if gun, item if melee, structure/whatever if it's a thrown, etc.
|
||||
* damage - The nominal damage this would do if it was to hit. Obviously doesn't take into effect explosions/magic/similar things.. unless you implement it to raise the value.
|
||||
* attack_text - The text that this attack should show, in the context of something like "[src] blocks [attack_text]!"
|
||||
* attack_type - See __DEFINES/combat.dm - Attack types, to distinguish between, for example, someone throwing an item at us vs bashing us with it.
|
||||
* armour_penetration - 0-100 value of how effectively armor penetrating the attack should be.
|
||||
* attacker - Set to the mob attacking IF KNOWN. Do not expect this to always be set!
|
||||
* def_zone - The zone this'll impact.
|
||||
* return_list - If something wants to grab things from what items/whatever put into list/block_return on obj/item/run_block and the comsig, pass in a list so you can grab anything put in it after block runs.
|
||||
*/
|
||||
/mob/living/proc/do_run_block(real_attack = TRUE, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list())
|
||||
// Component signal block runs have highest priority.. for now.
|
||||
. = SEND_SIGNAL(src, COMSIG_LIVING_RUN_BLOCK, real_attack, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)
|
||||
if((. & BLOCK_SUCCESS) && !(. & BLOCK_CONTINUE_CHAIN))
|
||||
return
|
||||
var/list/obj/item/tocheck = get_blocking_items()
|
||||
sortTim(tocheck, /proc/cmp_item_block_priority_asc)
|
||||
// i don't like this
|
||||
var/block_chance_modifier = round(damage / -3)
|
||||
if(real_attack)
|
||||
for(var/obj/item/I in tocheck)
|
||||
// i don't like this too
|
||||
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
|
||||
var/results = I.run_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list)
|
||||
. |= results
|
||||
if((results & BLOCK_SUCCESS) && !(results & BLOCK_CONTINUE_CHAIN))
|
||||
break
|
||||
else
|
||||
for(var/obj/item/I in tocheck)
|
||||
// i don't like this too
|
||||
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
|
||||
I.check_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list)
|
||||
|
||||
/// Gets an unsortedlist of objects to run block checks on.
|
||||
/mob/living/proc/get_blocking_items()
|
||||
. = list()
|
||||
for(var/obj/item/I in held_items)
|
||||
// this is a bad check but i am not removing it until a better catchall is made
|
||||
if(istype(I, /obj/item/clothing))
|
||||
continue
|
||||
. |= I
|
||||
|
||||
/obj/item
|
||||
/// The 0% to 100% chance for the default implementation of random block rolls.
|
||||
var/block_chance = 0
|
||||
/// Block priority, higher means we check this higher in the "chain".
|
||||
var/block_priority = BLOCK_PRIORITY_DEFAULT
|
||||
|
||||
/// Runs block and returns flag for do_run_block to process.
|
||||
/obj/item/proc/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_RUN_BLOCK, owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
|
||||
if(prob(final_block_chance))
|
||||
owner.visible_message("<span class='danger'>[owner] blocks [attack_text] with [src]!</span>")
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
|
||||
return BLOCK_NONE
|
||||
|
||||
/// Returns block information using list/block_return. Used for check_block() on mobs.
|
||||
/obj/item/proc/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_CHECK_BLOCK, owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
|
||||
var/existing = block_return[BLOCK_RETURN_NORMAL_BLOCK_CHANCE]
|
||||
block_return[BLOCK_RETURN_NORMAL_BLOCK_CHANCE] = max(existing || 0, final_block_chance)
|
||||
@@ -36,48 +36,44 @@
|
||||
/mob/living/proc/on_hit(obj/item/projectile/P)
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
/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/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("<span class='danger'>The [P.name] gets reflected by [src]!</span>", \
|
||||
"<span class='userdanger'>The [P.name] gets reflected by [src]!</span>")
|
||||
// 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/proc/handle_projectile_attack_redirection(obj/item/projectile/P, redirection_mode, silent = FALSE)
|
||||
P.ignore_source_check = TRUE
|
||||
switch(redirection_mode)
|
||||
if(REDIRECT_METHOD_DEFLECT)
|
||||
P.setAngle(SIMPLIFY_DEGREES(P.Angle + rand(120, 240)))
|
||||
if(!silent)
|
||||
visible_message("<span class='danger'>[P] gets deflected by [src]!</span>", \
|
||||
"<span class='userdanger'>[P] gets deflected by [src]!</span>")
|
||||
if(REDIRECT_METHOD_REFLECT)
|
||||
P.setAngle(SIMPLIFY_DEGREES(P.Angle + 180))
|
||||
if(!silent)
|
||||
visible_message("<span class='danger'>[P] gets reflected by [src]!</span>", \
|
||||
"<span class='userdanger'>[P] gets reflected by [src]!</span>")
|
||||
if(REDIRECT_METHOD_PASSTHROUGH)
|
||||
if(!silent)
|
||||
visible_message("<span class='danger'>[P] passes through [src]!</span>", \
|
||||
"<span class='userdanger'>[P] passes through [src]!</span>")
|
||||
return
|
||||
if(REDIRECT_METHOD_RETURN_TO_SENDER)
|
||||
if(!silent)
|
||||
visible_message("<span class='danger'>[src] deflects [P] back at their attacker!</span>", \
|
||||
"<span class='userdanger'>[src] deflects [P] back at their attacker!</span>")
|
||||
if(P.firer)
|
||||
P.setAngle(Get_Angle(src, P.firer))
|
||||
else
|
||||
P.setAngle(SIMPLIFY_DEGREES(P.Angle + 180))
|
||||
else
|
||||
CRASH("Invalid rediretion mode [redirection_mode]")
|
||||
|
||||
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
|
||||
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 BULLET_ACT_FORCE_PIERCE // complete projectile permutation
|
||||
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
|
||||
var/list/returnlist = list()
|
||||
var/returned = run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist)
|
||||
if(returned & BLOCK_SHOULD_REDIRECT)
|
||||
handle_projectile_attack_redirection(P, returnlist[BLOCK_RETURN_REDIRECT_METHOD])
|
||||
if(returned & BLOCK_REDIRECTED)
|
||||
return BULLET_ACT_FORCE_PIERCE
|
||||
if(returned & BLOCK_SUCCESS)
|
||||
P.on_hit(src, 100, def_zone)
|
||||
return BULLET_ACT_BLOCK
|
||||
var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null)
|
||||
@@ -108,12 +104,14 @@
|
||||
return FALSE
|
||||
|
||||
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
// Throwingdatum can be null if someone had an accident() while slipping with an item in hand.
|
||||
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))
|
||||
var/impacting_zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
|
||||
if(run_block(AM, throwpower, "\the [AM.name]", ATTACK_TYPE_THROWN, 0, throwingdatum?.thrower, impacting_zone) & BLOCK_SUCCESS)
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE
|
||||
blocked = TRUE
|
||||
@@ -124,10 +122,9 @@
|
||||
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()
|
||||
SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, zone)
|
||||
SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, impacting_zone)
|
||||
dtype = I.damtype
|
||||
|
||||
if (I.throwforce > 0) //If the weapon's throwforce is greater than zero...
|
||||
@@ -145,8 +142,8 @@
|
||||
if(!blocked)
|
||||
visible_message("<span class='danger'>[src] has been hit by [I].</span>", \
|
||||
"<span class='userdanger'>[src] has been hit by [I].</span>")
|
||||
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
|
||||
apply_damage(I.throwforce, dtype, zone, armor)
|
||||
var/armor = run_armor_check(impacting_zone, "melee", "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration)
|
||||
apply_damage(I.throwforce, dtype, impacting_zone, armor)
|
||||
if(I.thrownby)
|
||||
log_combat(I.thrownby, src, "threw and hit", I)
|
||||
else
|
||||
@@ -193,17 +190,6 @@
|
||||
if(user == anchored || !isturf(user.loc))
|
||||
return FALSE
|
||||
|
||||
//pacifist vore check.
|
||||
if(user.pulling && HAS_TRAIT(user, TRAIT_PACIFISM) && user.voremode) //they can only do heals, noisy guts, absorbing (technically not harm)
|
||||
if(ismob(user.pulling))
|
||||
var/mob/P = user.pulling
|
||||
if(src != user)
|
||||
to_chat(user, "<span class='notice'>You can't risk digestion!</span>")
|
||||
return FALSE
|
||||
else
|
||||
user.vore_attack(user, P, user)
|
||||
return
|
||||
|
||||
//normal vore check.
|
||||
if(user.pulling && user.grab_state == GRAB_AGGRESSIVE && user.voremode)
|
||||
if(ismob(user.pulling))
|
||||
@@ -283,7 +269,7 @@
|
||||
/mob/living/attack_hand(mob/user)
|
||||
..() //Ignoring parent return value here.
|
||||
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))
|
||||
if((user != src) && user.a_intent != INTENT_HELP && (run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS))
|
||||
log_combat(user, src, "attempted to touch")
|
||||
visible_message("<span class='warning'>[user] attempted to touch [src]!</span>")
|
||||
return TRUE
|
||||
@@ -294,7 +280,7 @@
|
||||
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return TRUE
|
||||
var/hulk_verb = pick("smash","pummel")
|
||||
if(user != src && check_shields(user, 15, "the [hulk_verb]ing"))
|
||||
if(user != src && (run_block(user, 15, "the [hulk_verb]ing", ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS))
|
||||
return TRUE
|
||||
..()
|
||||
return FALSE
|
||||
@@ -309,14 +295,14 @@
|
||||
M.Feedstop()
|
||||
return // can't attack while eating!
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_PACIFISM))
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return FALSE
|
||||
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 40)
|
||||
if(check_shields(M, damage, "the [M.name]"))
|
||||
if(run_block(M, damage, "the [M.name]", ATTACK_TYPE_MELEE, null, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS)
|
||||
return FALSE
|
||||
|
||||
if (stat != DEAD)
|
||||
@@ -335,7 +321,7 @@
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return FALSE
|
||||
if(check_shields(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", MELEE_ATTACK, M.armour_penetration))
|
||||
if(run_block(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", ATTACK_TYPE_MELEE, M.armour_penetration, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS)
|
||||
return FALSE
|
||||
if(M.attack_sound)
|
||||
playsound(loc, M.attack_sound, 50, 1, 1)
|
||||
@@ -345,17 +331,15 @@
|
||||
log_combat(M, src, "attacked")
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/attack_paw(mob/living/carbon/monkey/M)
|
||||
if (M.a_intent == INTENT_HARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return FALSE
|
||||
|
||||
if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
|
||||
to_chat(M, "<span class='warning'>You can't bite with your mouth covered!</span>")
|
||||
return FALSE
|
||||
if(check_shields(M, 0, "the [M.name]"))
|
||||
if(run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS)
|
||||
return FALSE
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
|
||||
if (prob(75))
|
||||
@@ -379,7 +363,7 @@
|
||||
if(HAS_TRAIT(L, TRAIT_PACIFISM))
|
||||
to_chat(L, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return FALSE
|
||||
if(L != src && check_shields(L, rand(1, 3), "the [L.name]"))
|
||||
if(L != src && (run_block(L, rand(1, 3), "the [L.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, L, check_zone(L.zone_selected)) & BLOCK_SUCCESS))
|
||||
return FALSE
|
||||
L.do_attack_animation(src)
|
||||
if(prob(90))
|
||||
@@ -393,7 +377,7 @@
|
||||
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/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]"))
|
||||
if((M != src) && M.a_intent != INTENT_HELP && (run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS))
|
||||
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
|
||||
return FALSE
|
||||
switch(M.a_intent)
|
||||
|
||||
@@ -354,7 +354,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
|
||||
if(cultslurring)
|
||||
message = cultslur(message)
|
||||
|
||||
|
||||
if(clockcultslurring)
|
||||
message = CLOCK_CULT_SLUR(message)
|
||||
|
||||
|
||||
@@ -695,7 +695,7 @@
|
||||
holo_icon = client.prefs.get_filtered_holoform(HOLOFORM_FILTER_AI)
|
||||
else
|
||||
holo_icon = getHologramIcon(icon('icons/mob/ai.dmi', "female"))
|
||||
else if("xeno queen")
|
||||
if("xeno queen")
|
||||
holo_icon = getHologramIcon(icon(icon_list[input],"alienq"))
|
||||
else
|
||||
holo_icon = getHologramIcon(icon(icon_list[input], input))
|
||||
|
||||
@@ -283,9 +283,7 @@
|
||||
T.visible_message("<span class='warning'>A port on [src] opens to reveal [cable], which promptly falls to the floor.</span>", "<span class='italics'>You hear the soft click of something light and hard falling to the ground.</span>")
|
||||
if("loudness")
|
||||
if(subscreen == 1) // Open Instrument
|
||||
internal_instrument.interact(src)
|
||||
if(subscreen == 2) // Change Instrument type
|
||||
internal_instrument.selectInstrument()
|
||||
internal_instrument.ui_interact(src)
|
||||
|
||||
//updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window
|
||||
paiInterface() // So we'll just call the update directly rather than doing some default checks
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
else
|
||||
add_overlay("ov-opencover -c")
|
||||
if(hat)
|
||||
var/mutable_appearance/head_overlay = hat.build_worn_icon(state = hat.icon_state, default_layer = 20, default_icon_file = 'icons/mob/head.dmi')
|
||||
var/mutable_appearance/head_overlay = hat.build_worn_icon(default_layer = 20, default_icon_file = 'icons/mob/clothing/head.dmi', override_state = hat.icon_state)
|
||||
head_overlay.pixel_y += hat_offset
|
||||
add_overlay(head_overlay)
|
||||
update_fire()
|
||||
|
||||
@@ -112,11 +112,15 @@
|
||||
|
||||
/mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone)
|
||||
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))
|
||||
var/list/returnlist = list()
|
||||
var/returned = run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist)
|
||||
if(returned & BLOCK_SHOULD_REDIRECT)
|
||||
handle_projectile_attack_redirection(P, returnlist[BLOCK_RETURN_REDIRECT_METHOD])
|
||||
if(returned & BLOCK_REDIRECTED)
|
||||
return BULLET_ACT_FORCE_PIERCE
|
||||
if(returned & BLOCK_SUCCESS)
|
||||
P.on_hit(src, 100, def_zone)
|
||||
return 2
|
||||
return BULLET_ACT_BLOCK
|
||||
if((P.damage_type == BRUTE || P.damage_type == BURN))
|
||||
adjustBruteLoss(P.damage)
|
||||
if(prob(P.damage*1.5))
|
||||
|
||||
@@ -445,7 +445,6 @@ Pass the desired type path itself, declaring a temporary var beforehand is not r
|
||||
return scan_result
|
||||
else
|
||||
return FALSE //The current element failed assessment, move on to the next.
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/proc/check_bot(targ)
|
||||
var/turf/T = get_turf(targ)
|
||||
|
||||
@@ -523,9 +523,6 @@
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
reagent_id = null
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/proc/check_overdose(mob/living/carbon/patient,reagent_id,injection_amount)
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[reagent_id]
|
||||
if(!R.overdose_threshold) //Some chems do not have an OD threshold
|
||||
|
||||
@@ -235,10 +235,11 @@ Auto Patrol: []"},
|
||||
playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2)
|
||||
C.visible_message("<span class='danger'>[src] is trying to put zipties on [C]!</span>",\
|
||||
"<span class='userdanger'>[src] is trying to put zipties on you!</span>")
|
||||
addtimer(CALLBACK(src, .proc/attempt_handcuff, C), 60)
|
||||
if(do_after(src, 60, FALSE, C))
|
||||
attempt_handcuff(C)
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/attempt_handcuff(mob/living/carbon/C)
|
||||
if( !on || !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
|
||||
if (!on)
|
||||
return
|
||||
if(!C.handcuffed)
|
||||
C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C)
|
||||
|
||||
@@ -392,6 +392,9 @@
|
||||
var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult)
|
||||
if(!C)
|
||||
return
|
||||
if(!C.cult_team)
|
||||
to_chat(the_construct, "<span class='cult italic'>You are alone, and have no team.</span>")
|
||||
return
|
||||
var/datum/objective/eldergod/summon_objective = locate() in C.cult_team.objectives
|
||||
|
||||
if(summon_objective.check_completion())
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
. = ..()
|
||||
if(can_be_held)
|
||||
//icon/item state is defined in mob_holder/drone_worn_icon()
|
||||
AddElement(/datum/element/mob_holder, null, 'icons/mob/head.dmi', 'icons/mob/inhands/clothing_righthand.dmi', 'icons/mob/inhands/clothing_lefthand.dmi', ITEM_SLOT_HEAD, /datum/element/mob_holder.proc/drone_worn_icon)
|
||||
AddElement(/datum/element/mob_holder, null, 'icons/mob/clothing/head.dmi', 'icons/mob/inhands/clothing_righthand.dmi', 'icons/mob/inhands/clothing_lefthand.dmi', ITEM_SLOT_HEAD, /datum/element/mob_holder.proc/drone_worn_icon)
|
||||
|
||||
/mob/living/simple_animal/drone/med_hud_set_health()
|
||||
var/image/holder = hud_list[DIAG_HUD]
|
||||
|
||||
@@ -92,8 +92,8 @@
|
||||
return
|
||||
if(hack)
|
||||
if(hacked)
|
||||
return
|
||||
Stun(40)
|
||||
return
|
||||
if(clockwork)
|
||||
to_chat(src, "<span class='large_brass'><b>ERROR: LAW OVERRIDE DETECTED</b></span>")
|
||||
to_chat(src, "<span class='heavy_brass'>From now on, these are your laws:</span>")
|
||||
|
||||
@@ -28,12 +28,7 @@
|
||||
var/y_shift = getItemPixelShiftY()
|
||||
|
||||
if(r_hand)
|
||||
|
||||
var/r_state = r_hand.item_state
|
||||
if(!r_state)
|
||||
r_state = r_hand.icon_state
|
||||
|
||||
var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(state = r_state, default_layer = DRONE_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
|
||||
var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(default_layer = DRONE_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
|
||||
if(y_shift)
|
||||
r_hand_overlay.pixel_y += y_shift
|
||||
|
||||
@@ -46,12 +41,7 @@
|
||||
client.screen |= r_hand
|
||||
|
||||
if(l_hand)
|
||||
|
||||
var/l_state = l_hand.item_state
|
||||
if(!l_state)
|
||||
l_state = l_hand.icon_state
|
||||
|
||||
var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(state = l_state, default_layer = DRONE_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
|
||||
var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(default_layer = DRONE_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
|
||||
if(y_shift)
|
||||
l_hand_overlay.pixel_y += y_shift
|
||||
|
||||
@@ -82,10 +72,10 @@
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
head.screen_loc = ui_drone_head
|
||||
client.screen += head
|
||||
var/used_head_icon = 'icons/mob/head.dmi'
|
||||
var/used_head_icon = 'icons/mob/clothing/head.dmi'
|
||||
if(istype(head, /obj/item/clothing/mask))
|
||||
used_head_icon = 'icons/mob/mask.dmi'
|
||||
var/mutable_appearance/head_overlay = head.build_worn_icon(state = head.icon_state, default_layer = DRONE_HEAD_LAYER, default_icon_file = used_head_icon)
|
||||
used_head_icon = 'icons/mob/clothing/mask.dmi'
|
||||
var/mutable_appearance/head_overlay = head.build_worn_icon(default_layer = DRONE_HEAD_LAYER, default_icon_file = used_head_icon, override_state = head.icon_state)
|
||||
head_overlay.pixel_y -= 15
|
||||
|
||||
drone_overlays[DRONE_HEAD_LAYER] = head_overlay
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
if (!(istype(src, /mob/living/simple_animal/pet/gondola/gondolapod)))
|
||||
CreateGondola()
|
||||
|
||||
/mob/living/simple_animal/pet/gondola/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/spellcasting, SPELL_SKIP_VOCAL) // so they can cast spells despite being silent.
|
||||
|
||||
/mob/living/simple_animal/pet/gondola/proc/CreateGondola()
|
||||
icon_state = null
|
||||
icon_living = null
|
||||
|
||||
@@ -112,6 +112,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
recolorentiresprite = TRUE
|
||||
if(!recolorentiresprite) //we want this to proc before stand logs in, so the overlay isnt gone for some reason
|
||||
cooloverlay = mutable_appearance(icon, theme)
|
||||
add_overlay(cooloverlay)
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/Login() //if we have a mind, set its name to ours when it logs in
|
||||
..()
|
||||
@@ -310,11 +313,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
var/obj/item/r_hand = get_item_for_held_index(2)
|
||||
|
||||
if(r_hand)
|
||||
var/r_state = r_hand.item_state
|
||||
if(!r_state)
|
||||
r_state = r_hand.icon_state
|
||||
|
||||
hands_overlays += r_hand.build_worn_icon(state = r_state, default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
|
||||
hands_overlays += r_hand.build_worn_icon(default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
|
||||
|
||||
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
|
||||
r_hand.layer = ABOVE_HUD_LAYER
|
||||
@@ -323,11 +322,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
client.screen |= r_hand
|
||||
|
||||
if(l_hand)
|
||||
var/l_state = l_hand.item_state
|
||||
if(!l_state)
|
||||
l_state = l_hand.icon_state
|
||||
|
||||
hands_overlays += l_hand.build_worn_icon(state = l_state, default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
|
||||
hands_overlays += l_hand.build_worn_icon(default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
|
||||
|
||||
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
|
||||
l_hand.layer = ABOVE_HUD_LAYER
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
var/blocked = FALSE
|
||||
if(hasmatchingsummoner(hit_atom)) //if the summoner matches don't hurt them
|
||||
blocked = TRUE
|
||||
if(L.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK))
|
||||
if(L.run_block(src, 90, "[name]", ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS)
|
||||
blocked = TRUE
|
||||
if(!blocked)
|
||||
L.drop_all_held_items()
|
||||
|
||||
@@ -400,10 +400,9 @@
|
||||
action.button_icon_state = "wrap_[active]"
|
||||
action.UpdateButtonIcon()
|
||||
|
||||
/obj/effect/proc_holder/wrap/Click()
|
||||
if(!istype(usr, /mob/living/simple_animal/hostile/poison/giant_spider/nurse))
|
||||
/obj/effect/proc_holder/wrap/Trigger(mob/living/simple_animal/hostile/poison/giant_spider/nurse/user)
|
||||
if(!istype(user))
|
||||
return TRUE
|
||||
var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/user = usr
|
||||
activate(user)
|
||||
return TRUE
|
||||
|
||||
@@ -444,7 +443,7 @@
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
button_icon_state = "lay_eggs"
|
||||
|
||||
/datum/action/innate/spider/lay_eggs/IsAvailable()
|
||||
/datum/action/innate/spider/lay_eggs/IsAvailable(silent = FALSE)
|
||||
if(..())
|
||||
if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse))
|
||||
return 0
|
||||
@@ -508,7 +507,7 @@
|
||||
desc = "Send a command to all living spiders."
|
||||
button_icon_state = "command"
|
||||
|
||||
/datum/action/innate/spider/comm/IsAvailable()
|
||||
/datum/action/innate/spider/comm/IsAvailable(silent = FALSE)
|
||||
if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -33,14 +33,12 @@
|
||||
var/obj/item/r_hand = get_item_for_held_index(2)
|
||||
|
||||
if(r_hand)
|
||||
var/r_state = r_hand.item_state ? r_hand.item_state : r_hand.icon_state
|
||||
var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(state = r_state, default_layer = GORILLA_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
|
||||
var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(default_layer = GORILLA_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
|
||||
r_hand_overlay.pixel_y -= 1
|
||||
hands_overlays += r_hand_overlay
|
||||
|
||||
if(l_hand)
|
||||
var/l_state = l_hand.item_state ? l_hand.item_state : l_hand.icon_state
|
||||
var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(state = l_state, default_layer = GORILLA_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
|
||||
var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(default_layer = GORILLA_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
|
||||
l_hand_overlay.pixel_y -= 1
|
||||
hands_overlays += l_hand_overlay
|
||||
|
||||
|
||||
@@ -762,7 +762,7 @@ Difficulty: Very Hard
|
||||
name = "Exit Possession"
|
||||
desc = "Exits the body you are possessing."
|
||||
charge_max = 60
|
||||
clothes_req = 0
|
||||
clothes_req = NONE
|
||||
invocation_type = "none"
|
||||
max_targets = 1
|
||||
range = -1
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
pull_force = MOVE_FORCE_OVERPOWERING
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
|
||||
flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1
|
||||
var/list/crusher_loot
|
||||
var/medal_type
|
||||
|
||||
@@ -40,27 +40,27 @@
|
||||
deathsound = 'sound/magic/demon_dies.ogg'
|
||||
deathmessage = "begins to shudder as it becomes transparent..."
|
||||
loot_drop = /obj/item/clothing/neck/cloak/herald_cloak
|
||||
|
||||
|
||||
can_talk = 1
|
||||
|
||||
attack_action_types = list(/datum/action/innate/elite_attack/herald_trishot,
|
||||
/datum/action/innate/elite_attack/herald_directionalshot,
|
||||
/datum/action/innate/elite_attack/herald_teleshot,
|
||||
/datum/action/innate/elite_attack/herald_mirror)
|
||||
|
||||
|
||||
var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/my_mirror = null
|
||||
var/is_mirror = FALSE
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/death()
|
||||
. = ..()
|
||||
if(!is_mirror)
|
||||
addtimer(CALLBACK(src, .proc/become_ghost), 8)
|
||||
if(my_mirror != null)
|
||||
qdel(my_mirror)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/become_ghost()
|
||||
icon_state = "herald_ghost"
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
|
||||
. = ..()
|
||||
if(.)
|
||||
@@ -71,25 +71,25 @@
|
||||
button_icon_state = "herald_trishot"
|
||||
chosen_message = "<span class='boldwarning'>You are now firing three shots in your chosen direction.</span>"
|
||||
chosen_attack_num = HERALD_TRISHOT
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/herald_directionalshot
|
||||
name = "Circular Shot"
|
||||
button_icon_state = "herald_directionalshot"
|
||||
chosen_message = "<span class='boldwarning'>You are firing projectiles in all directions.</span>"
|
||||
chosen_attack_num = HERALD_DIRECTIONALSHOT
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/herald_teleshot
|
||||
name = "Teleport Shot"
|
||||
button_icon_state = "herald_teleshot"
|
||||
chosen_message = "<span class='boldwarning'>You will now fire a shot which teleports you where it lands.</span>"
|
||||
chosen_attack_num = HERALD_TELESHOT
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/herald_mirror
|
||||
name = "Summon Mirror"
|
||||
button_icon_state = "herald_mirror"
|
||||
chosen_message = "<span class='boldwarning'>You will spawn a mirror which duplicates your attacks.</span>"
|
||||
chosen_attack_num = HERALD_MIRROR
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/OpenFire()
|
||||
if(client)
|
||||
switch(chosen_attack)
|
||||
@@ -124,7 +124,7 @@
|
||||
my_mirror.herald_teleshot(target)
|
||||
if(HERALD_MIRROR)
|
||||
herald_mirror()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/shoot_projectile(turf/marker, set_angle, var/is_teleshot)
|
||||
var/turf/startloc = get_turf(src)
|
||||
var/obj/item/projectile/herald/H = null
|
||||
@@ -137,7 +137,7 @@
|
||||
if(target)
|
||||
H.original = target
|
||||
H.fire(set_angle)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_trishot(target)
|
||||
ranged_cooldown = world.time + 30
|
||||
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
|
||||
@@ -151,17 +151,17 @@
|
||||
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 10)
|
||||
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 12)
|
||||
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 14)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_circleshot()
|
||||
var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315)
|
||||
for(var/i in directional_shot_angles)
|
||||
shoot_projectile(get_turf(src), i, FALSE)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/unenrage()
|
||||
if(stat == DEAD || is_mirror)
|
||||
return
|
||||
icon_state = "herald"
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_directionalshot()
|
||||
ranged_cooldown = world.time + 50
|
||||
if(!is_mirror)
|
||||
@@ -172,14 +172,14 @@
|
||||
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
|
||||
addtimer(CALLBACK(src, .proc/herald_circleshot), 15)
|
||||
addtimer(CALLBACK(src, .proc/unenrage), 20)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_teleshot(target)
|
||||
ranged_cooldown = world.time + 30
|
||||
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
|
||||
var/target_turf = get_turf(target)
|
||||
var/angle_to_target = Get_Angle(src, target_turf)
|
||||
shoot_projectile(target_turf, angle_to_target, TRUE)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_mirror()
|
||||
ranged_cooldown = world.time + 40
|
||||
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
|
||||
@@ -190,7 +190,7 @@
|
||||
my_mirror = new_mirror
|
||||
my_mirror.my_master = src
|
||||
my_mirror.faction = faction.Copy()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror
|
||||
name = "herald's mirror"
|
||||
desc = "This fiendish work of magic copies the herald's attacks. Seems logical to smash it."
|
||||
@@ -203,16 +203,16 @@
|
||||
del_on_death = TRUE
|
||||
is_mirror = TRUE
|
||||
var/mob/living/simple_animal/hostile/asteroid/elite/herald/my_master = null
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Initialize()
|
||||
..()
|
||||
toggle_ai(AI_OFF)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Destroy()
|
||||
if(my_master != null)
|
||||
my_master.my_mirror = null
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/item/projectile/herald
|
||||
name ="death bolt"
|
||||
icon_state= "chronobolt"
|
||||
@@ -222,7 +222,7 @@
|
||||
eyeblur = 0
|
||||
damage_type = BRUTE
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
|
||||
/obj/item/projectile/herald/teleshot
|
||||
name ="golden bolt"
|
||||
damage = 0
|
||||
@@ -239,11 +239,11 @@
|
||||
var/mob/living/F = firer
|
||||
if(F != null && istype(F, /mob/living/simple_animal/hostile/asteroid/elite) && F.faction_check_mob(L))
|
||||
L.heal_overall_damage(damage)
|
||||
|
||||
|
||||
/obj/item/projectile/herald/teleshot/on_hit(atom/target, blocked = FALSE)
|
||||
. = ..()
|
||||
firer.forceMove(get_turf(src))
|
||||
|
||||
|
||||
//Herald's loot: Cloak of the Prophet
|
||||
|
||||
/obj/item/clothing/neck/cloak/herald_cloak
|
||||
@@ -252,13 +252,13 @@
|
||||
icon = 'icons/obj/lavaland/elite_trophies.dmi'
|
||||
icon_state = "herald_cloak"
|
||||
body_parts_covered = CHEST|GROIN|ARMS
|
||||
hit_reaction_chance = 10
|
||||
|
||||
var/hit_reaction_chance = 10
|
||||
|
||||
/obj/item/clothing/neck/cloak/herald_cloak/proc/reactionshot(mob/living/carbon/owner)
|
||||
var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315)
|
||||
for(var/i in directional_shot_angles)
|
||||
shoot_projectile(get_turf(owner), i, owner)
|
||||
|
||||
|
||||
/obj/item/clothing/neck/cloak/herald_cloak/proc/shoot_projectile(turf/marker, set_angle, mob/living/carbon/owner)
|
||||
var/turf/startloc = get_turf(owner)
|
||||
var/obj/item/projectile/herald/H = null
|
||||
@@ -266,12 +266,11 @@
|
||||
H.preparePixelProjectile(marker, startloc)
|
||||
H.firer = owner
|
||||
H.fire(set_angle)
|
||||
|
||||
/obj/item/clothing/neck/cloak/herald_cloak/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
|
||||
/obj/item/clothing/neck/cloak/herald_cloak/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
. = ..()
|
||||
if(rand(1,100) > hit_reaction_chance)
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[owner]'s [src] emits a loud noise as [owner] is struck!</span>")
|
||||
var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315)
|
||||
playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
|
||||
addtimer(CALLBACK(src, .proc/reactionshot, owner), 10)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* - Charges at the target after a telegraph, throwing them across the arena should it connect.
|
||||
* - Legionnaire's head detaches, attacking as it's own entity. Has abilities of it's own later into the fight. Once dead, regenerates after a brief period. If the skill is used while the head is off, it will be killed.
|
||||
* - Leaves a pile of bones at your location. Upon using this skill again, you'll swap locations with the bone pile.
|
||||
* - Spews a cloud of smoke from it's maw, wherever said maw is.
|
||||
* - Spews a cloud of smoke from it's maw, wherever said maw is.
|
||||
* A unique fight incorporating the head mechanic of legion into a whole new beast. Combatants will need to make sure the tag-team of head and body don't lure them into a deadly trap.
|
||||
*/
|
||||
|
||||
@@ -45,35 +45,35 @@
|
||||
/datum/action/innate/elite_attack/head_detach,
|
||||
/datum/action/innate/elite_attack/bonfire_teleport,
|
||||
/datum/action/innate/elite_attack/spew_smoke)
|
||||
|
||||
|
||||
var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/myhead = null
|
||||
var/obj/structure/legionnaire_bonfire/mypile = null
|
||||
var/has_head = TRUE
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/legionnaire_charge
|
||||
name = "Legionnaire Charge"
|
||||
button_icon_state = "legionnaire_charge"
|
||||
chosen_message = "<span class='boldwarning'>You will attempt to grab your opponent and throw them.</span>"
|
||||
chosen_attack_num = LEGIONNAIRE_CHARGE
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/head_detach
|
||||
name = "Release Head"
|
||||
button_icon_state = "head_detach"
|
||||
chosen_message = "<span class='boldwarning'>You will now detach your head or kill it if it is already released.</span>"
|
||||
chosen_attack_num = HEAD_DETACH
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/bonfire_teleport
|
||||
name = "Bonfire Teleport"
|
||||
button_icon_state = "bonfire_teleport"
|
||||
chosen_message = "<span class='boldwarning'>You will leave a bonfire. Second use will let you swap positions with it indefintiely. Using this move on the same tile as your active bonfire removes it.</span>"
|
||||
chosen_attack_num = BONFIRE_TELEPORT
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/spew_smoke
|
||||
name = "Spew Smoke"
|
||||
button_icon_state = "spew_smoke"
|
||||
chosen_message = "<span class='boldwarning'>Your head will spew smoke in an area, wherever it may be.</span>"
|
||||
chosen_attack_num = SPEW_SMOKE
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/OpenFire()
|
||||
if(client)
|
||||
switch(chosen_attack)
|
||||
@@ -96,7 +96,7 @@
|
||||
bonfire_teleport()
|
||||
if(SPEW_SMOKE)
|
||||
spew_smoke()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge(target)
|
||||
ranged_cooldown = world.time + 50
|
||||
var/dir_to_target = get_dir(get_turf(src), get_turf(target))
|
||||
@@ -107,7 +107,7 @@
|
||||
playsound(src,'sound/magic/demon_attack1.ogg', 200, 1)
|
||||
visible_message("<span class='boldwarning'>[src] prepares to charge!</span>")
|
||||
addtimer(CALLBACK(src, .proc/legionnaire_charge_2, dir_to_target, 0), 5)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge_2(var/move_dir, var/times_ran)
|
||||
if(times_ran >= 4)
|
||||
return
|
||||
@@ -136,7 +136,7 @@
|
||||
L.Stun(20) //substituting this for the Paralyze from the line above, because we don't have tg paralysis stuff
|
||||
L.adjustBruteLoss(50)
|
||||
addtimer(CALLBACK(src, .proc/legionnaire_charge_2, move_dir, (times_ran + 1)), 2)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/head_detach(target)
|
||||
ranged_cooldown = world.time + 10
|
||||
if(myhead != null)
|
||||
@@ -160,11 +160,11 @@
|
||||
else if(health < maxHealth * 0.5)
|
||||
myhead.melee_damage_lower = 20
|
||||
myhead.melee_damage_upper = 20
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/onHeadDeath()
|
||||
myhead = null
|
||||
addtimer(CALLBACK(src, .proc/regain_head), 50)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/regain_head()
|
||||
has_head = TRUE
|
||||
if(stat == DEAD)
|
||||
@@ -196,7 +196,7 @@
|
||||
forceMove(pileturf)
|
||||
visible_message("<span class='boldwarning'>[src] forms from the bonfire!</span>")
|
||||
mypile.forceMove(legionturf)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/spew_smoke()
|
||||
ranged_cooldown = world.time + 60
|
||||
var/turf/T = null
|
||||
@@ -213,7 +213,7 @@
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(2, T)
|
||||
smoke.start()
|
||||
|
||||
|
||||
//The legionnaire's head. Basically the same as any legion head, but we have to tell our creator when we die so they can generate another head.
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead
|
||||
name = "legionnaire head"
|
||||
@@ -239,12 +239,12 @@
|
||||
faction = list()
|
||||
ranged = FALSE
|
||||
var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/body = null
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/death()
|
||||
. = ..()
|
||||
if(body)
|
||||
body.onHeadDeath()
|
||||
|
||||
|
||||
//The legionnaire's bonfire, which can be swapped positions with. Also sets flammable living beings on fire when they walk over it.
|
||||
/obj/structure/legionnaire_bonfire
|
||||
name = "bone pile"
|
||||
@@ -258,20 +258,20 @@
|
||||
light_range = 4
|
||||
light_color = LIGHT_COLOR_RED
|
||||
var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/myowner = null
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/structure/legionnaire_bonfire/Entered(atom/movable/mover, turf/target)
|
||||
if(isliving(mover))
|
||||
var/mob/living/L = mover
|
||||
L.adjust_fire_stacks(3)
|
||||
L.IgniteMob()
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/structure/legionnaire_bonfire/Destroy()
|
||||
if(myowner != null)
|
||||
myowner.mypile = null
|
||||
. = ..()
|
||||
|
||||
|
||||
//The visual effect which appears in front of legionnaire when he goes to charge.
|
||||
/obj/effect/temp_visual/dragon_swoop/legionnaire
|
||||
duration = 10
|
||||
@@ -280,7 +280,7 @@
|
||||
/obj/effect/temp_visual/dragon_swoop/legionnaire/Initialize()
|
||||
. = ..()
|
||||
transform *= 0.33
|
||||
|
||||
|
||||
// Legionnaire's loot: Legionnaire Spine
|
||||
|
||||
/obj/item/crusher_trophy/legionnaire_spine
|
||||
|
||||
@@ -285,9 +285,10 @@
|
||||
if("Miner")
|
||||
mob_species = pickweight(list(/datum/species/human = 70, /datum/species/lizard = 26, /datum/species/fly = 2, /datum/species/plasmaman = 2))
|
||||
if(mob_species == /datum/species/plasmaman)
|
||||
uniform = /obj/item/clothing/under/plasmaman
|
||||
head = /obj/item/clothing/head/helmet/space/plasmaman
|
||||
uniform = /obj/item/clothing/under/plasmaman/mining
|
||||
head = /obj/item/clothing/head/helmet/space/plasmaman/mining
|
||||
belt = /obj/item/tank/internals/plasmaman/belt
|
||||
mask = /obj/item/clothing/mask/gas/explorer
|
||||
else
|
||||
uniform = /obj/item/clothing/under/rank/cargo/miner/lavaland
|
||||
if (prob(4))
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
desc = "You will trigger a large amount of lights around you to flicker."
|
||||
|
||||
charge_max = 300
|
||||
clothes_req = 0
|
||||
clothes_req = NONE
|
||||
range = 14
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/flicker_lights/cast(list/targets,mob/user = usr)
|
||||
@@ -185,7 +185,7 @@
|
||||
|
||||
message = "<span class='notice'>You glare your eyes.</span>"
|
||||
charge_max = 600
|
||||
clothes_req = 0
|
||||
clothes_req = NONE
|
||||
range = 10
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/blindness/cast(list/targets,mob/user = usr)
|
||||
@@ -201,7 +201,7 @@
|
||||
desc = "Toggle your nightvision mode."
|
||||
|
||||
charge_max = 10
|
||||
clothes_req = 0
|
||||
clothes_req = NONE
|
||||
|
||||
message = "<span class='notice'>You toggle your night vision!</span>"
|
||||
range = -1
|
||||
|
||||
@@ -43,23 +43,23 @@
|
||||
/mob/living/simple_animal/hostile/wizard/Initialize()
|
||||
. = ..()
|
||||
fireball = new /obj/effect/proc_holder/spell/aimed/fireball
|
||||
fireball.clothes_req = 0
|
||||
fireball.human_req = 0
|
||||
fireball.player_lock = 0
|
||||
fireball.clothes_req = NONE
|
||||
fireball.mobs_whitelist = null
|
||||
fireball.player_lock = FALSE
|
||||
AddSpell(fireball)
|
||||
var/obj/item/implant/exile/I = new
|
||||
I.implant(src, null, TRUE)
|
||||
|
||||
mm = new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile
|
||||
mm.clothes_req = 0
|
||||
mm.human_req = 0
|
||||
mm.player_lock = 0
|
||||
mm.clothes_req = NONE
|
||||
mm.mobs_whitelist = null
|
||||
mm.player_lock = FALSE
|
||||
AddSpell(mm)
|
||||
|
||||
blink = new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink
|
||||
blink.clothes_req = 0
|
||||
blink.human_req = 0
|
||||
blink.player_lock = 0
|
||||
blink.clothes_req = NONE
|
||||
blink.mobs_whitelist = null
|
||||
blink.player_lock = FALSE
|
||||
blink.outer_tele_radius = 3
|
||||
AddSpell(blink)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
background_icon_state = "bg_alien"
|
||||
var/needs_growth = NO_GROWTH_NEEDED
|
||||
|
||||
/datum/action/innate/slime/IsAvailable()
|
||||
/datum/action/innate/slime/IsAvailable(silent = FALSE)
|
||||
if(..())
|
||||
var/mob/living/simple_animal/slime/S = owner
|
||||
if(needs_growth == GROWTH_NEEDED)
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
/mob/living/proc/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
|
||||
if(!iscarbon(src))
|
||||
return Paralyze(amount, updating, ignore_canknockdown)
|
||||
if(!ignore_canknockdown && !(status_flags & CANKNOCKDOWN))
|
||||
return FALSE
|
||||
if(istype(buckled, /obj/vehicle/ridden))
|
||||
buckled.unbuckle_mob(src)
|
||||
var/drop_items = amount > 80 //80 is cutoff for old item dropping behavior
|
||||
|
||||
Reference in New Issue
Block a user