Merge pull request #14603 from Putnam3145/fix-base-option

Activity tracking; traitor class tweaks
This commit is contained in:
silicons
2021-04-18 18:49:27 -06:00
committed by GitHub
26 changed files with 159 additions and 73 deletions
+5 -1
View File
@@ -266,6 +266,7 @@
#define COMSIG_MOB_GET_VISIBLE_MESSAGE "mob_get_visible_message" //from base of atom/visible_message(): (atom/A, msg, range, ignored_mobs) #define COMSIG_MOB_GET_VISIBLE_MESSAGE "mob_get_visible_message" //from base of atom/visible_message(): (atom/A, msg, range, ignored_mobs)
#define COMPONENT_NO_VISIBLE_MESSAGE 1 //exactly what's said on the tin. #define COMPONENT_NO_VISIBLE_MESSAGE 1 //exactly what's said on the tin.
#define COMSIG_MOB_ANTAG_ON_GAIN "mob_antag_on_gain" //from base of /datum/antagonist/on_gain(): (antag_datum) #define COMSIG_MOB_ANTAG_ON_GAIN "mob_antag_on_gain" //from base of /datum/antagonist/on_gain(): (antag_datum)
#define COMSIG_MOB_APPLY_DAMAGE "mob_apply_damage" //from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone, wound_bonus, bare_wound_bonus, sharpness)
#define COMSIG_MOB_SPELL_CAN_CAST "mob_spell_can_cast" //from base of /obj/effect/proc_holder/spell/can_cast(): (spell) #define COMSIG_MOB_SPELL_CAN_CAST "mob_spell_can_cast" //from base of /obj/effect/proc_holder/spell/can_cast(): (spell)
#define COMSIG_MOB_SWAP_HANDS "mob_swap_hands" //from base of mob/swap_hand(): (obj/item) #define COMSIG_MOB_SWAP_HANDS "mob_swap_hands" //from base of mob/swap_hand(): (obj/item)
@@ -303,6 +304,10 @@
#define COMSIG_LIVING_ACTIVE_PARRY_START "active_parry_start" //from base of mob/living/initiate_parry_sequence(): (parrying_method, datum/parrying_item_mob_or_art, list/backup_items, list/override) #define COMSIG_LIVING_ACTIVE_PARRY_START "active_parry_start" //from base of mob/living/initiate_parry_sequence(): (parrying_method, datum/parrying_item_mob_or_art, list/backup_items, list/override)
#define COMPONENT_PREVENT_PARRY_START 1 #define COMPONENT_PREVENT_PARRY_START 1
#define COMSIG_LIVING_ATTACKER_SET "living_attacker_set" // from base of /mob/living/set_last_attacker(): (attacker)
#define COMSIG_LIVING_SET_AS_ATTACKER "living_set_as_attacker" // from base of /mob/living/set_last_attacker(): (target)
//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS! //ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS!
#define COMSIG_LIVING_STATUS_STUN "living_stun" //from base of mob/living/Stun() (amount, update, ignore) #define COMSIG_LIVING_STATUS_STUN "living_stun" //from base of mob/living/Stun() (amount, update, ignore)
#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" //from base of mob/living/Knockdown() (amount, update, ignore) #define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" //from base of mob/living/Knockdown() (amount, update, ignore)
@@ -357,7 +362,6 @@
// /obj/item signals // /obj/item signals
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user) #define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
#define COMSIG_MOB_APPLY_DAMGE "mob_apply_damage" //from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone)
#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob) #define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob)
#define COMPONENT_NO_INTERACT 1 #define COMPONENT_NO_INTERACT 1
#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob) #define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob)
+1 -2
View File
@@ -94,8 +94,7 @@
else if(hitsound) else if(hitsound)
playsound(loc, hitsound, get_clamped_volume(), 1, -1) playsound(loc, hitsound, get_clamped_volume(), 1, -1)
M.lastattacker = user.real_name M.set_last_attacker(user)
M.lastattackerckey = user.ckey
if(force && M == user && user.client) if(force && M == user && user.client)
user.client.give_award(/datum/award/achievement/misc/selfouch, user) user.client.give_award(/datum/award/achievement/misc/selfouch, user)
+63
View File
@@ -0,0 +1,63 @@
/datum/component/activity
var/activity_level = 0
var/not_moved_counter = 0
var/list/historical_activity_levels = list()
/datum/component/activity/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
var/mob/living/L = parent
RegisterSignal(L, COMSIG_LIVING_SET_AS_ATTACKER, .proc/on_set_as_attacker)
RegisterSignal(L, COMSIG_LIVING_ATTACKER_SET, .proc/on_attacker_set)
RegisterSignal(L, COMSIG_MOB_DEATH, .proc/on_death)
RegisterSignal(L, COMSIG_EXIT_AREA, .proc/on_exit_area)
RegisterSignal(L, COMSIG_LIVING_LIFE, .proc/on_life)
RegisterSignal(L, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE, COMSIG_MOB_APPLY_DAMAGE), .proc/minor_activity)
/datum/component/activity/proc/log_activity()
historical_activity_levels[world.time] = activity_level
/datum/component/activity/proc/minor_activity(datum/source)
activity_level += 1
/datum/component/activity/proc/on_attacker_set(datum/source, mob/attacker)
activity_level += 10
if(attacker?.mind)
activity_level += 10
log_activity()
/datum/component/activity/proc/on_set_as_attacker(datum/source, mob/target)
activity_level += 10
if(target?.mind)
activity_level += 20
log_activity()
/datum/component/activity/proc/on_death(datum/source)
activity_level += 100 // dying means you're doing SOMETHING
log_activity()
/datum/component/activity/proc/on_exit_area(datum/source)
activity_level += 1
not_moved_counter = 0
/datum/component/activity/proc/on_life(datum/source, seconds, times_fired)
var/mob/living/L = source
if(L.stat >= UNCONSCIOUS) // can't expect the unconscious to move
return
not_moved_counter += seconds
var/should_log = FALSE
switch(not_moved_counter)
if(60 to 120)
activity_level -= 1
if(120 to 600)
activity_level -= 5
if(600 to 1200)
activity_level -= 10
should_log = TRUE
if(1200 to INFINITY)
activity_level -= 20
should_log = TRUE
activity_level = max(activity_level, 0)
if(should_log)
log_activity()
+2 -2
View File
@@ -56,10 +56,10 @@
detonate() detonate()
/datum/component/explodable/proc/on_equip(datum/source, mob/equipper, slot) /datum/component/explodable/proc/on_equip(datum/source, mob/equipper, slot)
RegisterSignal(equipper, COMSIG_MOB_APPLY_DAMGE, .proc/explodable_attack_zone, TRUE) RegisterSignal(equipper, COMSIG_MOB_APPLY_DAMAGE, .proc/explodable_attack_zone, TRUE)
/datum/component/explodable/proc/on_drop(datum/source, mob/user) /datum/component/explodable/proc/on_drop(datum/source, mob/user)
UnregisterSignal(user, COMSIG_MOB_APPLY_DAMGE) UnregisterSignal(user, COMSIG_MOB_APPLY_DAMAGE)
/// Checks if we're hitting the zone this component is covering /// Checks if we're hitting the zone this component is covering
/datum/component/explodable/proc/is_hitting_zone(def_zone) /datum/component/explodable/proc/is_hitting_zone(def_zone)
+2 -2
View File
@@ -34,13 +34,13 @@
. = ..() . = ..()
UnregisterSignal(source, COMSIG_MOB_ATTACK_HAND) UnregisterSignal(source, COMSIG_MOB_ATTACK_HAND)
/datum/element/wuv/proc/on_attack_hand(datum/source, mob/user) /datum/element/wuv/proc/on_attack_hand(datum/source, mob/user, act_intent)
var/mob/living/L = source var/mob/living/L = source
if(L.stat == DEAD) if(L.stat == DEAD)
return return
//we want to delay the effect to be displayed after the mob is petted, not before. //we want to delay the effect to be displayed after the mob is petted, not before.
switch(user.a_intent) switch(act_intent)
if(INTENT_HARM) if(INTENT_HARM)
addtimer(CALLBACK(src, .proc/kick_the_dog, source, user), 1) addtimer(CALLBACK(src, .proc/kick_the_dog, source, user), 1)
if(INTENT_HELP) if(INTENT_HELP)
+18
View File
@@ -412,6 +412,24 @@ If not set, defaults to check_completion instead. Set it. It's used by cryo.
counter++ counter++
return counter >= 8 return counter >= 8
/datum/objective/freedom
name = "freedom"
explanation_text = "Don't get captured by nanotrasen."
team_explanation_text = "Have all members of your team free of nanotrasen custody."
/datum/objective/freedom/check_completion()
var/list/datum/mind/owners = get_owners()
for(var/m in owners)
var/datum/mind/M = m
if(!considered_alive(M))
return FALSE
if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME)
return FALSE
var/turf/location = get_turf(M.current)
if(!location || istype(location, /turf/open/floor/plasteel/shuttle/red) || istype(location, /turf/open/floor/mineral/plastitanium/red/brig)) // Fails if they are in the shuttle brig
return FALSE
return TRUE
/datum/objective/escape /datum/objective/escape
name = "escape" name = "escape"
explanation_text = "Escape on the shuttle or an escape pod alive and without being in custody." explanation_text = "Escape on the shuttle or an escape pod alive and without being in custody."
+2 -4
View File
@@ -210,8 +210,7 @@
target.apply_effect(EFFECT_STUTTER, stunforce) target.apply_effect(EFFECT_STUTTER, stunforce)
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK) SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
if(user) if(user)
target.lastattacker = user.real_name target.set_last_attacker(user)
target.lastattackerckey = user.ckey
target.visible_message("<span class='danger'>[user] has shocked [target] with [src]!</span>", \ target.visible_message("<span class='danger'>[user] has shocked [target] with [src]!</span>", \
"<span class='userdanger'>[user] has shocked you with [src]!</span>") "<span class='userdanger'>[user] has shocked you with [src]!</span>")
log_combat(user, target, "stunned with an electrostaff") log_combat(user, target, "stunned with an electrostaff")
@@ -237,8 +236,7 @@
target.adjustFireLoss(lethal_force) //good against ointment spam target.adjustFireLoss(lethal_force) //good against ointment spam
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK) SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
if(user) if(user)
target.lastattacker = user.real_name target.set_last_attacker(user)
target.lastattackerckey = user.ckey
target.visible_message("<span class='danger'>[user] has seared [target] with [src]!</span>", \ target.visible_message("<span class='danger'>[user] has seared [target] with [src]!</span>", \
"<span class='userdanger'>[user] has seared you with [src]!</span>") "<span class='userdanger'>[user] has seared you with [src]!</span>")
log_combat(user, target, "burned with an electrostaff") log_combat(user, target, "burned with an electrostaff")
+1 -2
View File
@@ -209,8 +209,7 @@
L.apply_effect(EFFECT_STUTTER, stamforce) L.apply_effect(EFFECT_STUTTER, stamforce)
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK) SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
if(user) if(user)
L.lastattacker = user.real_name L.set_last_attacker(user)
L.lastattackerckey = user.ckey
L.visible_message("<span class='danger'>[user] has [disarming? "disarmed" : "stunned"] [L] with [src]!</span>", \ L.visible_message("<span class='danger'>[user] has [disarming? "disarmed" : "stunned"] [L] with [src]!</span>", \
"<span class='userdanger'>[user] has [disarming? "disarmed" : "stunned"] you with [src]!</span>") "<span class='userdanger'>[user] has [disarming? "disarmed" : "stunned"] you with [src]!</span>")
log_combat(user, L, disarming? "disarmed" : "stunned") log_combat(user, L, disarming? "disarmed" : "stunned")
@@ -199,8 +199,7 @@
return TRUE return TRUE
/obj/item/gun_control/attack(mob/living/M, mob/living/user) /obj/item/gun_control/attack(mob/living/M, mob/living/user)
M.lastattacker = user.real_name M.set_last_attacker(user)
M.lastattackerckey = user.ckey
M.attacked_by(src, user) M.attacked_by(src, user)
add_fingerprint(user) add_fingerprint(user)
+4
View File
@@ -101,6 +101,10 @@ GLOBAL_VAR(antag_prototypes)
out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]<br>" out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]<br>"
out += "Assigned role: [assigned_role]. <a href='?src=[REF(src)];role_edit=1'>Edit</a><br>" out += "Assigned role: [assigned_role]. <a href='?src=[REF(src)];role_edit=1'>Edit</a><br>"
out += "Faction and special role: <b><font color='red'>[special_role]</font></b><br>" out += "Faction and special role: <b><font color='red'>[special_role]</font></b><br>"
var/datum/component/activity/activity = current.GetComponent(/datum/component/activity)
if(activity)
out += "Activity level: [activity.activity_level]<br>"
out += "Hasn't changed areas in approximately [activity.not_moved_counter] seconds"
var/special_statuses = get_special_statuses() var/special_statuses = get_special_statuses()
if(length(special_statuses)) if(length(special_statuses))
@@ -111,6 +111,7 @@ GLOBAL_LIST_EMPTY(antagonists)
var/datum/skill_modifier/job/M = GLOB.skill_modifiers[GET_SKILL_MOD_ID(A, type)] var/datum/skill_modifier/job/M = GLOB.skill_modifiers[GET_SKILL_MOD_ID(A, type)]
if(istype(M)) if(istype(M))
M.name = "[name] Training" M.name = "[name] Training"
owner.AddComponent(/datum/component/activity)
SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src) SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src)
/datum/antagonist/proc/is_banned(mob/M) /datum/antagonist/proc/is_banned(mob/M)
@@ -141,6 +142,7 @@ GLOBAL_LIST_EMPTY(antagonists)
var/datum/team/team = get_team() var/datum/team/team = get_team()
if(team) if(team)
team.remove_member(owner) team.remove_member(owner)
// we don't remove the activity component on purpose--no real point to it
qdel(src) qdel(src)
/datum/antagonist/proc/greet() /datum/antagonist/proc/greet()
@@ -511,8 +511,7 @@
/obj/item/abductor/baton/proc/StunAttack(mob/living/L,mob/living/user) /obj/item/abductor/baton/proc/StunAttack(mob/living/L,mob/living/user)
L.lastattacker = user.real_name L.set_last_attacker(user)
L.lastattackerckey = user.ckey
L.adjustStaminaLoss(35) //because previously it took 5-6 hits to actually "incapacitate" someone for the purposes of the sleep inducement L.adjustStaminaLoss(35) //because previously it took 5-6 hits to actually "incapacitate" someone for the purposes of the sleep inducement
L.DefaultCombatKnockdown(140) L.DefaultCombatKnockdown(140)
+1 -2
View File
@@ -385,8 +385,7 @@
qdel(src) qdel(src)
return return
log_combat(user, M, "used a cult spell on", source.name, "") log_combat(user, M, "used a cult spell on", source.name, "")
M.lastattacker = user.real_name M.set_last_attacker(user)
M.lastattackerckey = user.ckey
/obj/item/melee/blood_magic/afterattack(atom/target, mob/living/carbon/user, proximity) /obj/item/melee/blood_magic/afterattack(atom/target, mob/living/carbon/user, proximity)
. = ..() . = ..()
@@ -1,30 +1,7 @@
/datum/traitor_class/human/assassin /datum/traitor_class/human/subterfuge/assassin
name = "Donk Co Operative" name = "Donk Co Operative"
employer = "Donk Corporation" employer = "Donk Corporation"
weight = 0 weight = 6
chaos = 1 chaos = 1
threat = 2 threat = 2
assassin_prob = 70
/datum/traitor_class/human/assassin/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/permakill_prob = 20
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
permakill_prob = max(0,mode.threat_level-50)
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = T.owner
destroy_objective.find_target()
T.add_objective(destroy_objective)
else if(prob(permakill_prob))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
@@ -1,12 +1,12 @@
/datum/traitor_class/human/freeform /datum/traitor_class/human/freeform
name = "Waffle Co Agent" name = "Waffle Co Agent"
employer = "Waffle Company" employer = "Waffle Company"
weight = 0 // should not spawn in unless admins bus something in the traitor panel with setting traitor classes weight = 5
chaos = 0 chaos = 0
/datum/traitor_class/human/freeform/forge_objectives(datum/antagonist/traitor/T) /datum/traitor_class/human/freeform/forge_objectives(datum/antagonist/traitor/T)
var/datum/objective/escape/O = new var/datum/objective/freedom/O = new
O.explanation_text = "You have no explicit goals! While we don't approve of mindless slaughter, you may antagonize nanotrasen any way you wish! Make sure to escape alive and not in custody, though!" O.explanation_text = "You have no explicit goals! While we don't approve of mindless slaughter, you may antagonize nanotrasen any way you wish! Don't get captured or killed, but if you've done nothing, you'll be in trouble!"
O.owner = T.owner O.owner = T.owner
T.add_objective(O) T.add_objective(O)
return return
@@ -13,8 +13,12 @@
T.assign_exchange_role(SSticker.mode.exchange_blue) T.assign_exchange_role(SSticker.mode.exchange_blue)
objective_count += 1 //Exchange counts towards number of objectives objective_count += 1 //Exchange counts towards number of objectives
var/toa = CONFIG_GET(number/traitor_objectives_amount) var/toa = CONFIG_GET(number/traitor_objectives_amount)
var/attempts = 0
for(var/i = objective_count, i < toa, i++) for(var/i = objective_count, i < toa, i++)
forge_single_objective(T) var/success = FALSE
while(!success && attempts < max(toa*10, 100))
success = forge_single_objective(T)
attempts += 1
if(!(locate(/datum/objective/escape) in T.objectives)) if(!(locate(/datum/objective/escape) in T.objectives))
var/datum/objective/escape/escape_objective = new var/datum/objective/escape/escape_objective = new
escape_objective.owner = T.owner escape_objective.owner = T.owner
@@ -1,12 +1,11 @@
/datum/traitor_class/human/subterfuge /datum/traitor_class/human/subterfuge
name = "MI13 Operative" name = "MI13 Operative"
employer = "MI13" employer = "MI13"
weight = 36 weight = 25
chaos = -5 chaos = -5
var/assassin_prob = 25
/datum/traitor_class/human/subterfuge/forge_single_objective(datum/antagonist/traitor/T) /datum/traitor_class/human/subterfuge/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/assassin_prob = 30
var/datum/game_mode/dynamic/mode var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic)) if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode mode = SSticker.mode
@@ -16,24 +15,31 @@
kill_objective.owner = T.owner kill_objective.owner = T.owner
kill_objective.find_target() kill_objective.find_target()
T.add_objective(kill_objective) T.add_objective(kill_objective)
return TRUE
else else
var/list/weights = list() var/list/weights = list()
weights["sabo"] = length(subtypesof(/datum/sabotage_objective)) var/datum/objective/sabotage/sabotage_objective = new
weights["steal"] = length(subtypesof(/datum/objective_item/steal)) sabotage_objective.owner = T.owner
if(sabotage_objective.find_target())
weights["sabo"] = length(subtypesof(/datum/objective_item/steal))
var/datum/objective/steal/steal_objective = new
steal_objective.owner = T.owner
if(steal_objective.find_target())
weights["steal"] = length(subtypesof(/datum/objective_item/steal))
weights["download"] = !(locate(/datum/objective/download) in T.objectives || (T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist"))) weights["download"] = !(locate(/datum/objective/download) in T.objectives || (T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
switch(pickweight(weights)) switch(pickweight(weights))
if("sabo") if("sabo")
var/datum/objective/sabotage/sabotage_objective = new
sabotage_objective.owner = T.owner
sabotage_objective.find_target()
T.add_objective(sabotage_objective) T.add_objective(sabotage_objective)
qdel(steal_objective)
return TRUE
if("steal") if("steal")
var/datum/objective/steal/steal_objective = new
steal_objective.owner = T.owner
steal_objective.find_target()
T.add_objective(steal_objective) T.add_objective(steal_objective)
qdel(sabotage_objective)
return TRUE
if("download") if("download")
var/datum/objective/download/download_objective = new var/datum/objective/download/download_objective = new
download_objective.owner = T.owner download_objective.owner = T.owner
download_objective.gen_amount_goal() download_objective.gen_amount_goal()
T.add_objective(download_objective) T.add_objective(download_objective)
return TRUE
return FALSE
@@ -7,7 +7,8 @@ GLOBAL_LIST_EMPTY(traitor_classes)
var/chaos = 0 var/chaos = 0
var/threat = 0 var/threat = 0
var/TC = 20 var/TC = 20
/// Minimum players for this to randomly roll via get_random_traitor_class(). var/processing = FALSE
/// Minimum players for this to randomly roll via get_random_traitor_kind().
var/min_players = 0 var/min_players = 0
var/list/uplink_filters var/list/uplink_filters
@@ -43,4 +44,6 @@ GLOBAL_LIST_EMPTY(traitor_classes)
/datum/traitor_class/proc/clean_up_traitor(datum/antagonist/traitor/T) /datum/traitor_class/proc/clean_up_traitor(datum/antagonist/traitor/T)
// Any effects that need to be cleaned up if traitor class is being swapped. // Any effects that need to be cleaned up if traitor class is being swapped.
/datum/traitor_class/proc/on_process(/datum/antagonist/traitor/T)
// only for processing traitor classes; runs once an SSprocessing tick
@@ -26,6 +26,8 @@
if(traitor_kind) if(traitor_kind)
traitor_kind.remove_innate_effects(owner.current) traitor_kind.remove_innate_effects(owner.current)
traitor_kind.clean_up_traitor(src) traitor_kind.clean_up_traitor(src)
if(traitor_kind.processing)
STOP_PROCESSING(SSprocessing, src)
swap_from_old = TRUE swap_from_old = TRUE
traitor_kind = GLOB.traitor_classes[kind] traitor_kind = GLOB.traitor_classes[kind]
traitor_kind.apply_innate_effects(owner.current) traitor_kind.apply_innate_effects(owner.current)
@@ -33,11 +35,16 @@
for(var/O in objectives) for(var/O in objectives)
qdel(O) qdel(O)
traitor_kind.forge_objectives(src) traitor_kind.forge_objectives(src)
if(traitor_kind.processing)
START_PROCESSING(SSprocessing, src)
if(swap_from_old) if(swap_from_old)
traitor_kind.finalize_traitor(src) traitor_kind.finalize_traitor(src)
traitor_kind.greet(src) traitor_kind.greet(src)
owner.announce_objectives() owner.announce_objectives()
/datum/antagonist/traitor/process()
traitor_kind.on_process(src)
/proc/get_random_traitor_kind(var/list/blacklist = list()) /proc/get_random_traitor_kind(var/list/blacklist = list())
var/chaos_weight = 0 var/chaos_weight = 0
if(istype(SSticker.mode,/datum/game_mode/dynamic)) if(istype(SSticker.mode,/datum/game_mode/dynamic))
@@ -1,7 +1,7 @@
/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) /mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone) SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone)
var/hit_percent = (100-blocked)/100 var/hit_percent = (100-blocked)/100
if(!forced && hit_percent <= 0) if(!forced && hit_percent <= 0)
return 0 return 0
@@ -1620,8 +1620,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
"<span class='userdanger'>[user] [atk_verb]ed you!</span>", null, COMBAT_MESSAGE_RANGE, null, \ "<span class='userdanger'>[user] [atk_verb]ed you!</span>", null, COMBAT_MESSAGE_RANGE, null, \
user, "<span class='danger'>You [atk_verb]ed [target]!</span>") user, "<span class='danger'>You [atk_verb]ed [target]!</span>")
target.lastattacker = user.real_name target.set_last_attacker(user)
target.lastattackerckey = user.ckey
user.dna.species.spec_unarmedattacked(user, target) user.dna.species.spec_unarmedattacked(user, target)
if(user.limb_destroyer) if(user.limb_destroyer)
@@ -2058,7 +2057,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
log_combat(user, target, "shoved", append_message) log_combat(user, target, "shoved", append_message)
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) /datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone, wound_bonus, bare_wound_bonus, sharpness) // make sure putting wound_bonus here doesn't screw up other signals or uses for this signal SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone, wound_bonus, bare_wound_bonus, sharpness) // make sure putting wound_bonus here doesn't screw up other signals or uses for this signal
var/hit_percent = (100-(blocked+armor))/100 var/hit_percent = (100-(blocked+armor))/100
hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100 hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100
if(!forced && hit_percent <= 0) if(!forced && hit_percent <= 0)
+1 -1
View File
@@ -2,7 +2,7 @@
/** /**
* Applies damage to this mob * Applies damage to this mob
* *
* Sends [COMSIG_MOB_APPLY_DAMGE] * Sends [COMSIG_MOB_APPLY_DAMAGE]
* *
* Arguuments: * Arguuments:
* * damage - amount of damage * * damage - amount of damage
+7 -1
View File
@@ -274,7 +274,7 @@
/mob/living/on_attack_hand(mob/user, act_intent = user.a_intent, attackchain_flags) /mob/living/on_attack_hand(mob/user, act_intent = user.a_intent, attackchain_flags)
..() //Ignoring parent return value here. ..() //Ignoring parent return value here.
SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user) SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user, act_intent)
if((user != src) && act_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE | ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE), null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS)) if((user != src) && act_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE | ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE), null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS))
log_combat(user, src, "attempted to touch") log_combat(user, src, "attempted to touch")
visible_message("<span class='warning'>[user] attempted to touch [src]!</span>", visible_message("<span class='warning'>[user] attempted to touch [src]!</span>",
@@ -561,3 +561,9 @@
/mob/living/proc/getFireLoss_nonProsthetic() /mob/living/proc/getFireLoss_nonProsthetic()
return getFireLoss() return getFireLoss()
/mob/living/proc/set_last_attacker(mob/attacker)
lastattacker = attacker.real_name
lastattackerckey = attacker.ckey
SEND_SIGNAL(src, COMSIG_LIVING_ATTACKER_SET, attacker)
SEND_SIGNAL(attacker, COMSIG_LIVING_SET_AS_ATTACKER, src)
+1 -2
View File
@@ -267,8 +267,7 @@ They *could* go in their appropriate files, but this is supposed to be modular
apply_effect(EFFECT_STUTTER, G.stunforce) apply_effect(EFFECT_STUTTER, G.stunforce)
SEND_SIGNAL(src, COMSIG_LIVING_MINOR_SHOCK) SEND_SIGNAL(src, COMSIG_LIVING_MINOR_SHOCK)
lastattacker = H.real_name set_last_attacker(H)
lastattackerckey = H.ckey
log_combat(H, src, "stunned") log_combat(H, src, "stunned")
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1) playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
@@ -172,17 +172,17 @@
/datum/uplink_item/bundles_TC/reroll /datum/uplink_item/bundles_TC/reroll
name = "Renegotiate Contract" name = "Renegotiate Contract"
desc = "Selecting this will inform your employers that you wish for new objectives. Can only be done once; no take-backs." desc = "Selecting this will inform your employers that you wish for new objectives. Can only be done twice."
item = /obj/effect/gibspawner/generic item = /obj/effect/gibspawner/generic
cost = 0 cost = 0
cant_discount = TRUE cant_discount = TRUE
restricted = TRUE restricted = TRUE
limited_stock = 1 limited_stock = 2
/datum/uplink_item/bundles_TC/reroll/purchase(mob/user, datum/component/uplink/U) /datum/uplink_item/bundles_TC/reroll/purchase(mob/user, datum/component/uplink/U)
var/datum/antagonist/traitor/T = user?.mind?.has_antag_datum(/datum/antagonist/traitor) var/datum/antagonist/traitor/T = user?.mind?.has_antag_datum(/datum/antagonist/traitor)
if(istype(T)) if(istype(T))
T.set_traitor_kind(/datum/traitor_class/human/subterfuge) T.set_traitor_kind(get_random_traitor_kind(blacklist = list(/datum/traitor_class/human/freeform, /datum/traitor_class/human/hijack, /datum/traitor_class/human/martyr)))
else else
to_chat(user,"Invalid user for contract renegotiation.") to_chat(user,"Invalid user for contract renegotiation.")
+1
View File
@@ -453,6 +453,7 @@
#include "code\datums\brain_damage\special.dm" #include "code\datums\brain_damage\special.dm"
#include "code\datums\brain_damage\split_personality.dm" #include "code\datums\brain_damage\split_personality.dm"
#include "code\datums\components\_component.dm" #include "code\datums\components\_component.dm"
#include "code\datums\components\activity.dm"
#include "code\datums\components\anti_magic.dm" #include "code\datums\components\anti_magic.dm"
#include "code\datums\components\armor_plate.dm" #include "code\datums\components\armor_plate.dm"
#include "code\datums\components\bane.dm" #include "code\datums\components\bane.dm"