Merge remote-tracking branch 'citadel/master' into combat_rework

This commit is contained in:
kevinz000
2020-05-27 18:11:15 -07:00
149 changed files with 3488 additions and 1036 deletions
@@ -24,12 +24,12 @@
if(!eye_blind)
blind_eyes(1)
update_mobility()
else
if(stat == UNCONSCIOUS)
stat = CONSCIOUS
if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT))
set_resting(FALSE, TRUE)
else if(stat == UNCONSCIOUS)
stat = CONSCIOUS
if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT))
set_resting(FALSE, TRUE)
if(eye_blind <= 1)
adjust_blindness(-1)
update_mobility()
update_mobility()
update_damage_hud()
update_health_hud()
+7 -10
View File
@@ -442,14 +442,14 @@
//dropItemToGround(I) CIT CHANGE - makes it so the item doesn't drop if the modifier rolls above 100
var/modifier = 0
var/modifier = 50
if(HAS_TRAIT(src, TRAIT_CLUMSY))
modifier -= 40 //Clumsy people are more likely to hit themselves -Honk!
//CIT CHANGES START HERE
else if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)
modifier += 50
else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
modifier -= 50
if(modifier < 100)
dropItemToGround(I)
@@ -827,16 +827,17 @@
return
if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !HAS_TRAIT(src, TRAIT_NOHARDCRIT)))
stat = UNCONSCIOUS
disable_intentional_combat_mode(FALSE, FALSE)
SEND_SIGNAL(src, COMSIG_DISABLE_COMBAT_MODE)
if(!eye_blind)
blind_eyes(1)
else
if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT))
stat = SOFT_CRIT
disable_intentional_combat_mode(FALSE, FALSE)
SEND_SIGNAL(src, COMSIG_DISABLE_COMBAT_MODE)
else
stat = CONSCIOUS
adjust_blindness(-1)
if(eye_blind <= 1)
adjust_blindness(-1)
update_mobility()
update_damage_hud()
update_health_hud()
@@ -1122,10 +1123,6 @@
if(mood.sanity < SANITY_UNSTABLE)
return TRUE
/mob/living/carbon/transfer_ckey(mob/new_mob, send_signal = TRUE)
disable_intentional_combat_mode(TRUE, FALSE)
return ..()
/mob/living/carbon/can_see_reagents()
. = ..()
if(.) //No need to run through all of this if it's already true.
@@ -1,6 +0,0 @@
/mob/living/carbon/enable_intentional_combat_mode()
. = ..()
if(.)
if(voremode)
toggle_vore_mode()
-6
View File
@@ -8,8 +8,6 @@
if(!gibbed)
emote("deathgasp")
disable_intentional_combat_mode(TRUE, FALSE)
. = ..()
for(var/T in get_traumas())
@@ -62,7 +60,3 @@
var/obj/item/bodypart/BP = X
BP.drop_limb()
BP.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
/mob/living/carbon/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE)
disable_intentional_combat_mode(TRUE, FALSE)
return ..()
+1 -1
View File
@@ -90,7 +90,7 @@
if(digitalcamo)
. += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly unsimian manner."
if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
. += "[t_He] [t_is] visibly tense[CHECK_MOBILITY(src, MOBILITY_STAND) ? "." : ", and [t_is] standing in combative stance."]"
var/trait_exam = common_trait_examine()
@@ -39,6 +39,7 @@
. = ..()
if(!CONFIG_GET(flag/disable_human_mood))
AddComponent(/datum/component/mood)
AddComponent(/datum/component/combat_mode)
AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text")
AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!")
AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE)
@@ -16,8 +16,6 @@
if(!SSI)
SSI = CONFIG_GET_ENTRY(number/movedelay/sprint_speed_increase)
. -= SSI.config_entry_value
if(wrongdirmovedelay)
. += 1
if (m_intent == MOVE_INTENT_WALK && HAS_TRAIT(src, TRAIT_SPEEDY_STEP))
. -= 1.5
@@ -1473,11 +1473,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
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))
if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 1.5
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
damage *= 0.5
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 0.25
//END OF CITADEL CHANGES
@@ -1625,11 +1625,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
log_combat(user, target, "disarmed out of grab from")
return
var/randn = rand(1, 100)
if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) // CITADEL CHANGE
if(SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) // CITADEL CHANGE
randn += -10 //CITADEL CHANGE - being out of combat mode makes it easier for you to get disarmed
if(!CHECK_MOBILITY(user, MOBILITY_STAND)) //CITADEL CHANGE
randn += 100 //CITADEL CHANGE - No kosher disarming if you're resting
if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //CITADEL CHANGE
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) //CITADEL CHANGE
randn += 25 //CITADEL CHANGE - Makes it harder to disarm outside of combat mode
if(user.pulling == target)
randn -= 20 //If you have the time to get someone in a grab, you should have a greater chance at snatching the thing in their hand. Will be made completely obsolete by the grab rework but i've got a poor track record for releasing big projects on time so w/e i guess
@@ -1830,7 +1830,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(IS_STAMCRIT(user))
to_chat(user, "<span class='warning'>You're too exhausted for that.</span>")
return
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
to_chat(user, "<span class='warning'>You need combat mode to be active to that!</span>")
return
if(user.IsKnockdown() || user.IsParalyzed() || user.IsStun())
@@ -6,8 +6,8 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
name = "Dwarf"
id = "dwarf" //Also called Homo sapiens pumilionis
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,NO_UNDERWEAR,TRAIT_DWARF)
inherent_traits = list()
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
inherent_traits = list(TRAIT_DWARF,TRAIT_SNOB)
limbs_id = "human"
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
say_mod = "bellows" //high energy, EXTRA BIOLOGICAL FUEL
@@ -87,9 +87,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
var/heal_rate = 0.5 //The rate they heal damages over 400 alcohol stored. Default is 0.5 so we times 3 since 3 seconds.
var/alcohol_rate = 0.25 //The rate the alcohol ticks down per each iteration of dwarf_eth_ticker completing.
//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()
@@ -100,64 +98,10 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
/obj/item/organ/dwarfgland/on_life() //Primary loop to hook into to start delayed loops for other loops..
. = ..()
if(owner && owner.stat != DEAD)
dwarf_cycle_ticker()
//Handles the delayed tick cycle by just adding on increments per each on_life() tick
/obj/item/organ/dwarfgland/proc/dwarf_cycle_ticker()
dwarf_eth_ticker++
dwarf_filth_ticker++
if(dwarf_filth_ticker >= 4) //Should be around 4-8 seconds since a tick is around 2 seconds.
dwarf_filth_cycle() //On_life will adjust regarding other factors, so we are along for the ride.
dwarf_filth_ticker = 0 //We set the ticker back to 0 to go again.
if(dwarf_eth_ticker >= 1) //Alcohol reagent check should be around 2 seconds, since a tick is around 2 seconds.
dwarf_eth_cycle()
dwarf_eth_ticker = 0
//If this still friggin uses too much CPU, I'll make a for view subsystem If I have to.
/obj/item/organ/dwarfgland/proc/dwarf_filth_cycle()
if(!owner?.client || !owner?.mind)
return
//Filth Reactions - Since miasma now exists
var/filth_counter = 0 //Holder for the filth check cycle, basically contains how much filth dwarf sees numerically.
for(var/fuck in owner.fov_view(7)) //hello byond for view loop.
if(istype(fuck, /mob/living/carbon/human))
var/mob/living/carbon/human/H = fuck
if(H.stat == DEAD || (HAS_TRAIT(H, TRAIT_FAKEDEATH)))
filth_counter += 10
if(istype(fuck, /obj/effect/decal/cleanable/blood))
if(istype(fuck, /obj/effect/decal/cleanable/blood/gibs))
filth_counter += 1
else
filth_counter += 0.1
if(istype(fuck,/obj/effect/decal/cleanable/vomit)) //They are disgusted by their own vomit too.
filth_counter += 10 //Dwarves could technically chainstun each other in a vomit tantrum spiral.
switch(filth_counter)
if(11 to 25)
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(6)) //And then the probability they vomit along with it.
to_chat(owner, "<span class = 'danger'>The stench makes you queasy.</span>")
owner.vomit(10) //I think vomit should stay over a disgust adjustment.
if(51 to 75)
if(prob(9))
to_chat(owner, "<span class = 'danger'>By Armok! You won't be able to keep alcohol down at all!</span>")
owner.vomit(20) //Its more funny
if(76 to 100)
if(prob(11))
to_chat(owner, "<span class = 'userdanger'>You can't live in such FILTH!</span>")
owner.adjustToxLoss(10) //Now they start dying.
owner.vomit(20)
if(101 to INFINITY) //Now they will really start dying
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(30)
CHECK_TICK //Check_tick right here, its motherfuckin magic. (To me at least)
dwarf_eth_ticker++
if(dwarf_eth_ticker >= 1) //Alcohol reagent check should be around 2 seconds, since a tick is around 2 seconds.
dwarf_eth_cycle()
dwarf_eth_ticker = 0
//Handles the dwarf alcohol cycle tied to on_life, it ticks in dwarf_cycle_ticker.
/obj/item/organ/dwarfgland/proc/dwarf_eth_cycle()
+1 -1
View File
@@ -523,7 +523,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
//this updates all special effects: stun, sleeping, knockdown, druggy, stuttering, etc..
/mob/living/carbon/handle_status_effects()
..()
if(getStaminaLoss() && !(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //CIT CHANGE - prevents stamina regen while combat mode is active
if(getStaminaLoss() && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //CIT CHANGE - prevents stamina regen while combat mode is active
adjustStaminaLoss(!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? -7.5 : -6) : -3)//CIT CHANGE - decreases adjuststaminaloss to stop stamina damage from being such a joke
if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && incomingstammult != 1)
+1 -1
View File
@@ -322,7 +322,7 @@
set_pull_offsets(M, state)
/mob/living/proc/set_pull_offsets(mob/living/M, grab_state = GRAB_PASSIVE)
if(M.buckled || M.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)
if(M.buckled || SEND_SIGNAL(M, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
return //don't make them change direction or offset them if they're buckled into something or in combat mode.
var/offset = 0
switch(grab_state)
+1 -1
View File
@@ -122,7 +122,7 @@
//// CITADEL STATION COMBAT ////
/// See __DEFINES/combat.dm
var/combat_flags = COMBAT_FLAGS_STAMSYSTEM_EXEMPT
var/combat_flags = COMBAT_FLAGS_SPRINT_EXEMPT
/// Next world.time when we will show a visible message on entering combat mode voluntarily again.
var/combatmessagecooldown = 0
@@ -15,8 +15,6 @@
speech_span = SPAN_ROBOT
flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1
vore_flags = NO_VORE
/// Enable sprint system but not stamina
combat_flags = COMBAT_FLAGS_STAMEXEMPT_YESSPRINT
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
var/last_lawchange_announce = 0
@@ -27,7 +27,7 @@
glide_size = 2
footstep_type = FOOTSTEP_MOB_CLAW
/mob/living/simple_animal/pet/fox/ComponentInitialize()
/mob/living/simple_animal/pet/sloth/ComponentInitialize()
. = ..()
AddElement(/datum/element/mob_holder, "sloth") //finally oranges can be held
@@ -23,29 +23,21 @@
for(var/ab in boss_abilities)
boss_abilities -= ab
var/datum/action/boss/AB = new ab()
AB.boss = src
AB.Grant(src)
boss_abilities += AB
atb.assign_abilities(boss_abilities)
/mob/living/simple_animal/hostile/boss/Destroy()
qdel(atb)
atb = null
for(var/ab in boss_abilities)
var/datum/action/boss/AB = ab
AB.boss = null
AB.Remove(src)
qdel(AB)
boss_abilities.Cut()
QDEL_NULL(atb)
QDEL_LIST(boss_abilities)
return ..()
//Action datum for bosses
//Override Trigger() as shown below to do things
/datum/action/boss
check_flags = AB_CHECK_CONSCIOUS //Incase the boss is given a player
required_mobility_flags = NONE
var/boss_cost = 100 //Cost of usage for the boss' AI 1-100
var/usage_probability = 100
var/mob/living/simple_animal/hostile/boss/boss
@@ -53,23 +45,34 @@
var/needs_target = TRUE //Does the boss need to have a target? (Only matters for the AI)
var/say_when_triggered = "" //What does the boss Say() when the ability triggers?
/datum/action/boss/Destroy()
boss = null
return ..()
/datum/action/boss/Grant(mob/M)
. = ..()
boss = owner
/datum/action/boss/Remove(mob/M)
. = ..()
boss = null
/datum/action/boss/Trigger()
. = ..()
if(.)
if(!istype(boss, boss_type))
return 0
if(!boss.atb)
return 0
if(boss.atb.points < boss_cost)
return 0
if(!boss.client)
if(needs_target && !boss.target)
return 0
if(boss)
if(say_when_triggered)
boss.say(say_when_triggered, forced = "boss action")
if(!boss.atb.spend(boss_cost))
return 0
if(!.)
return
if(!istype(boss, boss_type))
return FALSE
if(!boss.atb)
return FALSE
if(boss.atb.points < boss_cost)
return FALSE
if(!boss.client && needs_target && !boss.target)
return FALSE
if(!boss.atb.spend(boss_cost))
return FALSE
if(say_when_triggered)
boss.say(say_when_triggered, forced = "boss action")
//Example:
/*
@@ -83,7 +86,8 @@
/datum/boss_active_timed_battle
var/list/abilities //a list of /datum/action/boss owned by a boss mob
var/point_regen_delay = 5
var/points = 50 //1-100, start with 50 so we can use some abilities but not insta-buttfug somebody
var/max_points = 100
var/points = 50 //start with 50 so we can use some abilities but not insta-buttfug somebody
var/next_point_time = 0
var/chance_to_hold_onto_points = 50
var/highest_cost = 0
@@ -108,22 +112,22 @@
/datum/boss_active_timed_battle/proc/spend(cost)
if(cost <= points)
points = max(0,points-cost)
return 1
return 0
return TRUE
return FALSE
/datum/boss_active_timed_battle/proc/refund(cost)
points = min(points+cost, 100)
points = min(points+cost, max_points)
/datum/boss_active_timed_battle/process()
if(world.time >= next_point_time)
if(world.time >= next_point_time && points < max_points)
next_point_time = world.time + point_regen_delay
points = min(100, ++points) //has to be out of 100
points = min(max_points, ++points) //has to be out of 100
if(abilities)
chance_to_hold_onto_points = highest_cost*0.5
if(points != 100 && prob(chance_to_hold_onto_points))
if(points != max_points && prob(chance_to_hold_onto_points))
return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!)
if(!boss.client)
abilities = shuffle(abilities)
@@ -135,5 +139,5 @@
/datum/boss_active_timed_battle/Destroy()
abilities = null
SSobj.processing.Remove(src)
STOP_PROCESSING(SSobj, src)
return ..()
@@ -32,25 +32,47 @@
name = "Summon Minions"
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
button_icon_state = "art_summon"
usage_probability = 40
usage_probability = 20
boss_cost = 30
boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard
needs_target = FALSE
say_when_triggered = "Rise, my creations! Jump off your pages and into this realm!"
var/static/summoned_minions = 0
var/list/summoned_minions = list()
var/maximum_stickmen = 6
var/stickmen_to_summon = 3
/datum/action/boss/wizard_summon_minions/Trigger()
if(summoned_minions <= 6 && ..())
var/list/minions = list(
/mob/living/simple_animal/hostile/stickman,
/mob/living/simple_animal/hostile/stickman/ranged,
/mob/living/simple_animal/hostile/stickman/dog)
var/list/directions = GLOB.cardinals.Copy()
for(var/i in 1 to 3)
var/minions_chosen = pick_n_take(minions)
new minions_chosen (get_step(boss,pick_n_take(directions)), 1)
summoned_minions += 3;
. =..()
if(!.)
return
var/to_summon = stickmen_to_summon
var/current_len = length(summoned_minions)
if(current_len > maximum_stickmen - stickmen_to_summon)
for(var/a in (maximum_stickmen - stickmen_to_summon) to current_len)
var/mob/living/simple_animal/hostile/stickman/S = popleft(summoned_minions)
if(!S.client)
qdel(S)
else
S.forceMove(boss.drop_location())
S.revive(TRUE)
summoned_minions += S
to_summon--
var/static/list/minions = list(
/mob/living/simple_animal/hostile/stickman,
/mob/living/simple_animal/hostile/stickman/ranged,
/mob/living/simple_animal/hostile/stickman/dog)
var/list/directions = GLOB.cardinals.Copy()
for(var/i in 1 to to_summon)
var/minions_chosen = pick(minions)
var/mob/living/simple_animal/hostile/stickman/S = new minions_chosen (get_step(boss,pick_n_take(directions)), 1)
S.faction = boss.faction
RegisterSignal(S, COMSIG_PARENT_QDELETING, .proc/remove_from_list)
summoned_minions += S
/datum/action/boss/wizard_summon_minions/proc/remove_from_list(datum/source, forced)
summoned_minions -= source
//Mimic Ability
//Summons mimics of himself with magical papercraft
@@ -66,28 +88,32 @@
say_when_triggered = ""
/datum/action/boss/wizard_mimic/Trigger()
if(..())
var/mob/living/target
if(!boss.client) //AI's target
target = boss.target
else //random mob
var/list/threats = boss.PossibleThreats()
if(threats.len)
target = pick(threats)
if(target)
var/mob/living/simple_animal/hostile/boss/paper_wizard/wiz = boss
var/directions = GLOB.cardinals.Copy()
for(var/i in 1 to 3)
var/mob/living/simple_animal/hostile/boss/paper_wizard/copy/C = new (get_step(target,pick_n_take(directions)))
wiz.copies += C
C.original = wiz
C.say("My craft defines me, you could even say it IS me!")
wiz.say("My craft defines me, you could even say it IS me!")
wiz.forceMove(get_step(target,pick_n_take(directions)))
wiz.minimum_distance = 1 //so he doesn't run away and ruin everything
wiz.retreat_distance = 0
. = ..()
if(!.)
return
var/mob/living/target
if(!boss.client) //AI's target
target = boss.target
else //random mob
var/list/threats = boss.PossibleThreats()
if(threats.len)
target = pick(threats)
else
boss.atb.refund(boss_cost)
to_chat(owner, "<span class='warning'>There is no potential foe of different faction around to attack</span>")
if(target)
var/mob/living/simple_animal/hostile/boss/paper_wizard/wiz = boss
var/directions = GLOB.cardinals.Copy()
for(var/i in 1 to 3)
var/mob/living/simple_animal/hostile/boss/paper_wizard/copy/C = new (get_step(target,pick_n_take(directions)))
wiz.copies += C
C.original = wiz
C.say("My craft defines me, you could even say it IS me!")
wiz.say("My craft defines me, you could even say it IS me!")
wiz.forceMove(get_step(target,pick_n_take(directions)))
wiz.minimum_distance = 1 //so he doesn't run away and ruin everything
wiz.retreat_distance = 0
else
boss.atb.refund(boss_cost)
/mob/living/simple_animal/hostile/boss/paper_wizard/copy
desc = "'Tis a ruse!"
@@ -20,6 +20,7 @@
var/casingtype //set ONLY it and NULLIFY projectiletype, if we have projectile IN CASING
var/move_to_delay = 3 //delay for the automated movement.
var/list/friends = list()
var/list/foes = list()
var/list/emote_taunt = list()
var/taunt_chance = 0
@@ -62,6 +63,8 @@
/mob/living/simple_animal/hostile/Destroy()
targets_from = null
friends = null
foes = null
return ..()
/mob/living/simple_animal/hostile/Life()
@@ -193,7 +196,7 @@
// Please do not add one-off mob AIs here, but override this function for your mob
/mob/living/simple_animal/hostile/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids
if(!the_target || the_target.type == /atom/movable/lighting_object || isturf(the_target)) // bail out on invalids
return FALSE
if(ismob(the_target)) //Target is in godmode, ignore it.
@@ -208,13 +211,13 @@
if(search_objects < 2)
if(isliving(the_target))
var/mob/living/L = the_target
var/faction_check = faction_check_mob(L)
var/faction_check = !foes[L] && faction_check_mob(L)
if(robust_searching)
if(faction_check && !attack_same)
return FALSE
if(L.stat > stat_attack)
if(L.stat > stat_attack || (L.stat == UNCONSCIOUS && stat_attack == UNCONSCIOUS && HAS_TRAIT(L, TRAIT_DEATHCOMA)))
return FALSE
if(L in friends)
if(friends[L] > 0 && foes[L] < 1)
return FALSE
else
if((faction_check && !attack_same) || L.stat)
@@ -298,5 +298,5 @@
var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(user.loc)
A.flags_1 |= (flags_1 & ADMIN_SPAWNED_1)
A.GiveTarget(target)
A.friends = user
A.friends[user]++
A.faction = user.faction.Copy()
@@ -13,7 +13,7 @@
speed = 0
blood_volume = 0
stat_attack = UNCONSCIOUS
robust_searching = 1
robust_searching = TRUE //This is also required for the paper robe rallying to work.
environment_smash = ENVIRONMENT_SMASH_NONE
maxHealth = 100
health = 100
@@ -30,8 +30,6 @@
faction = list("hostile","stickman")
check_friendly_fire = 1
status_flags = CANPUSH
var/datum/action/boss/wizard_summon_minions/changesummons = /datum/action/boss/wizard_summon_minions
var/summoned_by_wizard = 0
/mob/living/simple_animal/hostile/stickman/ranged
ranged = 1
@@ -43,7 +41,6 @@
projectilesound = 'sound/misc/bang.ogg'
loot = list(/obj/item/gun/ballistic/automatic/pistol/stickman)
/mob/living/simple_animal/hostile/stickman/dog
name = "Angry Stick Dog"
desc = "Stickman's best friend, if he could see him at least."
@@ -52,12 +49,6 @@
icon_dead = "stickdog_dead"
mob_biotypes = MOB_BEAST
/mob/living/simple_animal/hostile/stickman/Initialize(mapload, var/wizard_summoned)
/mob/living/simple_animal/hostile/stickman/Initialize(mapload)
. = ..()
new /obj/effect/temp_visual/paper_scatter(src)
summoned_by_wizard = wizard_summoned
/mob/living/simple_animal/hostile/stickman/death()
..()
if(summoned_by_wizard == 1)
changesummons.summoned_minions --
+3 -2
View File
@@ -571,12 +571,13 @@
/mob/living/proc/cure_blind(source)
REMOVE_TRAIT(src, TRAIT_BLIND, source)
if(!HAS_TRAIT(src, TRAIT_BLIND))
update_blindness()
if(eye_blind <= 1) //little hack now that we don't actively check for trait and unconsciousness on update_blindness.
adjust_blindness(-1)
/mob/living/proc/become_blind(source)
if(!HAS_TRAIT(src, TRAIT_BLIND)) // not blind already, add trait then overlay
ADD_TRAIT(src, TRAIT_BLIND, source)
update_blindness()
blind_eyes(1)
else
ADD_TRAIT(src, TRAIT_BLIND, source)
+4 -8
View File
@@ -128,15 +128,13 @@
* * target (optional) is the other mob involved with the visible message. For example, the attacker in many combat messages.
* * target_message (optional) is what the target mob will see e.g. "[src] does something to you!"
*/
/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, mob/target, target_message)
/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, ignored_mobs, mob/target, target_message)
var/turf/T = get_turf(src)
if(!T)
return
var/list/hearers = get_hearers_in_view(vision_distance, src) //caches the hearers and then removes ignored mobs.
if(!length(hearers))
return
if(!islist(ignored_mobs))
ignored_mobs = list(ignored_mobs)
hearers -= ignored_mobs
if(target_message && target && istype(target) && target.client)
@@ -150,7 +148,7 @@
msg = blind_message
if(msg)
target.show_message(msg, MSG_VISUAL,blind_message, MSG_AUDIBLE)
else if(self_message)
if(self_message)
hearers -= src
for(var/mob/M in hearers)
if(!M.client)
@@ -185,15 +183,13 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
* * hearing_distance (optional) is the range, how many tiles away the message can be heard.
* * ignored_mobs (optional) doesn't show any message to any given mob in the list.
*/
/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/ignored_mobs)
/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, ignored_mobs)
var/turf/T = get_turf(src)
if(!T)
return
var/list/hearers = get_hearers_in_view(hearing_distance, src)
if(!length(hearers))
return
if(!islist(ignored_mobs))
ignored_mobs = list(ignored_mobs)
hearers -= ignored_mobs
if(self_message)
hearers -= src
@@ -377,7 +373,7 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
return FALSE
new /obj/effect/temp_visual/point(A,invisibility)
SEND_SIGNAL(src, COMSIG_MOB_POINTED, A)
return TRUE
/mob/proc/can_resist()
+7
View File
@@ -127,6 +127,13 @@
var/registered_z
var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly
var/list/screens = list()
var/list/client_colours = list()
var/hud_type = /datum/hud
var/datum/hSB/sandbox = null
var/mob/audiovisual_redirect //Mob to redirect messages, speech, and sounds to
var/siliconaccessareas = list()
+2 -2
View File
@@ -101,10 +101,10 @@
mob.throwing.finalize(FALSE)
var/atom/movable/AM = L.pulling
if(AM && AM.density && !(L.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && !ismob(AM))
if(AM && AM.density && !SEND_SIGNAL(L, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE) && !ismob(AM))
L.setDir(turn(L.dir, 180))
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc)
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc, add_delay)
/// Process_Grab(): checks for grab, attempts to break if so. Return TRUE to prevent movement.
/client/proc/Process_Grab()
+8 -8
View File
@@ -23,9 +23,9 @@
* Sets a mob's blindness to an amount if it was not above it already, similar to how status effects work
*/
/mob/proc/blind_eyes(amount)
var/old_blind = eye_blind || HAS_TRAIT(src, TRAIT_BLIND)
eye_blind = max(eye_blind, amount)
var/new_blind = eye_blind || HAS_TRAIT(src, TRAIT_BLIND)
var/old_blind = eye_blind
eye_blind = max((!eye_blind && stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : eye_blind , amount)
var/new_blind = eye_blind
if(old_blind != new_blind)
update_blindness()
@@ -36,21 +36,21 @@
*/
/mob/proc/adjust_blindness(amount)
var/old_eye_blind = eye_blind
eye_blind = max(0, eye_blind + amount)
if(!old_eye_blind || !eye_blind && !HAS_TRAIT(src, TRAIT_BLIND))
eye_blind = max((stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : 0, eye_blind + amount)
if(!old_eye_blind || !eye_blind)
update_blindness()
/**
* Force set the blindness of a mob to some level
*/
/mob/proc/set_blindness(amount)
var/old_eye_blind = eye_blind
eye_blind = max(amount, 0)
if(!old_eye_blind || !eye_blind && !HAS_TRAIT(src, TRAIT_BLIND))
eye_blind = max(amount, (stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : 0)
if(!old_eye_blind || !eye_blind)
update_blindness()
/// proc that adds and removes blindness overlays when necessary
/mob/proc/update_blindness()
if(stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND) || eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness
if(eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness
if(stat == CONSCIOUS || stat == SOFT_CRIT)
throw_alert("blind", /obj/screen/alert/blind)
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)