diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index 36225923fe0..e542c7df7ec 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -283,7 +283,7 @@ GLOBAL_LIST_INIT(ai_employers, list( #define GET_CULTIST(mob) (mob?.mind?.has_antag_datum(/datum/antagonist/cult)) /// Checks if the mob is a sentient or non-sentient cultist -#define IS_CULTIST_OR_CULTIST_MOB(mob) ((IS_CULTIST(mob)) || (mob.faction.Find(FACTION_CULT))) +#define IS_CULTIST_OR_CULTIST_MOB(mob) ((IS_CULTIST(mob)) || (mob.has_faction(FACTION_CULT))) /** * Heretic checks diff --git a/code/__DEFINES/mobfactions.dm b/code/__DEFINES/mobfactions.dm index 04126755f9d..9a3be60c5c7 100644 --- a/code/__DEFINES/mobfactions.dm +++ b/code/__DEFINES/mobfactions.dm @@ -102,3 +102,49 @@ /// Generates a mob faction for the passed owner, used by stabilized pink extracts #define FACTION_PINK_EXTRACT(owner) "pink_[owner]" + +/** + * SET_FACTION_AND_ALLIES_FROM(destination, source) + * Sets the atom's faction and allies to match that of the provided type's. + * + * This is equivalent to: + * destination.set_faction(source.get_faction()) + * destination.set_allies(source.allies) + * + * This is a macro (not a proc) to avoid proc call overhead in hot paths. + */ +#define SET_FACTION_AND_ALLIES_FROM(destination, source) \ + do { \ + (destination).set_faction((source).get_faction()); \ + (destination).set_allies(LAZYLISTDUPLICATE((source).allies)); \ + } while(FALSE) + +/** + * APPLY_FACTION_AND_ALLIES_FROM(destination, source) + * Adds the provided type's factions and allies to the atom's current factions and allies. + * + * This is equivalent to: + * destination.add_faction(source.get_faction()) + * destination.add_ally(source.allies) + * + * This is a macro (not a proc) to avoid proc call overhead in hot paths. + */ +#define APPLY_FACTION_AND_ALLIES_FROM(destination, source) \ + do { \ + (destination).add_faction((source).get_faction()); \ + (destination).add_ally(LAZYLISTDUPLICATE((source).allies)); \ + } while(FALSE) + +/** + * Compare two lists of factions, returning true if any match. + * If exact match is passed through we only return true if both faction lists match equally. + * + * Macro-ified version to avoid extra proc overhead. + */ +#define FAST_FACTION_CHECK(faction_A, faction_B, allies_A, allies_B, exact_match) \ +( \ + !(exact_match) ? \ + (LAZYLEN((faction_A) & (faction_B)) || LAZYLEN((allies_A) & (allies_B))) \ + : \ + ((LAZYLEN((faction_A) & (faction_B)) == LAZYLEN(faction_A)) && LAZYLEN((allies_A) & (allies_B))) \ +) diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index accfdf2ab22..5ad65cbc4df 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -106,6 +106,8 @@ #define VV_HK_OBSERVE_FOLLOW "observe_follow" #define VV_HK_GET_MOVABLE "get_movable" #define VV_HK_DEADCHAT_PLAYS "deadchat_plays" +#define VV_HK_ADD_REMOVE_FACTION "add_remove_faction" +#define VV_HK_GET_FACTIONS "add_remove_factions" // /obj #define VV_HK_OSAY "osay" diff --git a/code/datums/actions/mobs/create_legion_turrets.dm b/code/datums/actions/mobs/create_legion_turrets.dm index 18fc28e15eb..eb0505c5ffc 100644 --- a/code/datums/actions/mobs/create_legion_turrets.dm +++ b/code/datums/actions/mobs/create_legion_turrets.dm @@ -64,7 +64,7 @@ for(var/mob/living/possible_target in oview(9, src)) if(possible_target.stat == DEAD || possible_target.stat == UNCONSCIOUS) continue - if(faction_check(faction, possible_target.faction)) + if(faction_check_atom(possible_target)) continue fire(possible_target) return diff --git a/code/datums/ai/basic_mobs/admin_ai_templates.dm b/code/datums/ai/basic_mobs/admin_ai_templates.dm index 5d63b078543..96aedf36ec4 100644 --- a/code/datums/ai/basic_mobs/admin_ai_templates.dm +++ b/code/datums/ai/basic_mobs/admin_ai_templates.dm @@ -62,7 +62,8 @@ target.ai_controller = new controller_type(target) if (make_hostile) - target.faction = list(FACTION_HOSTILE, REF(target)) + target.set_faction(list(FACTION_HOSTILE)) + target.set_allies(list(REF(target))) var/datum/ai_controller/controller = target.ai_controller controller.set_blackboard_key(BB_BASIC_MOB_IDLE_WALK_CHANCE, idle_chance) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/play_with_owners.dm b/code/datums/ai/basic_mobs/basic_subtrees/play_with_owners.dm index e27e984e706..f78574a110a 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/play_with_owners.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/play_with_owners.dm @@ -11,7 +11,7 @@ behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION /datum/ai_behavior/find_hunt_target/find_owner/valid_dinner(mob/living/source, atom/friend, radius, datum/ai_controller/controller, seconds_per_tick) - return (friend != source) && (source.faction.Find(REF(friend))) && can_see(source, friend, radius) + return (friend != source) && (source.has_ally(friend)) && can_see(source, friend, radius) /datum/ai_behavior/hunt_target/play_with_owner diff --git a/code/datums/ai/generic/find_and_set.dm b/code/datums/ai/generic/find_and_set.dm index 95d8106a2ad..9ec033e0402 100644 --- a/code/datums/ai/generic/find_and_set.dm +++ b/code/datums/ai/generic/find_and_set.dm @@ -194,7 +194,7 @@ return null var/mob/living/living_pawn = controller.pawn - var/potential_friend = living_pawn.faction.Find(REF(friend)) ? friend : null + var/potential_friend = living_pawn.has_ally(friend) ? friend : null return potential_friend diff --git a/code/datums/ai/monkey/monkey_behaviors.dm b/code/datums/ai/monkey/monkey_behaviors.dm index 01dd0b61449..c21d15e8a19 100644 --- a/code/datums/ai/monkey/monkey_behaviors.dm +++ b/code/datums/ai/monkey/monkey_behaviors.dm @@ -288,7 +288,7 @@ if(!enemies[possible_enemy]) //We don't hate this creature! But we might still attack it! if(!controller.blackboard[BB_MONKEY_AGGRESSIVE]) //We are not aggressive either, so we won't attack! continue - if(faction_check(possible_enemy.faction, list(FACTION_MONKEY, FACTION_JUNGLE), exact_match = FALSE) && !controller.blackboard[BB_MONKEY_TARGET_MONKEYS]) // do not target your team. includes monkys gorillas etc. + if(possible_enemy.has_faction(list(FACTION_MONKEY, FACTION_JUNGLE)) && !controller.blackboard[BB_MONKEY_TARGET_MONKEYS]) // do not target your team. includes monkys gorillas etc. continue // Weighted list, so the closer they are the more likely they are to be chosen as the enemy valids[possible_enemy] = CEILING(100 / (get_dist(controller.pawn, possible_enemy) || 1), 1) diff --git a/code/datums/components/blob_minion.dm b/code/datums/components/blob_minion.dm index b6db9de6c36..8e8f796d3ae 100644 --- a/code/datums/components/blob_minion.dm +++ b/code/datums/components/blob_minion.dm @@ -72,7 +72,7 @@ /datum/component/blob_minion/RegisterWithParent() var/mob/living/living_parent = parent - living_parent.faction |= ROLE_BLOB + living_parent.add_faction(ROLE_BLOB) ADD_TRAIT(parent, TRAIT_BLOB_ALLY, REF(src)) remove_verb(parent, /mob/living/verb/pulled) // No dragging people into the blob RegisterSignal(parent, COMSIG_MOB_MIND_INITIALIZED, PROC_REF(on_mind_init)) @@ -96,7 +96,7 @@ overmind.blob_mobs -= parent var/mob/living/living_parent = parent living_parent.pass_flags &= ~PASSBLOB - living_parent.faction -= ROLE_BLOB + living_parent.remove_faction(ROLE_BLOB) REMOVE_TRAIT(parent, TRAIT_BLOB_ALLY, REF(src)) add_verb(parent, /mob/living/verb/pulled) UnregisterSignal(parent, list( diff --git a/code/datums/components/damage_aura.dm b/code/datums/components/damage_aura.dm index 3497e83cb90..424a8796054 100644 --- a/code/datums/components/damage_aura.dm +++ b/code/datums/components/damage_aura.dm @@ -90,7 +90,7 @@ /// The requirements for the mob to be effected by the damage aura. /datum/component/damage_aura/proc/check_requirements(mob/living/target_mob) - if(target_mob.stat == DEAD || faction_check(target_mob.faction, immune_factions)) + if(target_mob.stat == DEAD || target_mob.has_faction(immune_factions)) return TRUE return FALSE diff --git a/code/datums/components/faction_granter.dm b/code/datums/components/faction_granter.dm index ad6b4f63369..91ed24c20e0 100644 --- a/code/datums/components/faction_granter.dm +++ b/code/datums/components/faction_granter.dm @@ -51,5 +51,5 @@ return to_chat(user, grant_message) - user.faction |= faction_to_grant + user.add_faction(faction_to_grant) used = TRUE diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index a27e05915a4..c515df2cdd0 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -69,7 +69,7 @@ // for fireman carries, check if the ridden is stunned/restrained else if((ride_check_flags & CARRIER_NEEDS_ARM) && (HAS_TRAIT(living_parent, TRAIT_RESTRAINED) || INCAPACITATED_IGNORING(living_parent, INCAPABLE_RESTRAINTS|INCAPABLE_GRAB))) . = FALSE - else if((ride_check_flags & JUST_FRIEND_RIDERS) && !(living_parent.faction.Find(REF(rider)))) + else if((ride_check_flags & JUST_FRIEND_RIDERS) && !(living_parent.has_ally(rider))) . = FALSE if(. || !consequences) @@ -222,7 +222,7 @@ /datum/component/riding/creature/handle_buckle(mob/living/rider) . = ..() var/mob/living/ridden = parent - if(!require_minigame || ridden.faction.Find(REF(rider))) + if(!require_minigame || ridden.has_ally(rider)) return ridden.Shake(pixelshiftx = 1, pixelshifty = 0, duration = 1 SECONDS) ridden.spin(spintime = 1 SECONDS, speed = 1) diff --git a/code/datums/components/slime_friends.dm b/code/datums/components/slime_friends.dm index d2b751d092e..8e141fc8443 100644 --- a/code/datums/components/slime_friends.dm +++ b/code/datums/components/slime_friends.dm @@ -32,13 +32,13 @@ if(!isliving(parent)) return COMPONENT_INCOMPATIBLE var/mob/living/living_parent = parent - living_parent.faction |= FACTION_SLIME + living_parent.add_faction(FACTION_SLIME) RegisterSignal(living_parent, COMSIG_ENTER_AREA, PROC_REF(start_slime_prodaction)) /datum/component/slime_friends/Destroy(force) . = ..() var/mob/living/living_parent = parent - living_parent.faction -= FACTION_SLIME + living_parent.remove_faction(FACTION_SLIME) timer = null /// Start slime prodaction when we leave wizden. @@ -56,6 +56,6 @@ var/turf/where = get_turf(friend) var/new_colour = pick(colours) var/mob/living/basic/slime/new_friend = new(where, new_colour, SLIME_LIFE_STAGE_ADULT) - new_friend.faction = friend.faction.Copy() + SET_FACTION_AND_ALLIES_FROM(new_friend, friend) new_friend.set_enraged_behaviour() friend.nutrition -= 50 diff --git a/code/datums/components/spawner.dm b/code/datums/components/spawner.dm index 26dbffaef6f..89281a40e9f 100644 --- a/code/datums/components/spawner.dm +++ b/code/datums/components/spawner.dm @@ -90,19 +90,16 @@ if (isliving(created)) var/mob/living/created_mob = created - created_mob.faction = src.faction + created_mob.set_faction(faction) RegisterSignal(created, COMSIG_MOB_STATCHANGE, PROC_REF(mob_stat_changed)) SEND_SIGNAL(src, COMSIG_SPAWNER_SPAWNED, created) RegisterSignal(created, COMSIG_QDELETING, PROC_REF(on_deleted)) spawn_callback?.Invoke(created) - if (spawn_text) spawner.visible_message(span_danger("A creature [spawn_text] [spawner].")) - - /// Remove weakrefs to atoms which have been killed or deleted without us picking it up somehow /datum/component/spawner/proc/validate_references() for (var/datum/weakref/weak_thing as anything in spawned_things) diff --git a/code/datums/components/style/style.dm b/code/datums/components/style/style.dm index 7e156603e88..6e1147a7ba3 100644 --- a/code/datums/components/style/style.dm +++ b/code/datums/components/style/style.dm @@ -323,7 +323,7 @@ return var/mob/living/disrespected = attacked_atom - if(disrespected.stat || faction_check(punching_person.faction, disrespected.faction) || !(FACTION_MINING in disrespected.faction)) + if(disrespected.stat || disrespected.faction_check_atom(punching_person) || !disrespected.has_faction(FACTION_MINING)) return add_action(ACTION_DISRESPECT, 60 * (ismegafauna(disrespected) ? 2 : 1)) @@ -336,7 +336,7 @@ var/mob/living/attacked = attacked_mob var/mob/mob_parent = parent - if(faction_check(attacking_person.faction, attacked.faction) || !(FACTION_MINING in attacked.faction) || (istype(mob_parent.get_active_held_item(), /obj/item/kinetic_crusher) && attacked.has_status_effect(/datum/status_effect/crusher_mark))) + if(attacking_person.faction_check_atom(attacked) || !attacked.has_faction(FACTION_MINING) || (istype(mob_parent.get_active_held_item(), /obj/item/kinetic_crusher) && attacked.has_status_effect(/datum/status_effect/crusher_mark))) return add_action(ACTION_MELEED, 50 * (ismegafauna(attacked) ? 1.5 : 1)) @@ -370,7 +370,7 @@ /datum/component/style/proc/on_resonator_burst(datum/source, mob/creator, mob/living/hit_living) SIGNAL_HANDLER - if(faction_check(creator.faction, hit_living.faction) || (hit_living.stat != CONSCIOUS) || !(FACTION_MINING in hit_living.faction)) + if(creator.faction_check_atom(hit_living) || (hit_living.stat != CONSCIOUS) || !hit_living.has_faction(FACTION_MINING)) return add_action(ACTION_TRAPPER, 70) @@ -426,7 +426,7 @@ if(died == parent) change_points(-500, use_multiplier = FALSE) return - else if(faction_check(mob_parent.faction, died.faction) || !(FACTION_MINING in died.faction) || (died.z != mob_parent.z) || !(died in view(mob_parent.client?.view, get_turf(mob_parent)))) + else if(mob_parent.faction_check_atom(died) || !died.has_faction(FACTION_MINING) || (died.z != mob_parent.z) || !(died in view(mob_parent.client?.view, get_turf(mob_parent)))) return if(ismegafauna(died)) add_action(ACTION_MAJOR_KILL, 350) diff --git a/code/datums/components/summoning.dm b/code/datums/components/summoning.dm index 697a51f5d8f..d401b9785fa 100644 --- a/code/datums/components/summoning.dm +++ b/code/datums/components/summoning.dm @@ -76,8 +76,8 @@ var/mob/living/simple_animal/hostile/angry_boy = summoned angry_boy.friends |= summoner // do not attack our summon boy spawned_mobs |= summoned - if(faction != null) - summoned.faction = faction.Copy() + if(faction) + summoned.set_faction(faction) RegisterSignals(summoned, list(COMSIG_LIVING_DEATH, COMSIG_QDELETING), PROC_REF(on_spawned_death)) spawn_location.visible_message(span_danger("[summoned] [spawn_text]!")) diff --git a/code/datums/components/tameable.dm b/code/datums/components/tameable.dm index 6c64bfde0e0..2153d54d51e 100644 --- a/code/datums/components/tameable.dm +++ b/code/datums/components/tameable.dm @@ -50,7 +50,7 @@ if(!isliving(parent)) return FALSE // Figure this out when we actually need it var/mob/living/living_parent = parent - return living_parent.faction.Find(REF(potential_friend)) + return living_parent.has_ally(potential_friend) ///Ran once taming succeeds /datum/component/tameable/proc/on_tame(atom/source, mob/living/tamer, obj/item/food, inform_tamer = FALSE) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index dd27bf4232a..536fb1e0529 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -1,9 +1,15 @@ /datum/proc/CanProcCall(procname) return TRUE +/// Items in this list will not show up in VV +GLOBAL_LIST_INIT(vv_var_blacklist, list( + "faction" = TRUE, +)) /datum/proc/can_vv_get(var_name) if(var_name == NAMEOF(src, vars)) return FALSE + if(var_name in GLOB.vv_var_blacklist) + return FALSE return TRUE /// Called when a var is edited with the new value to change to diff --git a/code/datums/elements/pet_cult.dm b/code/datums/elements/pet_cult.dm index f26e6e343e6..90f561c75ec 100644 --- a/code/datums/elements/pet_cult.dm +++ b/code/datums/elements/pet_cult.dm @@ -35,14 +35,14 @@ /datum/element/cultist_pet/proc/on_overlays_updated(mob/living/basic/source, list/overlays) SIGNAL_HANDLER - if(isnull(source.mind) && (FACTION_CULT in source.faction)) //cult indicator we show for non sentient pets + if(isnull(source.mind) && source.has_faction(FACTION_CULT)) //cult indicator we show for non sentient pets var/image/cult_indicator = image(icon = 'icons/mob/simple/pets.dmi', icon_state = "pet_cult_indicator", layer = ABOVE_GAME_PLANE) overlays += cult_indicator /datum/element/cultist_pet/proc/on_icon_state_updated(mob/living/basic/source) SIGNAL_HANDLER - if(pet_cult_icon_state && (FACTION_CULT in source.faction)) + if(pet_cult_icon_state && source.has_faction(FACTION_CULT)) source.icon_state = pet_cult_icon_state source.icon_living = pet_cult_icon_state @@ -53,7 +53,7 @@ if(source.stat == DEAD) return - if(FACTION_CULT in source.faction) + if(source.has_faction(FACTION_CULT)) return STOP_SACRIFICE source.mind?.add_antag_datum(/datum/antagonist/cult, team) @@ -63,7 +63,7 @@ source.maxHealth = max(PET_CULT_HEALTH, source::maxHealth) source.fully_heal() - source.faction = list(FACTION_CULT) //we only serve the cult + source.set_faction(list(FACTION_CULT)) //we only serve the cult if(isnull(pet_cult_icon_state)) source.add_atom_colour(RUNE_COLOR_MEDIUMRED, FIXED_COLOUR_PRIORITY) @@ -115,7 +115,7 @@ /datum/element/cultist_pet/proc/on_login(mob/living/source) SIGNAL_HANDLER - if(!(FACTION_CULT in source.faction)) + if(!source.has_faction(FACTION_CULT)) return var/datum/team/cult_team = source.ai_controller.blackboard[BB_CULT_TEAM] if(isnull(cult_team)) diff --git a/code/datums/elements/regal_rat_minion.dm b/code/datums/elements/regal_rat_minion.dm index d0b2198dbf9..206c1f42278 100644 --- a/code/datums/elements/regal_rat_minion.dm +++ b/code/datums/elements/regal_rat_minion.dm @@ -44,5 +44,5 @@ qdel(new_minion.GetComponent(/datum/component/tameable)) // Rats don't share new_minion.befriend(master) - new_minion.faction = master.faction.Copy() + SET_FACTION_AND_ALLIES_FROM(new_minion, master) new_minion.balloon_alert_to_viewers(success_balloon) diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index 23baed7d334..b1cb83c8846 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -38,13 +38,13 @@ RegisterSignal(new_holder, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) RegisterSignal(new_holder, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(hit_by_projectile)) RegisterSignal(new_holder, COMSIG_LIVING_CHECK_BLOCK, PROC_REF(check_dodge)) - new_holder.faction |= FACTION_CARP //:D + new_holder.add_faction(FACTION_CARP) //:D new_holder.grant_language(/datum/language/carptongue, ALL, type) /datum/martial_art/the_sleeping_carp/deactivate_style(mob/living/remove_from) remove_from.remove_traits(scarp_traits, SLEEPING_CARP_TRAIT) UnregisterSignal(remove_from, list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_PRE_BULLET_ACT, COMSIG_LIVING_CHECK_BLOCK)) - remove_from.faction -= FACTION_CARP //:( + remove_from.remove_faction(FACTION_CARP) //:( if (!QDELING(remove_from)) remove_from.remove_language(/datum/language/carptongue, ALL, type) return ..() diff --git a/code/datums/mind/antag.dm b/code/datums/mind/antag.dm index 82921af80d8..007acd4c3b3 100644 --- a/code/datums/mind/antag.dm +++ b/code/datums/mind/antag.dm @@ -189,8 +189,8 @@ SEND_SIGNAL(current, COMSIG_MOB_ENSLAVED_TO, creator) - current.faction |= creator.faction - creator.faction |= "[REF(current)]" + current.add_faction(creator.get_faction()) + current.add_ally(current) current.log_message("has been enslaved to [key_name(creator)].", LOG_GAME) log_admin("[key_name(current)] has been enslaved to [key_name(creator)].") diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index 8696b4fe775..42ad8f177fa 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -35,7 +35,7 @@ if(WIRE_AI) // Pulse to pick a new AI. if(!R.emagged) var/new_ai - var/is_a_syndi_borg = (ROLE_SYNDICATE in R.faction) + var/is_a_syndi_borg = R.has_faction(ROLE_SYNDICATE) if(user) new_ai = select_active_ai(user, R.z, !is_a_syndi_borg, is_a_syndi_borg) else diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index f8f34533fd6..a5a22ec5347 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -782,7 +782,7 @@ * * Override this if you want an atom to be usable as a supplypod. */ -/atom/proc/setOpened() +/atom/proc/set_opened() return /** @@ -790,7 +790,7 @@ * * Override this if you want an atom to be usable as a supplypod. */ -/atom/proc/setClosed() +/atom/proc/set_closed() return ///Called after the atom is 'tamed' for type-specific operations, Usually called by the tameable component but also other things. diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 5377dccfddc..8b5d7911504 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -21,8 +21,10 @@ var/initial_language_holder = /datum/language_holder/atom_basic /// Holds all languages this mob can speak and understand VAR_PRIVATE/datum/language_holder/language_holder - /// The list of factions this atom belongs to - var/list/faction + /// The list of factions this atom belongs to (used for cacheable faction strings - these tend to not change very often) + VAR_PROTECTED/list/faction + /// The list of allies this atom has (used for anything too dynamic for string_list() - typically mob refs, each mob starts with themselves as an ally) + var/list/allies /// Use get_default_say_verb() in say.dm instead of reading verb_say. var/verb_say = "says" @@ -138,6 +140,9 @@ color = EM_BLOCK_COLOR /atom/movable/Initialize(mapload, ...) + if(LAZYLEN(faction)) + faction = string_list(faction) + . = ..() #ifdef UNIT_TESTS if(explosion_block && !HAS_TRAIT(src, TRAIT_BLOCKING_EXPLOSIVES)) @@ -1724,6 +1729,8 @@ VV_DROPDOWN_OPTION("", "---------") VV_DROPDOWN_OPTION(VV_HK_OBSERVE_FOLLOW, "Observe Follow") VV_DROPDOWN_OPTION(VV_HK_GET_MOVABLE, "Get Movable") + VV_DROPDOWN_OPTION(VV_HK_GET_FACTIONS, "Get Factions") + VV_DROPDOWN_OPTION(VV_HK_ADD_REMOVE_FACTION, "Add/Remove Faction") VV_DROPDOWN_OPTION(VV_HK_EDIT_PARTICLES, "Edit Particles") VV_DROPDOWN_OPTION(VV_HK_DEADCHAT_PLAYS, "Start/Stop Deadchat Plays") VV_DROPDOWN_OPTION(VV_HK_ADD_FANTASY_AFFIX, "Add Fantasy Affix") @@ -1746,6 +1753,23 @@ return forceMove(get_turf(usr)) + if(href_list[VV_HK_ADD_REMOVE_FACTION]) + if(!check_rights(R_ADMIN)) + return + if(QDELETED(src)) + return + if(edit_faction(usr)) + var/list/factions_printout = faction_to_text() + to_chat(usr, span_notice("Factions updated for [src]:[factions_printout]")) + + if(href_list[VV_HK_GET_FACTIONS]) + if(!check_rights(R_ADMIN)) + return + if(QDELETED(src)) + return + var/list/factions_printout = faction_to_text() + to_chat(usr, span_notice(span_notice("Factions for [src]:[factions_printout]"))) + if(href_list[VV_HK_EDIT_PARTICLES] && check_rights(R_VAREDIT)) var/client/C = usr.client C?.open_particle_editor(src) @@ -1777,19 +1801,232 @@ SHOULD_CALL_PARENT(TRUE) SEND_SIGNAL(src, COMSIG_ATOM_USED_IN_CRAFT, result) +/* + * Compare two lists of factions, returning true if any match + * + * If exact match is passed through we only return true if both faction lists match equally + */ +/proc/faction_check(list/faction_A, list/faction_B, list/allies_A, list/allies_B, exact_match) + if(!exact_match) + return LAZYLEN(faction_A & faction_B) || LAZYLEN(allies_A & allies_B) + else + if(LAZYLEN(faction_A&faction_B) != LAZYLEN(faction_A)) + return FALSE //if they're not the same len(gth) or we don't have a len, then this isn't an exact match. + return LAZYLEN(allies_A & allies_B) + /** * Check if the other atom/movable has any factions the same as us. Defined at the atom/movable level so it can be defined for just about anything. * * If exact match is set, then all our factions must match exactly */ /atom/movable/proc/faction_check_atom(atom/movable/target, exact_match) - if(!exact_match) - return faction_check(faction, target.faction, FALSE) + if(exact_match) + var/list/allies_src = LAZYCOPY(allies) + var/list/allies_target = LAZYCOPY(target.allies) + if(!("[REF(src)]" in allies_target)) //if they don't have our ref faction, remove it from our factions list. + allies_src -= "[REF(src)]" //if we don't do this, we'll never have an exact match. + if(!("[REF(target)]" in allies_src)) + allies_target -= "[REF(target)]" //same thing here. + return FAST_FACTION_CHECK(faction, target.faction, allies, target.allies, TRUE) + else + return FAST_FACTION_CHECK(faction, target.faction, allies, target.allies, FALSE) - var/list/faction_src = LAZYCOPY(faction) - var/list/faction_target = LAZYCOPY(target.faction) - if(!("[REF(src)]" in faction_target)) //if they don't have our ref faction, remove it from our factions list. - faction_src -= "[REF(src)]" //if we don't do this, we'll never have an exact match. - if(!("[REF(target)]" in faction_src)) - faction_target -= "[REF(target)]" //same thing here. - return faction_check(faction_src, faction_target, TRUE) +/* + * Sets atom's allies list to be the provided list of faction strings. Returns TRUE if successful. + */ +/atom/movable/proc/set_allies(ally_list) + if (!islist(ally_list) && !isnull(ally_list)) + stack_trace("Tried to call set_allies on [src] with a non-list arg. Use add_ally([ally_list]) instead.") + return FALSE + + if (!LAZYLEN(ally_list) && !isnull(ally_list)) // empty list, should just null it in that case + LAZYNULL(allies) + return TRUE + + allies = ally_list + + return TRUE + +/* + * Adds an ally or list of allies to the allies list. Automatically converts target to ref if it is an atom. + * Returns TRUE if something was actually added, false otherwise + */ +/atom/movable/proc/add_ally(ally_or_allies) + var/old_length = LAZYLEN(allies) + if(!isatom(ally_or_allies)) + LAZYOR(allies, ally_or_allies) + else + LAZYOR(allies, "[REF(ally_or_allies)]") + + return LAZYLEN(allies) != old_length + +/* + * Removes an ally or list of allies from the allies list. Automatically converts target to ref if it is an atom. + * Returns TRUE if something was actually added, false otherwise + */ +/atom/movable/proc/remove_ally(atom/target) + var/old_length = LAZYLEN(allies) + if (!old_length) + return FALSE + + if(!isatom(target)) + LAZYREMOVE(allies, target) + else + LAZYREMOVE(allies, "[REF(target)]") + + return old_length != LAZYLEN(allies) + +/* + * Returns TRUE if the ally or allies in list are in our allies list + * If match_all is set, we have to match everything in the provided list arg. + */ +/atom/movable/proc/has_ally(ally_or_allies, match_all) + if (!LAZYLEN(allies)) + return FALSE + + if (islist(ally_or_allies)) + if(match_all) + var/match_count = FAST_FACTION_CHECK(null, null, allies, ally_or_allies, TRUE) + return (match_count == LAZYLEN(ally_or_allies)) + else + return FAST_FACTION_CHECK(null, null, allies, ally_or_allies, FALSE) + + else if(isatom(ally_or_allies)) + return "[REF(ally_or_allies)]" in allies + else + return ally_or_allies in allies +/** + * Returns the faction list of this atom/movable + */ +/atom/movable/proc/get_faction() + return faction + +/** + * Sets atom's faction list to be the provided list of faction strings. Returns TRUE if successful. + */ +/atom/movable/proc/set_faction(factions) + if (factions == faction) // Same list in memory - early return + return TRUE + if (!islist(factions) && !isnull(factions)) + stack_trace("Tried to call set_faction on [src] with a non-list arg. Use add_faction([factions]) instead.") + return FALSE + + if (!LAZYLEN(factions)) // empty list, should just null it in that case + LAZYNULL(faction) + return TRUE + + faction = string_list(factions) + return TRUE + +/** + * Adds a single faction string or list of faction strings to the atom's faction list. Returns TRUE if something was added. + */ +/atom/movable/proc/add_faction(faction_or_factions) + var/list/faction_copy = LAZYLISTDUPLICATE(faction) // Copy so we are not mutating the cached list + LAZYOR(faction_copy, faction_or_factions) + + // If OR didn't add anything, do nothing + if (LAZYLEN(faction_copy) == LAZYLEN(faction)) + return FALSE + + faction = string_list(faction_copy) + return TRUE + +/** + * Removes a single faction string or list of faction strings from the atom's faction list. Returns TRUE if something was removed. + */ +/atom/movable/proc/remove_faction(faction_or_factions) + var/old_length = LAZYLEN(faction) + if (!old_length) + return FALSE + + var/list/faction_copy = LAZYLISTDUPLICATE(faction) // Copy so we are not mutating the cached list + LAZYREMOVE(faction_copy, faction_or_factions) + + var/new_length = LAZYLEN(faction_copy) + // If nothing remains in the copy, null the actual list too. + if (!new_length) + LAZYNULL(faction) + return TRUE + + if (old_length == new_length) // Nothing was removed, do nothing + return FALSE + + faction = string_list(faction_copy) + + return TRUE + +/** + * Returns TRUE if the faction or factions in list are in our faction list. + * If match_all is set, we have to match everything in the provided list arg. + */ +/atom/movable/proc/has_faction(faction_or_factions, match_all) + if (!LAZYLEN(faction)) + return FALSE + + if (islist(faction_or_factions)) + if(match_all) + var/match_count = FAST_FACTION_CHECK(faction, faction_or_factions, null, null, TRUE) + return (match_count == LAZYLEN(faction_or_factions)) + else + return FAST_FACTION_CHECK(faction, faction_or_factions, null, null, FALSE) + + else + return faction_or_factions in faction + +/** + * Returns TRUE if any of the factions or allies are in our faction list. + * If match_all is set, we have to match everything in the provided list arg. + */ +/atom/movable/proc/has_faction_or_allies(faction_or_factions, allies_list, match_all) + if (!LAZYLEN(faction_or_factions)) + return FALSE + + if (islist(faction_or_factions)) + if (match_all) + var/match_count = FAST_FACTION_CHECK(faction, faction_or_factions, allies, allies_list, TRUE) + return (match_count == LAZYLEN(faction_or_factions) + LAZYLEN(allies_list)) + else + return FAST_FACTION_CHECK(faction, faction_or_factions, allies, allies_list, FALSE) + + else + return (faction_or_factions in faction) && FAST_FACTION_CHECK(null, null, allies, allies_list, match_all) + +/** + * Opens the modify faction ui. + */ +/atom/movable/proc/edit_faction(mob/user) + var/prompt = tgui_alert(usr, "Would you like to Add or Remove faction?", "Add/Remove?", list("Add", "Remove")) + if (isnull(prompt)) + return FALSE + + if (prompt == "Add") + var/faction_to_add = tgui_input_text(user, "Enter a faction name to add.", "Add Faction", max_length = MAX_NAME_LEN) + if(isnull(faction_to_add)) + return FALSE + + return add_faction(faction_to_add) + + else if (prompt == "Remove") + var/list/current_factions = LAZYLISTDUPLICATE(faction) + if(!LAZYLEN(current_factions)) + to_chat(user, span_warning("[src] has no factions left to remove!")) + return FALSE + + current_factions = sort_list(current_factions, GLOBAL_PROC_REF(cmp_text_asc)) // sort alphabetically + + var/faction_to_remove = tgui_input_list(user, "Select a faction to remove.", "Remove faction", current_factions) + if(isnull(faction_to_remove)) + return FALSE + + return remove_faction(faction_to_remove) + +/** + * Outputs the factions list as text + */ +/atom/movable/proc/faction_to_text() + var/list/factions_printout = list() + for(var/faction_string in get_faction()) + factions_printout += "\n[faction_string]" + + return jointext(factions_printout, "") diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index bf179dff162..2b2d1dd7918 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -813,7 +813,7 @@ /obj/machinery/attack_ai(mob/user) if(!(interaction_flags_machine & INTERACT_MACHINE_ALLOW_SILICON) && !isAdminGhostAI(user)) return FALSE - if(!(ROLE_SYNDICATE in user.faction)) + if(!user.has_faction(ROLE_SYNDICATE)) if((ACCESS_SYNDICATE in req_access) || (ACCESS_SYNDICATE_LEADER in req_access) || (ACCESS_SYNDICATE in req_one_access) || (ACCESS_SYNDICATE_LEADER in req_one_access)) return FALSE if((onSyndieBase() && loc != user)) diff --git a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm index 6f2e35b3219..8939fb64e0f 100644 --- a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm @@ -146,7 +146,7 @@ var/mob/living/fresh_pancake = target // Check for nemesis factions on the target. - if(!(FACTION_MINING in fresh_pancake.faction) && !(FACTION_BOSS in fresh_pancake.faction)) + if(!fresh_pancake.has_faction(list(FACTION_MINING, FACTION_BOSS))) // Target is not a nemesis, so attack normally. return diff --git a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm index f8d47242623..b3d400ac39d 100644 --- a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm @@ -27,7 +27,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... greyscale_colors = GONDOLA_COLORS organ_traits = list(TRAIT_PACIFISM) ///keeps track of whether the receiver actually gained factions - var/list/factions_to_remove = list() + var/list/factions_to_remove /obj/item/organ/heart/gondola/Initialize(mapload) . = ..() @@ -37,18 +37,16 @@ Fluoride Stare: After someone says 5 words, blah blah blah... /obj/item/organ/heart/gondola/on_mob_insert(mob/living/carbon/receiver, special, movement_flags) . = ..() - if(!(FACTION_HOSTILE in receiver.faction)) - factions_to_remove += FACTION_HOSTILE - if(!(FACTION_MINING in receiver.faction)) - factions_to_remove += FACTION_MINING - receiver.faction |= list(FACTION_HOSTILE, FACTION_MINING) + if(!receiver.has_faction(FACTION_HOSTILE)) + LAZYADD(factions_to_remove, FACTION_HOSTILE) + if(!receiver.has_faction(FACTION_MINING)) + LAZYADD(factions_to_remove, FACTION_MINING) + receiver.add_faction(list(FACTION_HOSTILE, FACTION_MINING)) /obj/item/organ/heart/gondola/on_mob_remove(mob/living/carbon/heartless, special, movement_flags) . = ..() - for(var/faction in factions_to_remove) - heartless.faction -= faction - //reset this for a different target - factions_to_remove = list() + if(LAZYLEN(factions_to_remove)) + heartless.remove_faction(factions_to_remove) /// Zen (tounge): You can no longer speak, but get a powerful positive moodlet /obj/item/organ/tongue/gondola diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index e7a9826b183..738d5d15075 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -482,7 +482,7 @@ DEFINE_BITFIELD(turret_flags, list( continue if(in_faction(sillyconerobot)) // borgs in faction are friendly continue - if((ROLE_SYNDICATE in faction) && sillyconerobot.emagged) // special case: emagged station borgs are friendly to syndicate turrets + if(has_faction(ROLE_SYNDICATE) && sillyconerobot.emagged) // special case: emagged station borgs are friendly to syndicate turrets continue targets += sillyconerobot @@ -610,10 +610,7 @@ DEFINE_BITFIELD(turret_flags, list( return threatcount /obj/machinery/porta_turret/proc/in_faction(mob/target) - for(var/faction1 in faction) - if(faction1 in target.faction) - return TRUE - return FALSE + return faction_check_atom(target) /obj/machinery/porta_turret/proc/target(atom/movable/target) if(target) diff --git a/code/game/objects/items/crab17.dm b/code/game/objects/items/crab17.dm index b2254fa2e65..05d3c8cab59 100644 --- a/code/game/objects/items/crab17.dm +++ b/code/game/objects/items/crab17.dm @@ -293,12 +293,12 @@ priority_announce("The spacecoin bubble has popped! Get to the credit deposit machine at [get_area(src)] and cash out before you lose all of your funds!", sender_override = "CRAB-17 Protocol") animate(DF, pixel_z = -8, time = 5, , easing = LINEAR_EASING) playsound(src, 'sound/items/weapons/mortar_whistle.ogg', 70, TRUE, 6) - addtimer(CALLBACK(src, PROC_REF(endLaunch)), 5, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation + addtimer(CALLBACK(src, PROC_REF(end_launch)), 5, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation /** * Cleans up after the falling animation. */ -/obj/effect/dumpeet_target/proc/endLaunch() +/obj/effect/dumpeet_target/proc/end_launch() QDEL_NULL(DF) //Delete the falling machine effect, because at this point its animation is over. We dont use temp_visual because we want to manually delete it as soon as the pod appears playsound(src, SFX_EXPLOSION, 80, TRUE) dump.forceMove(get_turf(src)) diff --git a/code/game/objects/items/dehy_carp.dm b/code/game/objects/items/dehy_carp.dm index 71c9211d28e..8d47b9e891b 100644 --- a/code/game/objects/items/dehy_carp.dm +++ b/code/game/objects/items/dehy_carp.dm @@ -60,7 +60,7 @@ var/mob/living/spawned_mob = new mobtype(get_turf(src), owner) //Make carp non-hostile to user if(owner) - spawned_mob.faction = list("[REF(owner)]") + spawned_mob.set_allies(list("[REF(owner)]")) spawned_mob.grant_language(/datum/language/common, UNDERSTOOD_LANGUAGE, LANGUAGE_ATOM) for(var/mob/living/viewer in viewers(5, get_turf(src))) to_chat(viewer, viewer == owner ? span_notice("The newly grown [spawned_mob.name] looks up at you with friendly eyes.") : span_warning("You have a bad feeling about this.")) diff --git a/code/game/objects/items/devices/aicard_evil.dm b/code/game/objects/items/devices/aicard_evil.dm index 2dc8b15ccb2..d5146c0a54a 100644 --- a/code/game/objects/items/devices/aicard_evil.dm +++ b/code/game/objects/items/devices/aicard_evil.dm @@ -78,7 +78,7 @@ nuke_datum.send_to_spawnpoint = FALSE new_ai.mind.add_antag_datum(nuke_datum, op_datum.nuke_team) LAZYADD(new_ai.mind.special_roles, "Syndicate AI") - new_ai.faction |= ROLE_SYNDICATE + new_ai.add_faction(ROLE_SYNDICATE) // Make it look evil!!! new_ai.hologram_appearance = mutable_appearance('icons/mob/silicon/ai.dmi',"xeno_queen") //good enough diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index b4c9c628c05..2b5e0aaaf34 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -429,7 +429,7 @@ effective or pretty fucking useless. /obj/machinery/porta_turret/syndicate/toolbox/examine(mob/user) . = ..() - if(faction_check(faction, user.faction)) + if(faction_check_atom(user)) . += span_notice("You can repair it by left-clicking with a combat wrench.") . += span_notice("You can fold it by right-clicking with a combat wrench.") @@ -494,7 +494,7 @@ effective or pretty fucking useless. qdel(src) /obj/machinery/porta_turret/syndicate/toolbox/ui_status(mob/user, datum/ui_state/state) - if(faction_check(user.faction, faction)) + if(faction_check_atom(user)) return ..() return UI_CLOSE diff --git a/code/game/objects/items/food/monkeycube.dm b/code/game/objects/items/food/monkeycube.dm index e2f79791817..a6554230f25 100644 --- a/code/game/objects/items/food/monkeycube.dm +++ b/code/game/objects/items/food/monkeycube.dm @@ -32,8 +32,7 @@ var/mob/living/bananas = new spawned_mob(drop_location(), TRUE, spammer) // funny that we pass monkey init args to non-monkey mobs, that's totally a future issue if (!QDELETED(bananas)) ADD_TRAIT(bananas, TRAIT_SPAWNED_MOB, INNATE_TRAIT) - if(faction) - bananas.faction = faction + SET_FACTION_AND_ALLIES_FROM(bananas, src) visible_message(span_notice("[src] expands!")) bananas.log_message("spawned via [src], Last attached mob: [key_name(spammer)].", LOG_ATTACK) diff --git a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm index f7f2ef8f414..ab8e3796f22 100644 --- a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm +++ b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm @@ -397,7 +397,7 @@ if (!proximity || !isliving(punchee)) return NONE var/mob/living/victim = punchee - if (victim.body_position == LYING_DOWN || (!(FACTION_MINING in victim.faction) && !(FACTION_BOSS in victim.faction))) + if (victim.body_position == LYING_DOWN || !victim.has_faction(list(FACTION_MINING, FACTION_BOSS))) return NONE victim.apply_damage(mining_bonus, BRUTE) diff --git a/code/game/objects/items/storage/toolboxes/weapons.dm b/code/game/objects/items/storage/toolboxes/weapons.dm index f7d63848659..e899572e31e 100644 --- a/code/game/objects/items/storage/toolboxes/weapons.dm +++ b/code/game/objects/items/storage/toolboxes/weapons.dm @@ -331,13 +331,14 @@ playsound(src, 'sound/items/tools/drill_use.ogg', 80, TRUE, -1) var/obj/machinery/porta_turret/syndicate/toolbox/turret = new(get_turf(loc)) - set_faction(turret, user) + set_toolbox_faction(turret, user) turret.toolbox = src forceMove(turret) return ITEM_INTERACT_SUCCESS -/obj/item/storage/toolbox/emergency/turret/proc/set_faction(obj/machinery/porta_turret/turret, mob/user) - turret.faction = list("[REF(user)]") +/obj/item/storage/toolbox/emergency/turret/proc/set_toolbox_faction(obj/machinery/porta_turret/turret, mob/user) + turret.set_allies(list("[REF(user)]")) + turret.set_faction(null) -/obj/item/storage/toolbox/emergency/turret/nukie/set_faction(obj/machinery/porta_turret/turret, mob/user) - turret.faction = list(ROLE_SYNDICATE) +/obj/item/storage/toolbox/emergency/turret/nukie/set_toolbox_faction(obj/machinery/porta_turret/turret, mob/user) + turret.set_faction(list(ROLE_SYNDICATE)) diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index f25006bd992..9adea0fa833 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -800,7 +800,7 @@ nuke_datum.send_to_spawnpoint = FALSE nuke_datum.nukeop_outfit = null human_target.mind?.add_antag_datum(nuke_datum) - human_target.faction |= ROLE_SYNDICATE + human_target.add_faction(ROLE_SYNDICATE) to_chat(human_target, span_warning("You are now a nuclear operative. Your main objective, if you were an antagonist and willing, is presumably to assist the nuclear operative team and secure the disk.")) to_chat(human_target, span_userdanger("This implant does NOT, in any way, brainwash you. If you were a normal crew member beforehand, forcibly implanted or otherwise, you are still one and cannot assist the nuclear operatives.")) return TRUE @@ -811,7 +811,7 @@ return FALSE var/mob/living/living_target = target living_target.mind.remove_antag_datum(/datum/antagonist/nukeop) - living_target.faction -= ROLE_SYNDICATE + living_target.remove_faction(ROLE_SYNDICATE) to_chat(target, span_notice("You feel a little less nuclear.")) to_chat(target, span_userdanger("You're no longer identified as a nuclear operative! You are free to follow any valid goals you wish, even continuing to secure the disk. Just make sure neither any turrets nor operatives kill you on sight.")) return TRUE diff --git a/code/game/objects/items/weaponry/melee/soulscythe.dm b/code/game/objects/items/weaponry/melee/soulscythe.dm index 4e00fea5143..35b27736e13 100644 --- a/code/game/objects/items/weaponry/melee/soulscythe.dm +++ b/code/game/objects/items/weaponry/melee/soulscythe.dm @@ -95,7 +95,8 @@ soul.PossessByPlayer(ghost.ckey) soul.copy_languages(master, LANGUAGE_MASTER) //Make sure the sword can understand and communicate with the master. - soul.faction = list("[REF(master)]") + soul.set_allies(list("[REF(master)]")) + soul.set_faction(null) balloon_alert(master, "the scythe glows") add_overlay("soulscythe_gem") density = TRUE @@ -255,7 +256,6 @@ health = 200 gender = NEUTER mob_biotypes = MOB_SPIRIT - faction = list() default_blood_volume = MAX_BLOOD_LEVEL hud_type = /datum/hud/soulscythe spawn_blacklisted = TRUE diff --git a/code/game/objects/items/weaponry/melee/spear.dm b/code/game/objects/items/weaponry/melee/spear.dm index bc6ede60014..3f7b0e1bfd7 100644 --- a/code/game/objects/items/weaponry/melee/spear.dm +++ b/code/game/objects/items/weaponry/melee/spear.dm @@ -272,7 +272,7 @@ improvised_construction = FALSE /obj/item/spear/grey_tide/afterattack(atom/movable/target, mob/living/user, list/modifiers, list/attack_modifiers) - user.faction |= "greytide([REF(user)])" + user.add_ally("greytide([REF(user)])") if(!isliving(target)) return var/mob/living/stabbed = target @@ -280,7 +280,7 @@ return if(stabbed.stat == CONSCIOUS && prob(50)) var/mob/living/basic/illusion/fake_clone = new(user.loc) - fake_clone.full_setup(user, target_mob = stabbed, faction = user.faction, life = 10 SECONDS, hp = user.health / 2.5, damage = 12, replicate = 30) + fake_clone.full_setup(user, target_mob = stabbed, life = 10 SECONDS, hp = user.health / 2.5, damage = 12, replicate = 30) //MILITARY /obj/item/spear/military diff --git a/code/game/objects/structures/petrified_statue.dm b/code/game/objects/structures/petrified_statue.dm index 4e0a76cf09a..73f3ac942f1 100644 --- a/code/game/objects/structures/petrified_statue.dm +++ b/code/game/objects/structures/petrified_statue.dm @@ -29,7 +29,7 @@ living.visible_message(span_warning("[living]'s skin rapidly turns to marble!"), span_userdanger("Your body freezes up! Can't... move... can't... think...")) living.forceMove(src) living.add_traits(list(TRAIT_GODMODE, TRAIT_MUTE, TRAIT_NOBLOOD), STATUE_MUTE) - living.faction |= FACTION_MIMIC //Stops mimics from instaqdeling people in statues + living.add_faction(FACTION_MIMIC) //Stops mimics from instaqdeling people in statues atom_integrity = living.health + 100 //stoning damaged mobs will result in easier to shatter statues max_integrity = atom_integrity START_PROCESSING(SSobj, src) @@ -52,7 +52,7 @@ petrified_mob.remove_traits(list(TRAIT_GODMODE, TRAIT_MUTE, TRAIT_NOBLOOD), STATUE_MUTE) petrified_mob.Paralyze(10 SECONDS) petrified_mob.take_overall_damage((petrified_mob.health - atom_integrity + 100)) //any new damage the statue incurred is transferred to the mob - petrified_mob.faction -= FACTION_MIMIC + petrified_mob.remove_faction(FACTION_MIMIC) petrified_mob = null /obj/structure/statue/petrified/Destroy() diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm index e91c77e5a4c..bf8d713eb14 100644 --- a/code/game/objects/structures/spawner.dm +++ b/code/game/objects/structures/spawner.dm @@ -76,7 +76,7 @@ ) /obj/structure/spawner/attack_animal(mob/living/simple_animal/user, list/modifiers) - if(faction_check(faction, user.faction, FALSE) && !user.client) + if(faction_check_atom(user) && !user.client) return return ..() diff --git a/code/game/objects/structures/toiletbong.dm b/code/game/objects/structures/toiletbong.dm index 4ff8aabe6a7..e4ff9776cea 100644 --- a/code/game/objects/structures/toiletbong.dm +++ b/code/game/objects/structures/toiletbong.dm @@ -69,7 +69,7 @@ user.adjust_disgust(50) user.vomit(VOMIT_CATEGORY_DEFAULT) var/mob/living/spawned_mob = new /mob/living/basic/mouse(get_turf(user)) - spawned_mob.faction |= "[REF(user)]" + spawned_mob.add_faction("[REF(user)]") if(prob(50)) for(var/j in 1 to rand(1, 3)) step(spawned_mob, pick(NORTH,SOUTH,EAST,WEST)) diff --git a/code/modules/antagonists/abductor/equipment/glands/slime.dm b/code/modules/antagonists/abductor/equipment/glands/slime.dm index 252afdaa45e..646eb691797 100644 --- a/code/modules/antagonists/abductor/equipment/glands/slime.dm +++ b/code/modules/antagonists/abductor/equipment/glands/slime.dm @@ -9,12 +9,12 @@ /obj/item/organ/heart/gland/slime/on_mob_insert(mob/living/carbon/gland_owner) . = ..() - gland_owner.faction |= FACTION_SLIME + gland_owner.add_faction(FACTION_SLIME) gland_owner.grant_language(/datum/language/slime, source = LANGUAGE_GLAND) /obj/item/organ/heart/gland/slime/on_mob_remove(mob/living/carbon/gland_owner) . = ..() - gland_owner.faction -= FACTION_SLIME + gland_owner.remove_faction(FACTION_SLIME) gland_owner.remove_language(/datum/language/slime, source = LANGUAGE_GLAND) /obj/item/organ/heart/gland/slime/activate() diff --git a/code/modules/antagonists/abductor/equipment/glands/spider.dm b/code/modules/antagonists/abductor/equipment/glands/spider.dm index 44150d9ed80..8b9efc50e6b 100644 --- a/code/modules/antagonists/abductor/equipment/glands/spider.dm +++ b/code/modules/antagonists/abductor/equipment/glands/spider.dm @@ -9,6 +9,6 @@ /obj/item/organ/heart/gland/spiderman/activate() to_chat(owner, span_warning("You feel something crawling in your skin.")) - owner.faction |= FACTION_SPIDER + owner.add_faction(FACTION_SPIDER) var/mob/living/basic/spider/growing/spiderling/spider = new(owner.drop_location()) spider.directive = "Protect your nest inside [owner.real_name]." diff --git a/code/modules/antagonists/ashwalker/ashwalker.dm b/code/modules/antagonists/ashwalker/ashwalker.dm index 8aac0654c11..b25dac73057 100644 --- a/code/modules/antagonists/ashwalker/ashwalker.dm +++ b/code/modules/antagonists/ashwalker/ashwalker.dm @@ -27,16 +27,14 @@ . = ..() RegisterSignal(owner.current, COMSIG_MOB_EXAMINATE, PROC_REF(on_examinate)) owner.teach_crafting_recipe(/datum/crafting_recipe/skeleton_key) - if(FACTION_NEUTRAL in owner.current.faction) - owner.current.faction.Remove(FACTION_NEUTRAL) // ashwalkers aren't neutral; they're ashwalker-aligned + owner.current.remove_faction(FACTION_NEUTRAL) // ashwalkers aren't neutral; they're ashwalker-aligned /datum/antagonist/ashwalker/on_removal() . = ..() if(!owner.current) return UnregisterSignal(owner.current, COMSIG_MOB_EXAMINATE) - if(!(FACTION_NEUTRAL in owner.current.faction)) - owner.current.faction.Add(FACTION_NEUTRAL) + owner.current.add_faction(FACTION_NEUTRAL) /datum/antagonist/ashwalker/proc/on_examinate(datum/source, atom/A) SIGNAL_HANDLER diff --git a/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm b/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm index 26131c837c2..117d303d6a7 100644 --- a/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm +++ b/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm @@ -22,7 +22,7 @@ var/obj/effect/temp_visual/explosion/fast/effect = new /obj/effect/temp_visual/explosion/fast(get_turf(dead_spore)) effect.alpha = 150 for(var/mob/living/actor in orange(get_turf(dead_spore), death_cloud_size)) - if(ROLE_BLOB in actor.faction) // No friendly fire + if(actor.has_faction(ROLE_BLOB)) // No friendly fire continue //increases damage to mobs if death_cloud_size is increased, but the damage falls off with distance. var/damage_total = (10 + 10 * death_cloud_size) / max(1, get_dist(get_turf(dead_spore), get_turf(actor))) @@ -59,7 +59,7 @@ exposed_mob.take_overall_damage(brute_loss, burn_loss) for(var/mob/living/nearby_mob in orange(epicenter_turf, 1)) - if(ROLE_BLOB in nearby_mob.faction) // No friendly fire. + if(nearby_mob.has_faction(ROLE_BLOB)) // No friendly fire. continue if(nearby_mob == exposed_mob) // We've already hit the epicenter mob continue diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index a5ee1697a3b..2fc737cb365 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -240,7 +240,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) if(!(blob_area.area_flags & BLOBS_ALLOWED)) continue - if(!(ROLE_BLOB in live_guy.faction)) + if(!live_guy.has_faction(ROLE_BLOB)) playsound(live_guy, 'sound/effects/splat.ogg', 50, TRUE) if(live_guy.stat != DEAD) live_guy.investigate_log("has died from blob takeover.", INVESTIGATE_DEATHS) diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm index 593cd4ebc6f..bafcd778401 100644 --- a/code/modules/antagonists/blob/powers.dm +++ b/code/modules/antagonists/blob/powers.dm @@ -52,14 +52,14 @@ /** Checks proximity for mobs */ /mob/eye/blob/proc/check_core_visibility() for(var/mob/living/player in range(7, src)) - if(ROLE_BLOB in player.faction) + if(player.has_faction(ROLE_BLOB)) continue if(player.client) to_chat(src, span_warning("There is someone too close to place your blob core!")) return FALSE for(var/mob/living/player in view(13, src)) - if(ROLE_BLOB in player.faction) + if(player.has_faction(ROLE_BLOB)) continue if(player.client) to_chat(src, span_warning("Someone could see your blob core from here!")) @@ -295,7 +295,7 @@ for(var/mob/living/player in tile) if(!player.can_blob_attack()) continue - if(ROLE_BLOB in player.faction) //no friendly/dead fire + if(player.has_faction(ROLE_BLOB)) //no friendly/dead fire continue if(player.stat != DEAD) attack_success = TRUE diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index 34f9989f80c..418a6615447 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -274,7 +274,7 @@ /obj/structure/blob/attack_animal(mob/living/simple_animal/user, list/modifiers) - if(ROLE_BLOB in user.faction) //sorry, but you can't kill the blob as a blobbernaut + if(user.has_faction(ROLE_BLOB)) //sorry, but you can't kill the blob as a blobbernaut return ..() diff --git a/code/modules/antagonists/blood_worm/blood_worm_antag.dm b/code/modules/antagonists/blood_worm/blood_worm_antag.dm index fc8206ffdfd..16b4a56fdd7 100644 --- a/code/modules/antagonists/blood_worm/blood_worm_antag.dm +++ b/code/modules/antagonists/blood_worm/blood_worm_antag.dm @@ -52,7 +52,7 @@ add_team_hud(target) if (!istype(target, /mob/living/basic/blood_worm)) - target.faction |= FACTION_BLOOD_WORM + target.add_faction(FACTION_BLOOD_WORM) // Apathy and fearlessness are traits inherent to the very mind of a blood worm. // Being immune to hunger, withdrawals, etc. are physical traits of blood worm hosts. @@ -62,7 +62,7 @@ var/mob/living/target = mob_override || owner.current if (!istype(target, /mob/living/basic/blood_worm)) - target.faction -= FACTION_BLOOD_WORM + target.remove_faction(FACTION_BLOOD_WORM) REMOVE_TRAITS_IN(target, REF(src)) diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index 5747a2b6fa0..20c4b7e220d 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -692,7 +692,8 @@ spawns = 1 for(var/i in 1 to spawns) var/mob/living/basic/summoned_minion = new spawn_type(owner.drop_location()) - summoned_minion.faction = list("[REF(owner)]") + summoned_minion.set_allies(list("[REF(owner)]")) + summoned_minion.set_faction(null) minion_additional_changes(summoned_minion) ///Our tell that we're using this ability. Usually a sound and a visible message.area diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 93dfabbfc72..017dbf49d6e 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -1103,7 +1103,7 @@ Striking a noncultist, however, will tear their flesh."} if(!IS_CULTIST(owner)) if(prob(50)) var/mob/living/basic/illusion/bizarro = new(owner.loc) - bizarro.full_setup(owner, target_mob = owner, faction = list(FACTION_CULT), life = 10 SECONDS, damage = 20, replicate = 5) + bizarro.full_setup(owner, target_mob = owner, faction_override = list(FACTION_CULT), life = 10 SECONDS, damage = 20, replicate = 5) to_chat(owner, span_bolddanger("You're betrayed by \"yourself\"!")) return FALSE @@ -1131,11 +1131,11 @@ Striking a noncultist, however, will tear their flesh."} addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/item/shield/mirror, readd)), 45 SECONDS) if(prob(60)) // make a potentially slower, but replicable apparation var/mob/living/basic/illusion/apparation = new(owner.loc) - apparation.full_setup(owner, target_mob = null, faction = list(FACTION_CULT), life = 7 SECONDS, damage = 10, replicate = 5) + apparation.full_setup(owner, target_mob = null, faction_override = list(FACTION_CULT), life = 7 SECONDS, damage = 10, replicate = 5) apparation.cached_multiplicative_slowdown = owner.cached_multiplicative_slowdown else // normal apparation designed to escape var/mob/living/basic/illusion/escape/decoy = new(owner.loc) - decoy.full_setup(owner, target_mob = owner, faction = list(FACTION_CULT), life = 7 SECONDS, damage = 10) // Damage for retaliation + decoy.full_setup(owner, target_mob = owner, faction_override = list(FACTION_CULT), life = 7 SECONDS, damage = 10) // Damage for retaliation return TRUE diff --git a/code/modules/antagonists/cult/datums/cultist.dm b/code/modules/antagonists/cult/datums/cultist.dm index 55f0f61d97a..9ce4dc5b13a 100644 --- a/code/modules/antagonists/cult/datums/cultist.dm +++ b/code/modules/antagonists/cult/datums/cultist.dm @@ -56,7 +56,7 @@ . = ..() var/mob/living/current = owner.current || mob_override handle_clown_mutation(current, mob_override ? null : "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - current.faction |= FACTION_CULT + current.add_faction(FACTION_CULT) current.grant_language(/datum/language/narsie, source = LANGUAGE_CULTIST) current.throw_alert("bloodsense", /atom/movable/screen/alert/bloodsense) @@ -76,7 +76,7 @@ . = ..() var/mob/living/current = owner.current || mob_override handle_clown_mutation(current, removing = FALSE) - current.faction -= FACTION_CULT + current.remove_faction(FACTION_CULT) current.remove_language(/datum/language/narsie, source = LANGUAGE_CULTIST) current.clear_alert("bloodsense") diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm index eed1f6d2e9e..a34ef8418dd 100644 --- a/code/modules/antagonists/heretic/heretic_antag.dm +++ b/code/modules/antagonists/heretic/heretic_antag.dm @@ -376,7 +376,7 @@ /datum/antagonist/heretic/apply_innate_effects(mob/living/mob_override) var/mob/living/our_mob = mob_override || owner.current handle_clown_mutation(our_mob, "Ancient knowledge described to you has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - our_mob.faction |= FACTION_HERETIC + our_mob.add_faction(FACTION_HERETIC) if(!issilicon(our_mob)) GLOB.reality_smash_track.add_tracked_mind(owner) @@ -397,7 +397,7 @@ /datum/antagonist/heretic/remove_innate_effects(mob/living/mob_override) var/mob/living/our_mob = mob_override || owner.current handle_clown_mutation(our_mob, removing = FALSE) - our_mob.faction -= FACTION_HERETIC + our_mob.remove_faction(FACTION_HERETIC) if(owner in GLOB.reality_smash_track.tracked_heretics) GLOB.reality_smash_track.remove_tracked_mind(owner) diff --git a/code/modules/antagonists/heretic/magic/moon_ringleader.dm b/code/modules/antagonists/heretic/magic/moon_ringleader.dm index 54702b41171..4654dd39ed5 100644 --- a/code/modules/antagonists/heretic/magic/moon_ringleader.dm +++ b/code/modules/antagonists/heretic/magic/moon_ringleader.dm @@ -21,7 +21,7 @@ /datum/action/cooldown/spell/aoe/moon_ringleader/cast(mob/living/caster) new moon_effect(get_turf(caster)) - caster.faction |= "ringleader([REF(caster)])" + caster.add_ally("ringleader([REF(caster)])") return ..() /datum/action/cooldown/spell/aoe/moon_ringleader/get_things_to_cast_on(atom/center, radius_override) @@ -46,7 +46,6 @@ shove_clone.full_setup( caster, target_mob = victim, - faction = caster.faction, life = 30 SECONDS, hp = caster.health, damage = 1, diff --git a/code/modules/antagonists/heretic/moon_lunatic.dm b/code/modules/antagonists/heretic/moon_lunatic.dm index 3d877ee962c..d33ad281a83 100644 --- a/code/modules/antagonists/heretic/moon_lunatic.dm +++ b/code/modules/antagonists/heretic/moon_lunatic.dm @@ -40,7 +40,7 @@ /datum/antagonist/lunatic/apply_innate_effects(mob/living/mob_override) var/mob/living/our_mob = mob_override || owner.current handle_clown_mutation(our_mob, "Ancient knowledge from the moon has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - our_mob.faction |= FACTION_HERETIC + our_mob.add_faction(FACTION_HERETIC) add_team_hud(our_mob, /datum/antagonist/lunatic) ADD_TRAIT(our_mob, TRAIT_MADNESS_IMMUNE, REF(src)) @@ -52,7 +52,7 @@ /datum/antagonist/lunatic/remove_innate_effects(mob/living/mob_override) var/mob/living/our_mob = mob_override || owner.current handle_clown_mutation(our_mob, removing = FALSE) - our_mob.faction -= FACTION_HERETIC + our_mob.remove_faction(FACTION_HERETIC) // Mood event given to moon acolytes /datum/mood_event/heretics/lunatic diff --git a/code/modules/antagonists/heretic/status_effects/ghoul.dm b/code/modules/antagonists/heretic/status_effects/ghoul.dm index 7219b77ac14..74e60c966a4 100644 --- a/code/modules/antagonists/heretic/status_effects/ghoul.dm +++ b/code/modules/antagonists/heretic/status_effects/ghoul.dm @@ -64,7 +64,7 @@ ADD_TRAIT(human_target, TRAIT_HERETIC_SUMMON, TRAIT_STATUS_EFFECT(id)) ADD_TRAIT(human_target, TRAIT_DESENSITIZED, TRAIT_STATUS_EFFECT(id)) human_target.become_husk(TRAIT_STATUS_EFFECT(id)) - human_target.faction |= FACTION_HERETIC + human_target.add_faction(FACTION_HERETIC) if(human_target.mind) var/datum/antagonist/heretic_monster/heretic_monster = human_target.mind.add_antag_datum(/datum/antagonist/heretic_monster) @@ -95,7 +95,7 @@ REMOVE_TRAIT(human_target, TRAIT_HERETIC_SUMMON, TRAIT_STATUS_EFFECT(id)) REMOVE_TRAIT(human_target, TRAIT_DESENSITIZED, TRAIT_STATUS_EFFECT(id)) human_target.cure_husk(TRAIT_STATUS_EFFECT(id)) - human_target.faction -= FACTION_HERETIC + human_target.remove_faction(FACTION_HERETIC) human_target.mind?.remove_antag_datum(/datum/antagonist/heretic_monster) UnregisterSignal(human_target, COMSIG_LIVING_DEATH) diff --git a/code/modules/antagonists/heretic/structures/lock_final.dm b/code/modules/antagonists/heretic/structures/lock_final.dm index 4438e4d6f25..fa4a34d3a78 100644 --- a/code/modules/antagonists/heretic/structures/lock_final.dm +++ b/code/modules/antagonists/heretic/structures/lock_final.dm @@ -79,7 +79,7 @@ var/datum/antagonist/heretic_monster/woohoo_free_antag = new(src) monster.mind.add_antag_datum(woohoo_free_antag) if(ascendee) - monster.faction = ascendee.current.faction + SET_FACTION_AND_ALLIES_FROM(monster, ascendee.current) woohoo_free_antag.set_owner(ascendee) var/datum/objective/kill_all_your_friends = new() kill_all_your_friends.owner = monster.mind diff --git a/code/modules/antagonists/nukeop/outfits.dm b/code/modules/antagonists/nukeop/outfits.dm index a259a869b0b..ec2b63e7413 100644 --- a/code/modules/antagonists/nukeop/outfits.dm +++ b/code/modules/antagonists/nukeop/outfits.dm @@ -62,7 +62,7 @@ weapons_implant.implant(nukie) var/obj/item/implant/explosive/explosive_implant = new/obj/item/implant/explosive(nukie) explosive_implant.implant(nukie) - nukie.faction |= ROLE_SYNDICATE + nukie.add_faction(ROLE_SYNDICATE) nukie.update_icons() /datum/outfit/syndicate/full diff --git a/code/modules/antagonists/pirate/pirate_outfits.dm b/code/modules/antagonists/pirate/pirate_outfits.dm index 5b75e046199..11e0af4bf49 100644 --- a/code/modules/antagonists/pirate/pirate_outfits.dm +++ b/code/modules/antagonists/pirate/pirate_outfits.dm @@ -11,7 +11,7 @@ shoes = /obj/item/clothing/shoes/pirate/armored /datum/outfit/pirate/post_equip(mob/living/carbon/human/equipped) - equipped.faction |= FACTION_PIRATE + equipped.add_faction(FACTION_PIRATE) var/obj/item/radio/outfit_radio = equipped.ears if(outfit_radio) diff --git a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm index 0f980c5e1d2..4cc06387530 100644 --- a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm +++ b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm @@ -423,7 +423,7 @@ /datum/export/pirate/ransom/get_base_cost(mob/living/carbon/human/ransomee) if(ransomee.stat != CONSCIOUS || !ransomee.mind || HAS_TRAIT(ransomee.mind, TRAIT_HAS_BEEN_KIDNAPPED)) //mint condition only return 0 - else if(FACTION_PIRATE in ransomee.faction) //can't ransom your fellow pirates to CentCom! + else if(ransomee.has_faction(FACTION_PIRATE)) //can't ransom your fellow pirates to CentCom! return 0 else if(HAS_TRAIT(ransomee, TRAIT_HIGH_VALUE_RANSOM)) return 3000 diff --git a/code/modules/antagonists/space_dragon/carp_rift.dm b/code/modules/antagonists/space_dragon/carp_rift.dm index 432fba6e7ea..7345de2fcc8 100644 --- a/code/modules/antagonists/space_dragon/carp_rift.dm +++ b/code/modules/antagonists/space_dragon/carp_rift.dm @@ -159,7 +159,7 @@ if(charge_state == CHARGE_COMPLETED) if(SPT_PROB(1.25, seconds_per_tick) && dragon) var/mob/living/newcarp = new dragon.ai_to_spawn(loc) - newcarp.faction = dragon.owner.current.faction.Copy() + newcarp.set_faction(dragon.owner.current.get_faction()) if(SPT_PROB(1.5, seconds_per_tick)) var/rand_dir = pick(GLOB.cardinals) GLOB.move_manager.move_to(src, get_step(src, rand_dir), 1) @@ -258,7 +258,7 @@ if(isnull(dragon)) return var/mob/living/newcarp = new dragon.minion_to_spawn(loc) - newcarp.faction = dragon.owner.current.faction + SET_FACTION_AND_ALLIES_FROM(newcarp, dragon.owner.current) newcarp.AddElement(/datum/element/nerfed_pulling, GLOB.typecache_general_bad_things_to_easily_move) newcarp.AddElement(/datum/element/prevent_attacking_of_types, GLOB.typecache_general_bad_hostile_attack_targets, "this tastes awful!") dragon.wavespeak?.link_mob(newcarp) diff --git a/code/modules/antagonists/space_dragon/space_dragon.dm b/code/modules/antagonists/space_dragon/space_dragon.dm index 034c328cf9e..320015c34bc 100644 --- a/code/modules/antagonists/space_dragon/space_dragon.dm +++ b/code/modules/antagonists/space_dragon/space_dragon.dm @@ -77,7 +77,7 @@ var/mob/living/antag = mob_override || owner.current RegisterSignal(antag, COMSIG_LIVING_LIFE, PROC_REF(rift_checks)) RegisterSignal(antag, COMSIG_LIVING_DEATH, PROC_REF(destroy_rifts)) - antag.faction |= FACTION_CARP + antag.add_faction(FACTION_CARP) // Give the ability over if we have one rift_ability?.Grant(antag) wavespeak = antag.AddComponent( \ @@ -94,7 +94,7 @@ var/mob/living/antag = mob_override || owner.current UnregisterSignal(antag, COMSIG_LIVING_LIFE) UnregisterSignal(antag, COMSIG_LIVING_DEATH) - antag.faction -= FACTION_CARP + antag.remove_faction(FACTION_CARP) rift_ability?.Remove(antag) QDEL_NULL(wavespeak) diff --git a/code/modules/antagonists/traitor/contractor/syndicate_contract.dm b/code/modules/antagonists/traitor/contractor/syndicate_contract.dm index fb1212fb931..42dfb52157c 100644 --- a/code/modules/antagonists/traitor/contractor/syndicate_contract.dm +++ b/code/modules/antagonists/traitor/contractor/syndicate_contract.dm @@ -117,7 +117,7 @@ var/obj/structure/closet/supplypod/extractionpod/pod = source // Handle the pod returning - pod.startExitSequence(pod) + pod.start_exit_sequence(pod) if(ishuman(person_sent)) var/mob/living/carbon/human/target = person_sent diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index 0d587f2343d..e1af2388a7d 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -445,7 +445,7 @@ soulstone_spirit.copy_languages(user, LANGUAGE_MASTER) soulstone_spirit.get_language_holder().omnitongue = TRUE //Grants omnitongue if(user) - soulstone_spirit.faction |= "[REF(user)]" //Add the master as a faction, allowing inter-mob cooperation + soulstone_spirit.add_ally(user) //Add the master as a faction, allowing inter-mob cooperation if(IS_CULTIST(user)) soulstone_spirit.mind.add_antag_datum(/datum/antagonist/cult/shade) SSblackbox.record_feedback("tally", "cult_shade_created", 1) @@ -557,7 +557,7 @@ flick("make_[makeicon][theme]", newstruct) playsound(newstruct, 'sound/effects/constructform.ogg', 50) if(stoner) - newstruct.faction |= "[REF(stoner)]" + newstruct.add_ally(stoner) newstruct.construct_master = stoner var/datum/action/innate/seek_master/seek_master = new seek_master.Grant(newstruct) diff --git a/code/modules/antagonists/wizard/equipment/wiz_robe.dm b/code/modules/antagonists/wizard/equipment/wiz_robe.dm index 9f756be5c59..cae9a388ae0 100644 --- a/code/modules/antagonists/wizard/equipment/wiz_robe.dm +++ b/code/modules/antagonists/wizard/equipment/wiz_robe.dm @@ -299,7 +299,6 @@ playsound(src, 'sound/effects/magic/summon_magic.ogg', 50, TRUE, TRUE) var/mob/living/stickman = new /mob/living/basic/stickman/lesser(get_turf(summoner)) - - stickman.faction |= summoner.faction - FACTION_NEUTRAL //These bad boys shouldn't inherit the neutral faction from the crew + stickman.remove_faction(FACTION_NEUTRAL) //These bad boys shouldn't inherit the neutral faction from the crew COOLDOWN_START(src, summoning_cooldown, 3 SECONDS) diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index f31ae96f050..ce38b05c426 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -49,12 +49,12 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key) /datum/antagonist/wizard_minion/apply_innate_effects(mob/living/mob_override) var/mob/living/current_mob = mob_override || owner.current - current_mob.faction |= ROLE_WIZARD + current_mob.add_faction(ROLE_WIZARD) add_team_hud(current_mob) /datum/antagonist/wizard_minion/remove_innate_effects(mob/living/mob_override) var/mob/living/last_mob = mob_override || owner.current - last_mob.faction -= ROLE_WIZARD + last_mob.remove_faction(ROLE_WIZARD) /datum/antagonist/wizard_minion/on_gain() create_objectives() @@ -235,13 +235,13 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key) /datum/antagonist/wizard/apply_innate_effects(mob/living/mob_override) var/mob/living/wizard_mob = mob_override || owner.current - wizard_mob.faction |= ROLE_WIZARD + wizard_mob.add_faction(ROLE_WIZARD) add_team_hud(wizard_mob) ritual?.Grant(owner.current) /datum/antagonist/wizard/remove_innate_effects(mob/living/mob_override) var/mob/living/wizard_mob = mob_override || owner.current - wizard_mob.faction -= ROLE_WIZARD + wizard_mob.remove_faction(ROLE_WIZARD) if (ritual) ritual.Remove(wizard_mob) UnregisterSignal(ritual, COMSIG_GRAND_RITUAL_FINAL_COMPLETE) diff --git a/code/modules/bitrunning/components/glitch.dm b/code/modules/bitrunning/components/glitch.dm index df42fb4eaf6..420c84b7296 100644 --- a/code/modules/bitrunning/components/glitch.dm +++ b/code/modules/bitrunning/components/glitch.dm @@ -17,8 +17,7 @@ server.remove_threat(owner) // so the server doesn't dust us health_boost = ROUND_UP(server.threat * 0.2) - owner.faction.Cut() - owner.faction += list(ROLE_GLITCH) + owner.set_faction(list(ROLE_GLITCH)) owner.maxHealth = clamp(owner.maxHealth + health_boost, 200, 500) owner.fully_heal() diff --git a/code/modules/bitrunning/components/npc_friendly.dm b/code/modules/bitrunning/components/npc_friendly.dm index 0e15ec60e6f..f76c38b6322 100644 --- a/code/modules/bitrunning/components/npc_friendly.dm +++ b/code/modules/bitrunning/components/npc_friendly.dm @@ -1,7 +1,7 @@ /// Makes a mob friendly with most NPC factions /datum/component/npc_friendly /// The list of factions to add to the player - var/list/npc_factions = list( + var/static/list/npc_factions = list( FACTION_BOSS, FACTION_CARP, FACTION_HIVEBOT, @@ -15,7 +15,7 @@ ROLE_SYNDICATE, ) /// List of factions previously held by the player - var/list/previous_factions = list() + var/list/previous_factions /datum/component/npc_friendly/Initialize() . = ..() @@ -25,13 +25,11 @@ var/mob/living/player = parent - previous_factions.Add(player.faction) - player.faction |= npc_factions + previous_factions = player.get_faction() + player.add_faction(npc_factions) /datum/component/npc_friendly/Destroy(force) - . = ..() - var/mob/living/player = parent - - player.faction.Cut() - player.faction.Add(previous_factions) + if(!QDELETED(parent)) + player.set_faction(previous_factions) + return ..() diff --git a/code/modules/bitrunning/spawners.dm b/code/modules/bitrunning/spawners.dm index 4baa533c104..a7f742d9d42 100644 --- a/code/modules/bitrunning/spawners.dm +++ b/code/modules/bitrunning/spawners.dm @@ -102,4 +102,4 @@ implants = list(/obj/item/implant/weapons_auth) /datum/outfit/virtual_syndicate/post_equip(mob/living/carbon/human/user, visuals_only) - user.faction |= ROLE_SYNDICATE + user.add_faction(ROLE_SYNDICATE) diff --git a/code/modules/bitrunning/virtual_domain/domains/heretic_hunt.dm b/code/modules/bitrunning/virtual_domain/domains/heretic_hunt.dm index 921e9033a18..77a4fcfed60 100644 --- a/code/modules/bitrunning/virtual_domain/domains/heretic_hunt.dm +++ b/code/modules/bitrunning/virtual_domain/domains/heretic_hunt.dm @@ -76,7 +76,7 @@ ADD_TRAIT(user, TRAIT_ACT_AS_HERETIC, INNATE_TRAIT) ADD_TRAIT(user, TRAIT_NO_TELEPORT, INNATE_TRAIT) user.AddElement(/datum/element/rust_healing) - user.faction |= FACTION_HERETIC + user.add_faction(FACTION_HERETIC) // All it does is stand there, only attacks if attacked (Manuel player) /datum/ai_controller/basic_controller/fake_crewman diff --git a/code/modules/capture_the_flag/ctf_game.dm b/code/modules/capture_the_flag/ctf_game.dm index d168881276c..56636f28a73 100644 --- a/code/modules/capture_the_flag/ctf_game.dm +++ b/code/modules/capture_the_flag/ctf_game.dm @@ -166,7 +166,7 @@ ctf_game.add_player(team, player_mob.ckey, player_component) else player_mob.mind.TakeComponent(ctf_player_component) - player_mob.faction += team + player_mob.add_faction(team) player_mob.equipOutfit(chosen_class) player_mob.add_traits(player_traits, CAPTURE_THE_FLAG_TRAIT) return player_mob //used in medisim_game.dm @@ -249,7 +249,7 @@ if(!is_ctf_target(user) && !anyonecanpickup) to_chat(user, span_warning("Non-players shouldn't be moving the flag!")) return - if(team in user.faction) + if(user.has_faction(team)) to_chat(user, span_warning("You can't move your own flag!")) return if(loc == user) @@ -408,7 +408,7 @@ /obj/structure/trap/ctf/trap_effect(mob/living/living) if(!is_ctf_target(living)) return - if(!(src.team in living.faction)) + if(!living.has_faction(team)) to_chat(living, span_bolddanger("Stay out of the enemy spawn!")) living.investigate_log("has died from entering the enemy spawn in CTF.", INVESTIGATE_DEATHS) living.apply_damage(200) //Damage instead of instant death so we trigger the damage signal. diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm index 1961b374a47..f4f28c21ad8 100644 --- a/code/modules/cargo/centcom_podlauncher.dm +++ b/code/modules/cargo/centcom_podlauncher.dm @@ -335,10 +335,10 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a temp_pod.damage = 5000 temp_pod.effectGib = TRUE //Gibs whoever is under the pod when it lands . = TRUE - if("effectName") //Give the supplypod a custom name. Supplypods automatically get their name based on their style (see supplypod/setStyle() proc), so doing this overrides that. + if("effectName") //Give the supplypod a custom name. Supplypods automatically get their name based on their style (see supplypod/set_style() proc), so doing this overrides that. if (temp_pod.adminNamed) //If we're already adminNamed, set the name of the pod back to default temp_pod.adminNamed = FALSE - temp_pod.setStyle(temp_pod.style) //This resets the name of the pod based on its current style (see supplypod/setStyle() proc) + temp_pod.set_style(temp_pod.style) //This resets the name of the pod based on its current style (see supplypod/set_style() proc) return var/nameInput= tgui_input_text(usr, "Enter a custom name", "Custom name", temp_pod.style::name, max_length = MAX_NAME_LEN) if (isnull(nameInput)) @@ -348,7 +348,7 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a return temp_pod.name = nameInput temp_pod.desc = descInput - temp_pod.adminNamed = TRUE //This variable is checked in the supplypod/setStyle() proc + temp_pod.adminNamed = TRUE //This variable is checked in the supplypod/set_style() proc . = TRUE if("effectShrapnel") //Creates a cloud of shrapnel on landing if (temp_pod.effectShrapnel == TRUE) //If already doing custom damage, set back to default (no shrapnel) @@ -524,7 +524,7 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a . = TRUE if("setStyle") var/chosenStyle = params["style"] - temp_pod.setStyle(pod_style_lookup[chosenStyle]) + temp_pod.set_style(pod_style_lookup[chosenStyle]) . = TRUE if("refresh") //Refresh the Pod bay. User should press this if they spawn something new in the centcom bay. Automatically called whenever the user launches a pod refreshBay() @@ -818,7 +818,7 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a temp_pod.delays = dataToLoad["delays"] temp_pod.reverse_delays = dataToLoad["rev_delays"] temp_pod.custom_rev_delay = dataToLoad["custom_rev_delay"] - temp_pod.setStyle(dataToLoad["styleChoice"]) //Style is a variable that keeps track of what the pod is supposed to look like. + temp_pod.set_style(dataToLoad["styleChoice"]) //Style is a variable that keeps track of what the pod is supposed to look like. temp_pod.effectShrapnel = dataToLoad["effectShrapnel"] //If true, creates a cloud of shrapnel of a decided type and magnitude on landing temp_pod.shrapnel_type = text2path(dataToLoad["shrapnelType"]) temp_pod.shrapnel_magnitude = dataToLoad["shrapnelMagnitude"] diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm index db565991cee..c1829cb21cf 100644 --- a/code/modules/cargo/supplypod.dm +++ b/code/modules/cargo/supplypod.dm @@ -1,7 +1,7 @@ //The "pod_landingzone" temp visual is created by anything that "launches" a supplypod. This is what animates the pod and makes the pod forcemove to the station. //------------------------------------SUPPLY POD-------------------------------------// /obj/structure/closet/supplypod - name = "supply pod" //Names and descriptions are normally created with the setStyle() proc during initialization, but we have these default values here as a failsafe + name = "supply pod" //Names and descriptions are normally created with the set_style() proc during initialization, but we have these default values here as a failsafe desc = "A Nanotrasen supply drop pod." icon = 'icons/obj/supplypods.dmi' icon_state = "pod" //This is a common base sprite shared by a number of pods @@ -88,9 +88,9 @@ desc = "A blood-red styled drop pod." specialised = TRUE -/obj/structure/closet/supplypod/podspawn/deathmatch/preOpen() +/obj/structure/closet/supplypod/podspawn/deathmatch/pre_open() for(var/mob/living/critter in contents) - critter.faction = list(FACTION_HOSTILE) //No infighting, but also KILL!! + critter.set_faction(list(FACTION_HOSTILE)) //No infighting, but also KILL!! return ..() /obj/structure/closet/supplypod/extractionpod @@ -165,9 +165,9 @@ forceMove(shippingLane) if (customStyle) style = customStyle - setStyle(style) //Upon initialization, give the supplypod an iconstate, name, and description based on the "style" variable. This system is important for the centcom_podlauncher to function correctly + set_style(style) //Upon initialization, give the supplypod an iconstate, name, and description based on the "style" variable. This system is important for the centcom_podlauncher to function correctly -/obj/structure/closet/supplypod/proc/setStyle(datum/pod_style/chosen_style) //Used to give the sprite an icon state, name, and description. +/obj/structure/closet/supplypod/proc/set_style(datum/pod_style/chosen_style) //Used to give the sprite an icon state, name, and description. style = chosen_style icon_state = chosen_style::icon_state decal = chosen_style::decal_icon @@ -206,7 +206,7 @@ return if(rubble) - . += rubble.getForeground(src) + . += rubble.get_foreground(src) if(ispath(style, /datum/pod_style/seethrough)) for(var/atom/A in contents) @@ -317,7 +317,7 @@ var/turf/return_turf = locate(reverse_dropoff_coords[1], reverse_dropoff_coords[2], reverse_dropoff_coords[3]) new /obj/effect/pod_landingzone(return_turf, src) -/obj/structure/closet/supplypod/proc/preOpen() //Called before the open_pod() proc. Handles anything that occurs right as the pod lands. +/obj/structure/closet/supplypod/proc/pre_open() //Called before the open_pod() proc. Handles anything that occurs right as the pod lands. var/turf/turf_underneath = get_turf(src) var/list/boom = explosionSize resistance_flags = initial(resistance_flags) @@ -386,7 +386,7 @@ return if (opened) //This is to ensure we don't open something that has already been opened return - holder.setOpened() + holder.set_opened() var/turf/turf_underneath = get_turf(holder) //Get the turf of whoever's contents we're talking about if (istype(holder, /mob)) //Allows mobs to assume the role of the holder, meaning we look at the mob's contents rather than the supplypod's contents. Typically by this point the supplypod's contents have already been moved over to the mob's contents var/mob/holder_as_mob = holder @@ -404,20 +404,20 @@ if (broken) //If the pod is opening because it's been destroyed, we end here return if (ispath(style, /datum/pod_style/seethrough)) - startExitSequence(src) + start_exit_sequence(src) else if (reversing) addtimer(CALLBACK(src, PROC_REF(SetReverseIcon)), delays[POD_LEAVING]/2) //Finish up the pod's duties after a certain amount of time if(!stay_after_drop) // Departing should be handled manually - addtimer(CALLBACK(src, PROC_REF(startExitSequence), holder), delays[POD_LEAVING]*(4/5)) //Finish up the pod's duties after a certain amount of time + addtimer(CALLBACK(src, PROC_REF(start_exit_sequence), holder), delays[POD_LEAVING]*(4/5)) //Finish up the pod's duties after a certain amount of time -/obj/structure/closet/supplypod/proc/startExitSequence(atom/movable/holder) +/obj/structure/closet/supplypod/proc/start_exit_sequence(atom/movable/holder) if (leavingSound) playsound(get_turf(holder), leavingSound, soundVolume, FALSE, FALSE) if (reversing) //If we're reversing, we call the close proc. This sends the pod back up to centcom close(holder) else if (bluespace) //If we're a bluespace pod, then delete ourselves (along with our holder, if a separate holder exists) - deleteRubble() + delete_rubble() if (!effectQuiet && create_sparks && !ispath(style, /datum/pod_style/invisible) && !ispath(style, /datum/pod_style/seethrough)) do_sparks(5, TRUE, holder) //Create some sparks right before closing qdel(src) //Delete ourselves and the holder @@ -430,8 +430,8 @@ take_contents(holder) if (close_sound) playsound(holder, close_sound, soundVolume*0.75, TRUE, -3) - holder.setClosed() - addtimer(CALLBACK(src, PROC_REF(preReturn), holder), delays[POD_LEAVING] * 0.2) //Start to leave a bit after closing for cinematic effect + holder.set_closed() + addtimer(CALLBACK(src, PROC_REF(pre_return), holder), delays[POD_LEAVING] * 0.2) //Start to leave a bit after closing for cinematic effect /obj/structure/closet/supplypod/take_contents(atom/movable/holder) var/turf/turf_underneath = holder.drop_location() @@ -506,38 +506,38 @@ return FALSE return TRUE -/obj/structure/closet/supplypod/proc/preReturn(atom/movable/holder) - deleteRubble() +/obj/structure/closet/supplypod/proc/pre_return(atom/movable/holder) + delete_rubble() animate(holder, alpha = 0, time = 8, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_PARALLEL) animate(holder, pixel_z = 400, time = 10, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_PARALLEL) //Animate our rising pod addtimer(CALLBACK(src, PROC_REF(handleReturnAfterDeparting), holder), 15) //Finish up the pod's duties after a certain amount of time -/obj/structure/closet/supplypod/extractionpod/preReturn(atom/movable/holder) +/obj/structure/closet/supplypod/extractionpod/pre_return(atom/movable/holder) // Double ensure we're loaded, this SHOULD be here by now but you never know SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NINJA_HOLDING_FACILITY) var/turf/picked_turf = pick(GLOB.holdingfacility) reverse_dropoff_coords = list(picked_turf.x, picked_turf.y, picked_turf.z) return ..() -/obj/structure/closet/supplypod/setOpened() //Proc exists here, as well as in any atom that can assume the role of a "holder" of a supplypod. Check the open_pod() proc for more details +/obj/structure/closet/supplypod/set_opened() //Proc exists here, as well as in any atom that can assume the role of a "holder" of a supplypod. Check the open_pod() proc for more details opened = TRUE set_density(FALSE) update_appearance() after_open(null, FALSE) -/obj/structure/closet/supplypod/extractionpod/setOpened() +/obj/structure/closet/supplypod/extractionpod/set_opened() opened = TRUE set_density(TRUE) update_appearance() after_open(null, FALSE) -/obj/structure/closet/supplypod/setClosed() //Ditto +/obj/structure/closet/supplypod/set_closed() //Ditto opened = FALSE set_density(TRUE) update_appearance() after_close(null, FALSE) -/obj/structure/closet/supplypod/proc/tryMakeRubble(turf/T) //Ditto +/obj/structure/closet/supplypod/proc/try_make_rubble(turf/T) //Ditto if (rubble_type == RUBBLE_NONE) return if (rubble) @@ -547,19 +547,19 @@ if (isspaceturf(T) || isclosedturf(T)) return rubble = new /obj/effect/supplypod_rubble(T) - rubble.setStyle(rubble_type, src) + rubble.set_style(rubble_type, src) update_appearance() /obj/structure/closet/supplypod/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) - deleteRubble() + delete_rubble() return ..() -/obj/structure/closet/supplypod/proc/deleteRubble() - rubble?.fadeAway() +/obj/structure/closet/supplypod/proc/delete_rubble() + rubble?.fade_away() rubble = null update_appearance() -/obj/structure/closet/supplypod/proc/addGlow() +/obj/structure/closet/supplypod/proc/add_glow() if (style::shape != POD_SHAPE_NORMAL) return glow_effect = new(src) @@ -576,11 +576,11 @@ if(glow_effect) SET_PLANE_EXPLICIT(glow_effect, ABOVE_GAME_PLANE, src) -/obj/structure/closet/supplypod/proc/endGlow() +/obj/structure/closet/supplypod/proc/end_glow() if(!glow_effect) return glow_effect.layer = LOW_ITEM_LAYER - glow_effect.fadeAway(delays[POD_OPENING]) + glow_effect.fade_away(delays[POD_OPENING]) //Trust the signals /obj/structure/closet/supplypod/proc/remove_glow() @@ -589,8 +589,8 @@ vis_contents -= glow_effect glow_effect = null -/obj/structure/closet/supplypod/Destroy() - deleteRubble() +/obj/structure/closet/supplypod/Destroy(force) + delete_rubble() //Trust the signals even harder qdel(glow_effect) open_pod(src, broken = TRUE) //Lets dump our contents by opening up @@ -616,12 +616,12 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT alpha = 255 -/obj/effect/engineglow/proc/fadeAway(leaveTime) +/obj/effect/engineglow/proc/fade_away(leaveTime) var/duration = min(leaveTime, 25) animate(src, alpha=0, time = duration) QDEL_IN(src, duration + 5) -/obj/effect/supplypod_smoke/proc/drawSelf(amount) +/obj/effect/supplypod_smoke/proc/draw_self(amount) alpha = max(0, 255-(amount*20)) /obj/effect/supplypod_rubble @@ -635,17 +635,17 @@ var/foreground = "rubble_fg" var/verticle_offset = 0 -/obj/effect/supplypod_rubble/proc/getForeground(obj/structure/closet/supplypod/pod) +/obj/effect/supplypod_rubble/proc/get_foreground(obj/structure/closet/supplypod/pod) var/mutable_appearance/rubble_overlay = mutable_appearance('icons/obj/supplypods.dmi', foreground) rubble_overlay.appearance_flags = KEEP_APART|RESET_TRANSFORM rubble_overlay.transform = matrix().Translate(SUPPLYPOD_X_OFFSET - pod.pixel_x, verticle_offset) return rubble_overlay -/obj/effect/supplypod_rubble/proc/fadeAway() +/obj/effect/supplypod_rubble/proc/fade_away() animate(src, alpha=0, time = 30) QDEL_IN(src, 35) -/obj/effect/supplypod_rubble/proc/setStyle(type, obj/structure/closet/supplypod/pod) +/obj/effect/supplypod_rubble/proc/set_style(type, obj/structure/closet/supplypod/pod) if (type == RUBBLE_WIDE) icon_state += "_wide" foreground += "_wide" @@ -729,14 +729,14 @@ var/soundStartTime = pod.delays[POD_TRANSIT] - pod.fallingSoundLength + pod.delays[POD_FALLING] if (soundStartTime < 0) soundStartTime = 1 - addtimer(CALLBACK(src, PROC_REF(playFallingSound)), soundStartTime) - addtimer(CALLBACK(src, PROC_REF(beginLaunch), pod.effectCircle), pod.delays[POD_TRANSIT]) + addtimer(CALLBACK(src, PROC_REF(play_falling_sound)), soundStartTime) + addtimer(CALLBACK(src, PROC_REF(begin_launch), pod.effectCircle), pod.delays[POD_TRANSIT]) -/obj/effect/pod_landingzone/proc/playFallingSound() +/obj/effect/pod_landingzone/proc/play_falling_sound() playsound(src, pod.fallingSound, pod.soundVolume, TRUE, 6) -/obj/effect/pod_landingzone/proc/beginLaunch(effectCircle) //Begin the animation for the pod falling. The effectCircle param determines whether the pod gets to come in from any descent angle - pod.addGlow() +/obj/effect/pod_landingzone/proc/begin_launch(effectCircle) //Begin the animation for the pod falling. The effectCircle param determines whether the pod gets to come in from any descent angle + pod.add_glow() pod.update_appearance() pod.forceMove(drop_location()) for (var/mob/living/M in pod) //Remember earlier (initialization) when we moved mobs into the pod_landingzone so they wouldnt get lost in nullspace? Time to get them out @@ -745,15 +745,15 @@ pod.pixel_x = cos(angle)*32*length(smoke_effects) //Use some ADVANCED MATHEMATICS to set the animated pod's position to somewhere on the edge of a circle with the center being the pod_landingzone pod.pixel_z = sin(angle)*32*length(smoke_effects) var/rotation = get_pixel_angle(pod.pixel_z, pod.pixel_x) //CUSTOM HOMEBREWED proc that is just arctan with extra steps - setupSmoke(rotation) + setup_smoke(rotation) pod.transform = matrix().Turn(rotation) pod.layer = FLY_LAYER SET_PLANE_EXPLICIT(pod, ABOVE_GAME_PLANE, src) if (!ispath(pod.style, /datum/pod_style/invisible)) animate(pod, pixel_z = -1 * abs(sin(rotation))*4, pixel_x = SUPPLYPOD_X_OFFSET + (sin(rotation) * 20), time = pod.delays[POD_FALLING], easing = LINEAR_EASING) //Make the pod fall! At an angle! - addtimer(CALLBACK(src, PROC_REF(endLaunch)), pod.delays[POD_FALLING], TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation + addtimer(CALLBACK(src, PROC_REF(end_launch)), pod.delays[POD_FALLING], TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation -/obj/effect/pod_landingzone/proc/setupSmoke(rotation) +/obj/effect/pod_landingzone/proc/setup_smoke(rotation) if (ispath(pod.style, /datum/pod_style/invisible) || ispath(pod.style, /datum/pod_style/seethrough)) return var/turf/our_turf = get_turf(drop_location()) @@ -769,25 +769,25 @@ smoke_part.pixel_y = abs(cos(rotation))*32 * i smoke_part.add_filter("smoke_blur", 1, gauss_blur_filter(size = 4)) var/time = (pod.delays[POD_FALLING] / length(smoke_effects))*(length(smoke_effects)-i) - addtimer(CALLBACK(smoke_part, TYPE_PROC_REF(/obj/effect/supplypod_smoke/, drawSelf), i), time, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation + addtimer(CALLBACK(smoke_part, TYPE_PROC_REF(/obj/effect/supplypod_smoke/, draw_self), i), time, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation QDEL_IN(smoke_part, pod.delays[POD_FALLING] + 35) -/obj/effect/pod_landingzone/proc/drawSmoke() +/obj/effect/pod_landingzone/proc/draw_smoke() if (ispath(pod.style, /datum/pod_style/invisible) || ispath(pod.style, /datum/pod_style/seethrough)) return for (var/obj/effect/supplypod_smoke/smoke_part in smoke_effects) animate(smoke_part, alpha = 0, time = 20, flags = ANIMATION_PARALLEL) animate(smoke_part.get_filter("smoke_blur"), size = 6, time = 15, easing = CUBIC_EASING|EASE_OUT, flags = ANIMATION_PARALLEL) -/obj/effect/pod_landingzone/proc/endLaunch() +/obj/effect/pod_landingzone/proc/end_launch() var/turf/our_turf = get_turf(drop_location()) - pod.tryMakeRubble(drop_location()) + pod.try_make_rubble(drop_location()) pod.layer = initial(pod.layer) SET_PLANE(pod, initial(pod.plane), our_turf) - pod.endGlow() + pod.end_glow() QDEL_NULL(helper) - pod.preOpen() //Begin supplypod open procedures. Here effects like explosions, damage, and other dangerous (and potentially admin-caused, if the centcom_podlauncher datum was used) memes will take place - drawSmoke() + pod.pre_open() //Begin supplypod open procedures. Here effects like explosions, damage, and other dangerous (and potentially admin-caused, if the centcom_podlauncher datum was used) memes will take place + draw_smoke() qdel(src) //The pod_landingzone's purpose is complete. It can rest easy now //------------------------------------UPGRADES-------------------------------------// diff --git a/code/modules/cargo/supplypod_beacon.dm b/code/modules/cargo/supplypod_beacon.dm index 9c74037e080..f3258f57634 100644 --- a/code/modules/cargo/supplypod_beacon.dm +++ b/code/modules/cargo/supplypod_beacon.dm @@ -35,7 +35,7 @@ launched = TRUE playsound(src,'sound/machines/beep/triple_beep.ogg',50,FALSE) playsound(src,'sound/machines/warning-buzzer.ogg',50,FALSE) - addtimer(CALLBACK(src, PROC_REF(endLaunch)), 33)//wait 3.3 seconds (time it takes for supplypod to land), then update icon + addtimer(CALLBACK(src, PROC_REF(end_launch)), 33)//wait 3.3 seconds (time it takes for supplypod to land), then update icon if (SP_UNLINK) linked = FALSE playsound(src,'sound/machines/synth/synth_no.ogg',50,FALSE) @@ -55,7 +55,7 @@ . += "sp_orange" return -/obj/item/supplypod_beacon/proc/endLaunch() +/obj/item/supplypod_beacon/proc/end_launch() launched = FALSE update_status() diff --git a/code/modules/clothing/neck/horrific_necktie.dm b/code/modules/clothing/neck/horrific_necktie.dm index 6170bae31cc..bb96be364d7 100644 --- a/code/modules/clothing/neck/horrific_necktie.dm +++ b/code/modules/clothing/neck/horrific_necktie.dm @@ -117,7 +117,6 @@ name = "horrific necktie" gender = NEUTER mob_biotypes = MOB_SPIRIT - faction = list() unsuitable_cold_damage = 0 unsuitable_heat_damage = 0 unsuitable_atmos_damage = 0 diff --git a/code/modules/clothing/outfits/vr.dm b/code/modules/clothing/outfits/vr.dm index 740944dd987..654887b11d5 100644 --- a/code/modules/clothing/outfits/vr.dm +++ b/code/modules/clothing/outfits/vr.dm @@ -32,7 +32,7 @@ W.implant(H) var/obj/item/implant/explosive/E = new/obj/item/implant/explosive(H) E.implant(H) - H.faction |= ROLE_SYNDICATE + H.add_faction(ROLE_SYNDICATE) H.update_icons() /obj/item/paper/fluff/vr/fluke_ops diff --git a/code/modules/clothing/suits/costume.dm b/code/modules/clothing/suits/costume.dm index 14a2bbeec78..f497b5d701b 100644 --- a/code/modules/clothing/suits/costume.dm +++ b/code/modules/clothing/suits/costume.dm @@ -301,12 +301,12 @@ /obj/item/clothing/head/hooded/carp_hood/equipped(mob/living/carbon/human/user, slot) ..() if (slot & ITEM_SLOT_HEAD) - user.faction |= "carp" + user.add_faction("carp") /obj/item/clothing/head/hooded/carp_hood/dropped(mob/living/carbon/human/user) ..() if (user.head == src) - user.faction -= "carp" + user.remove_faction("carp") /obj/item/clothing/suit/hooded/carp_costume/spaceproof name = "carp space suit" @@ -724,7 +724,7 @@ full_suit = FALSE var/mob/living/carbon/human/human_user = user UnregisterSignal(human_user.head, COMSIG_ITEM_DROPPED) - user.faction -= FACTION_BEAR + user.remove_faction(FACTION_BEAR) /obj/item/clothing/suit/costume/bear_suit/proc/make_friendly(mob/living/carbon/human/human_user, obj/item/clothing/head/costume/bearpelt/bear_head) if(!istype(human_user)) @@ -733,10 +733,10 @@ return RegisterSignal(bear_head, COMSIG_ITEM_DROPPED, PROC_REF(helmet_drop)) full_suit = TRUE - human_user.faction |= FACTION_BEAR + human_user.add_faction(FACTION_BEAR) /obj/item/clothing/suit/costume/bear_suit/proc/helmet_drop(datum/source, mob/living/user) SIGNAL_HANDLER UnregisterSignal(source, COMSIG_ITEM_DROPPED) full_suit = FALSE - user.faction -= FACTION_BEAR + user.remove_faction(FACTION_BEAR) diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm index d6d28df30d5..e74144abedc 100644 --- a/code/modules/clothing/suits/reactive_armour.dm +++ b/code/modules/clothing/suits/reactive_armour.dm @@ -197,7 +197,6 @@ decoy.full_setup( owner, target_mob = owner, - faction = owner.faction, life = 5 SECONDS, hp = owner.health / 4, damage = 5, diff --git a/code/modules/events/space_vines/vine_controller.dm b/code/modules/events/space_vines/vine_controller.dm index c80358929e3..119e9f86235 100644 --- a/code/modules/events/space_vines/vine_controller.dm +++ b/code/modules/events/space_vines/vine_controller.dm @@ -163,6 +163,6 @@ GLOBAL_LIST_INIT(vine_mutations_list, init_vine_mutation_list()) /proc/isvineimmune(atom/target) if(isliving(target)) var/mob/living/victim = target - if((FACTION_VINES in victim.faction) || (FACTION_PLANTS in victim.faction)) + if(victim.has_faction(FACTION_VINES, FACTION_PLANTS)) return TRUE return FALSE diff --git a/code/modules/events/stray_cargo.dm b/code/modules/events/stray_cargo.dm index 8d589ea1c72..a3f851f3acf 100644 --- a/code/modules/events/stray_cargo.dm +++ b/code/modules/events/stray_cargo.dm @@ -189,5 +189,5 @@ ///Apply the syndicate pod skin /datum/round_event/stray_cargo/syndicate/make_pod() var/obj/structure/closet/supplypod/S = new - S.setStyle(/datum/pod_style/syndicate) + S.set_style(/datum/pod_style/syndicate) return S diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index 129d090e9fe..7c79f6b79ef 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -197,7 +197,7 @@ podman.PossessByPlayer(ckey_holder) podman.gender = blood_gender - podman.faction |= factions + podman.add_faction(factions) features[FEATURE_MUTANT_COLOR] ||= "#59CE00" features[FEATURE_POD_HAIR] ||= pick(SSaccessories.feature_list[FEATURE_POD_HAIR]) diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index e353a1683c7..104c4e4384c 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -1103,7 +1103,7 @@ var/list/livingplants = list(/mob/living/basic/tree, /mob/living/basic/killer_tomato) var/chosen = pick(livingplants) var/mob/living/C = new chosen(get_turf(src)) - C.faction = list(FACTION_PLANTS) + C.set_faction(list(FACTION_PLANTS)) /// Plants the seed / graft into the tray and resets growth related stats such as maturity on the tray. /obj/machinery/hydroponics/proc/propagate_plant(obj/item/seeds/young_plant, mob/living/user) diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm index b3e242d2e1f..89ef4b24f0f 100644 --- a/code/modules/jobs/access.dm +++ b/code/modules/jobs/access.dm @@ -24,7 +24,7 @@ return TRUE if(HAS_SILICON_ACCESS(accessor)) - if(!(ROLE_SYNDICATE in accessor.faction)) + if(!(accessor.has_faction(ROLE_SYNDICATE))) if((ACCESS_SYNDICATE in req_access) || (ACCESS_SYNDICATE_LEADER in req_access) || (ACCESS_SYNDICATE in req_one_access) || (ACCESS_SYNDICATE_LEADER in req_one_access)) return FALSE if(onSyndieBase() && loc != accessor) diff --git a/code/modules/jobs/job_types/clown.dm b/code/modules/jobs/job_types/clown.dm index a28bfea710b..453216d2df1 100644 --- a/code/modules/jobs/job_types/clown.dm +++ b/code/modules/jobs/job_types/clown.dm @@ -101,4 +101,4 @@ H.fully_replace_character_name(H.real_name, pick(GLOB.clown_names)) //rename the mob AFTER they're equipped so their ID gets updated properly. H.dna.add_mutation(/datum/mutation/clumsy, MUTATION_SOURCE_CLOWN_CLUMSINESS) ADD_TRAIT(H, TRAIT_CLOWN_ENJOYER, INNATE_TRAIT) - H.faction |= FACTION_CLOWN + H.add_faction(FACTION_CLOWN) diff --git a/code/modules/jobs/job_types/station_trait/human_ai.dm b/code/modules/jobs/job_types/station_trait/human_ai.dm index 8a59d55f49d..2e9baf58d96 100644 --- a/code/modules/jobs/job_types/station_trait/human_ai.dm +++ b/code/modules/jobs/job_types/station_trait/human_ai.dm @@ -131,7 +131,7 @@ cybernetic.Insert(equipped, special = TRUE, movement_flags = DELETE_IF_REPLACED) //you only get respect if you go all the way, man. ADD_TRAIT(equipped, TRAIT_COMMISSIONED, INNATE_TRAIT) - equipped.faction |= list(FACTION_SILICON, FACTION_TURRET) + equipped.add_faction(list(FACTION_SILICON, FACTION_TURRET)) /obj/item/paper/default_lawset_list name = "Lawset Note" diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/watcher_grave.dm b/code/modules/mapfluff/ruins/lavalandruin_code/watcher_grave.dm index d25581bd3f3..27d83a9e042 100644 --- a/code/modules/mapfluff/ruins/lavalandruin_code/watcher_grave.dm +++ b/code/modules/mapfluff/ruins/lavalandruin_code/watcher_grave.dm @@ -165,6 +165,8 @@ /obj/effect/watcher_orbiter/Initialize(mapload) . = ..() + if(LAZYLEN(target_faction)) + target_faction = string_list(target_faction) START_PROCESSING(SSobj, src) // Shuttle rotation fucks with our position, we just want to stick with our guy @@ -182,7 +184,7 @@ for (var/mob/living/potential_target in oview(5, src)) if (!ismining(potential_target) || potential_target.stat == DEAD) continue - if (!faction_check(target_faction, potential_target.faction)) + if (!potential_target.has_faction(target_faction)) continue shoot_at(potential_target) return diff --git a/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm b/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm index c8bc6404fdb..9b6b6561aff 100644 --- a/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm +++ b/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm @@ -231,7 +231,7 @@ for(var/i in 1 to summon_amount) var/turf/drop_off = find_dropoff_turf(target, user) var/mob/living/basic/mining/demon_afterimage/crusher/friend = new(drop_off) - friend.faction = list(FACTION_NEUTRAL) + friend.set_faction(list(FACTION_NEUTRAL)) friend.befriend(user) friend.ai_controller?.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, target) COOLDOWN_START(src, summon_cooldown, 30 SECONDS) diff --git a/code/modules/mining/lavaland/mining_loot/megafauna/blood_drunk.dm b/code/modules/mining/lavaland/mining_loot/megafauna/blood_drunk.dm index 7791cdce339..74d7267e465 100644 --- a/code/modules/mining/lavaland/mining_loot/megafauna/blood_drunk.dm +++ b/code/modules/mining/lavaland/mining_loot/megafauna/blood_drunk.dm @@ -66,7 +66,7 @@ /obj/item/melee/cleaving_saw/attack(mob/living/target, mob/living/carbon/human/user, list/modifiers, list/attack_modifiers) var/is_open = HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE) if(!is_open || swiping || !target.density || get_turf(target) == get_turf(user)) - for(var/found_faction in target.faction) + for(var/found_faction in target.get_faction()) if(!(found_faction in nemesis_factions)) continue if(is_open) diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm index d8a333ca49f..8bffeaed85c 100644 --- a/code/modules/mob/dead/dead.dm +++ b/code/modules/mob/dead/dead.dm @@ -13,6 +13,8 @@ INITIALIZE_IMMEDIATE(/mob/dead) if(flags_1 & INITIALIZED_1) stack_trace("Warning: [src]([type]) initialized multiple times!") flags_1 |= INITIALIZED_1 + if(LAZYLEN(faction)) + faction = string_list(faction) // Initial is non standard here, but ghosts move before they get here so it's needed. this is a cold path too so it's ok SET_PLANE_IMPLICIT(src, initial(plane)) add_to_mob_list() diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 9a184ace5ec..e8e26e5de0a 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -767,7 +767,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return FALSE target.PossessByPlayer(key) - target.faction = list(FACTION_NEUTRAL) + target.set_faction(list(FACTION_NEUTRAL)) return TRUE /mob/dead/observer/_pointed(atom/pointed_at) diff --git a/code/modules/mob/living/basic/blob_minions/blob_spore.dm b/code/modules/mob/living/basic/blob_minions/blob_spore.dm index bee1e255ab1..b123fafc5b0 100644 --- a/code/modules/mob/living/basic/blob_minions/blob_spore.dm +++ b/code/modules/mob/living/basic/blob_minions/blob_spore.dm @@ -53,7 +53,7 @@ visible_message(span_warning("The corpse of [target.name] suddenly rises!")) var/mob/living/basic/blob_minion/zombie/blombie = change_mob_type(zombie_type, loc, new_name = initial(zombie_type.name)) blombie.pass_flags |= PASSBLOB //No way to pass the blob_borne info through change_mob_type() to Initilize(), so we just circumvent it here. - blombie.faction |= faction //inherit the spore's faction in case it was spawned with a different one (eg gold core) + APPLY_FACTION_AND_ALLIES_FROM(blombie, src) //inherit the spore's faction in case it was spawned with a different one (eg gold core) blombie.set_name() if (istype(blombie)) // In case of badmin blombie.consume_corpse(target) diff --git a/code/modules/mob/living/basic/bots/_bots.dm b/code/modules/mob/living/basic/bots/_bots.dm index 740e55d7bc5..40fa7e51dac 100644 --- a/code/modules/mob/living/basic/bots/_bots.dm +++ b/code/modules/mob/living/basic/bots/_bots.dm @@ -102,6 +102,10 @@ GLOBAL_LIST_INIT(command_strings, list( ) ///name of the UI we will attempt to open var/bot_ui = "SimpleBot" + // The faction of the bot before it inherited the pai's faction + var/list/original_faction + // The allies of the bot before it inherited the pai's faction + var/list/original_allies /// If true we will offer this COOLDOWN_DECLARE(offer_ghosts_cooldown) @@ -706,7 +710,9 @@ GLOBAL_LIST_INIT(command_strings, list( paicard.pai.mind.transfer_to(src) to_chat(src, span_notice("You sense your form change as you are uploaded into [src].")) name = paicard.pai.name - faction = user.faction.Copy() + original_faction = get_faction() + original_allies = allies + SET_FACTION_AND_ALLIES_FROM(src, user) log_combat(user, paicard.pai, "uploaded to [initial(src.name)],") return TRUE @@ -737,7 +743,8 @@ GLOBAL_LIST_INIT(command_strings, list( to_chat(paicard.pai, span_notice("You feel your control fade as [paicard] ejects from [initial(name)].")) paicard = null name = initial(name) - faction = initial(faction) + set_faction(original_faction) + set_allies(original_allies) remove_all_languages(source = LANGUAGE_PAI) get_selected_language() diff --git a/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm b/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm index b5e860199f8..25029c5bc55 100644 --- a/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm +++ b/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm @@ -185,7 +185,7 @@ continue if(!HAS_TRAIT(human_target, TRAIT_CLEANBOT_WHISPERER)) continue - if((living_pawn.faction.Find(REF(human_target)))) + if(living_pawn.has_ally(REF(human_target))) continue return human_target return null diff --git a/code/modules/mob/living/basic/bots/dedbot.dm b/code/modules/mob/living/basic/bots/dedbot.dm index 607d788b430..d55570edbdc 100644 --- a/code/modules/mob/living/basic/bots/dedbot.dm +++ b/code/modules/mob/living/basic/bots/dedbot.dm @@ -109,7 +109,7 @@ /datum/action/cooldown/mob_cooldown/exenterate/proc/slash_em(atom/caster) for(var/mob/living/victim in range(ability_range, caster)) - if(faction_check(victim.faction, immune_factions) && victim.IsReachableBy(owner)) + if(victim.has_faction(immune_factions) && victim.IsReachableBy(owner)) continue to_chat(caster, span_warning("You slice [victim]!")) to_chat(victim, span_warning("You are cut by [caster]'s blades!")) diff --git a/code/modules/mob/living/basic/cytology/vatbeast.dm b/code/modules/mob/living/basic/cytology/vatbeast.dm index 5b6460eebb2..84eb8e1fcd4 100644 --- a/code/modules/mob/living/basic/cytology/vatbeast.dm +++ b/code/modules/mob/living/basic/cytology/vatbeast.dm @@ -53,7 +53,7 @@ /mob/living/basic/vatbeast/tamed(mob/living/tamer, obj/item/food) buckle_lying = 0 AddElement(/datum/element/ridable, /datum/component/riding/creature/vatbeast) - faction = list(FACTION_NEUTRAL) + set_faction(list(FACTION_NEUTRAL)) /mob/living/basic/vatbeast/proc/add_cell_sample() AddElement(/datum/element/swabable, CELL_LINE_TABLE_VATBEAST, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) diff --git a/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm b/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm index c0e51bfd39e..25879d07d5c 100644 --- a/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm +++ b/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm @@ -37,7 +37,7 @@ /mob/living/basic/cow/moonicorn/tamed(mob/living/tamer, atom/food) . = ..() ///stop killing my FRIENDS - faction |= tamer.faction + APPLY_FACTION_AND_ALLIES_FROM(src, tamer) /datum/ai_controller/basic_controller/cow/moonicorn blackboard = list( diff --git a/code/modules/mob/living/basic/guardian/guardian.dm b/code/modules/mob/living/basic/guardian/guardian.dm index cd903cbc020..fd84556c99d 100644 --- a/code/modules/mob/living/basic/guardian/guardian.dm +++ b/code/modules/mob/living/basic/guardian/guardian.dm @@ -15,7 +15,6 @@ mob_biotypes = MOB_SPECIAL sentience_type = SENTIENCE_HUMANOID hud_type = /datum/hud/guardian - faction = list() speed = 0 status_flags = CANPUSH maxHealth = INFINITY // The spirit itself is invincible and passes damage to its host @@ -225,8 +224,9 @@ if (mind) mind.enslave_mind_to_creator(to_who) else //mindless guardian, manually give them factions - faction += summoner.faction - summoner.faction += "[REF(src)]" + add_faction(summoner.get_faction()) + add_ally(summoner.allies) + summoner.add_ally(src) remove_all_languages(LANGUAGE_MASTER) copy_languages(to_who, LANGUAGE_MASTER) // make sure holoparasites speak same language as master RegisterSignal(to_who, COMSIG_QDELETING, PROC_REF(on_summoner_deletion)) @@ -251,8 +251,8 @@ unleash() UnregisterSignal(summoner, list(COMSIG_QDELETING, COMSIG_LIVING_ON_WABBAJACKED, COMSIG_LIVING_SHAPESHIFTED, COMSIG_LIVING_UNSHAPESHIFTED)) if (different_person) - summoner.faction -= "[REF(src)]" - faction -= summoner.faction + summoner.remove_ally(src) + remove_faction(summoner.get_faction()) mind?.remove_all_antag_datums() if (!length(summoner.get_all_linked_holoparasites() - src)) for (var/action_type in control_actions) diff --git a/code/modules/mob/living/basic/icemoon/wolf/wolf.dm b/code/modules/mob/living/basic/icemoon/wolf/wolf.dm index cd2e743fb95..c50c56c38c3 100644 --- a/code/modules/mob/living/basic/icemoon/wolf/wolf.dm +++ b/code/modules/mob/living/basic/icemoon/wolf/wolf.dm @@ -83,5 +83,5 @@ . = ..() if(isnull(.)) return - faction = new_friend.faction.Copy() + SET_FACTION_AND_ALLIES_FROM(src, new_friend) visible_message(span_notice("[src] lowers [src.p_their()] snout at [new_friend]'s offering and begins to wag [src.p_their()] tail.")) diff --git a/code/modules/mob/living/basic/illusion/illusion.dm b/code/modules/mob/living/basic/illusion/illusion.dm index 793cdb3092c..0a1a5fa3195 100644 --- a/code/modules/mob/living/basic/illusion/illusion.dm +++ b/code/modules/mob/living/basic/illusion/illusion.dm @@ -50,9 +50,11 @@ try_replicate() /// Full setup for illusion mobs to lessen code duplication in the individual files. -/mob/living/basic/illusion/proc/full_setup(mob/living/original, mob/living/target_mob = null, list/faction = null, life = 5 SECONDS, hp = 100, damage = 0, replicate = 0) +/mob/living/basic/illusion/proc/full_setup(mob/living/original, mob/living/target_mob = null, list/faction_override = null, life = 5 SECONDS, hp = 100, damage = 0, replicate = 0) mock_as(original, life, hp, damage, replicate) - set_faction(faction) + SET_FACTION_AND_ALLIES_FROM(src, original) + if(faction_override) + set_faction(faction_override) set_target(target_mob) /// Gives the illusion a target to focus on in whatever behavior it wants to engage as. @@ -61,12 +63,6 @@ return ai_controller.set_blackboard_key(target_key, target_mob) -/// Sets the faction of the illusion -/mob/living/basic/illusion/proc/set_faction(list/new_faction) - if(!new_faction) // can be list with no length or null - return - faction = new_faction.Copy() - /// Does the actual work of setting up the illusion's appearance and some other functionality. /mob/living/basic/illusion/proc/mock_as(mob/living/original, life, hp, damage, replicate) if(QDELETED(original)) @@ -83,7 +79,7 @@ melee_damage_upper = damage multiply_chance = replicate - faction -= FACTION_NEUTRAL + remove_faction(FACTION_NEUTRAL) transform = initial(transform) pixel_x = base_pixel_x pixel_y = base_pixel_y @@ -104,7 +100,7 @@ new_clone.full_setup( parent_mob, target_mob = ai_controller.blackboard[target_key], - faction = faction, + faction_override = faction, life = 8 SECONDS, hp = health / 2, damage = melee_damage_upper, diff --git a/code/modules/mob/living/basic/jungle/leaper/leaper_abilities.dm b/code/modules/mob/living/basic/jungle/leaper/leaper_abilities.dm index 5d268338dcd..762ac89f0dd 100644 --- a/code/modules/mob/living/basic/jungle/leaper/leaper_abilities.dm +++ b/code/modules/mob/living/basic/jungle/leaper/leaper_abilities.dm @@ -247,4 +247,4 @@ /datum/action/cooldown/spell/conjure/limit_summons/create_suicide_toads/post_summon(atom/summoned_object, atom/cast_on) . = ..() var/mob/living/summoned_toad = summoned_object - summoned_toad.faction = owner.faction ///so they dont attack the leaper or the wizard master + SET_FACTION_AND_ALLIES_FROM(summoned_toad, owner) // so they dont attack the leaper or the wizard master diff --git a/code/modules/mob/living/basic/jungle/seedling/seedling_projectiles.dm b/code/modules/mob/living/basic/jungle/seedling/seedling_projectiles.dm index a5b47c7d22f..662c5542b60 100644 --- a/code/modules/mob/living/basic/jungle/seedling/seedling_projectiles.dm +++ b/code/modules/mob/living/basic/jungle/seedling/seedling_projectiles.dm @@ -16,7 +16,7 @@ return ..() var/mob/living/living_target = target - if(FACTION_JUNGLE in living_target.faction) + if(living_target.has_faction(FACTION_JUNGLE)) return BULLET_ACT_BLOCK return ..() diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm index 5932f47df66..7a5cdef49ea 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm @@ -159,7 +159,7 @@ . = ..() if(isnull(.)) return - faction = new_friend.faction.Copy() + SET_FACTION_AND_ALLIES_FROM(src, new_friend) /mob/living/basic/mining/goliath/RangedAttack(atom/atom_target, modifiers) tentacles?.Trigger(target = atom_target) diff --git a/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm index 7174800ab15..800f4c351aa 100644 --- a/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm +++ b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm @@ -42,7 +42,7 @@ for(var/mob/living/potential_friend in oview(9, living_pawn)) if(!isashwalker(potential_friend)) continue - if((living_pawn.faction.Find(REF(potential_friend)))) + if(living_pawn.has_ally(REF(potential_friend))) continue living_pawn.befriend(potential_friend) to_chat(potential_friend, span_nicegreen("[living_pawn] looks at you with endearing eyes!")) diff --git a/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm b/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm index d6082793103..08599831a51 100644 --- a/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm +++ b/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm @@ -59,7 +59,7 @@ /// Spawns a worm on the specified turf /mob/living/basic/mining/hivelord/proc/complete_spawn(turf/spawn_turf) var/mob/living/brood = new death_spawn_type(spawn_turf) - brood.faction = faction + SET_FACTION_AND_ALLIES_FROM(brood, src) brood.ai_controller?.set_blackboard_key(ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET]) brood.dir = get_dir(src, spawn_turf) diff --git a/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm b/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm index 6dbbe72a245..146d2fba82f 100644 --- a/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm +++ b/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm @@ -79,7 +79,7 @@ /// Actually create a mob /datum/action/cooldown/mob_cooldown/hivelord_spawn/proc/complete_spawn(turf/spawn_turf, target) var/mob/living/brood = new spawn_type(spawn_turf) - brood.faction = owner.faction + SET_FACTION_AND_ALLIES_FROM(brood, owner) brood.ai_controller?.set_blackboard_key(ai_target_key, target) brood.dir = get_dir(owner, spawn_turf) diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm index bad0b34a2d0..1fc6a7d02be 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm @@ -85,7 +85,7 @@ var/spawn_type = get_legion_type(target) var/mob/living/basic/mining/legion/new_legion = new spawn_type(loc) new_legion.consume(target) - new_legion.faction = faction.Copy() + new_legion.set_faction(get_faction()) qdel(src) /// Returns the kind of legion we make out of the target @@ -99,9 +99,9 @@ /// Sets someone as our creator, mostly so you can't use skulls to heal yourself /mob/living/basic/mining/legion_brood/proc/assign_creator(mob/living/creator, copy_full_faction = TRUE) if (copy_full_faction) - faction = creator.faction.Copy() + set_faction(creator.get_faction()) else - faction |= REF(creator) + add_ally(creator) created_by = WEAKREF(creator) ai_controller?.set_blackboard_key(BB_LEGION_BROOD_CREATOR, creator) RegisterSignal(creator, COMSIG_QDELETING, PROC_REF(creator_destroyed)) diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm index 93522890134..640cdc10338 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm @@ -97,8 +97,8 @@ . = ..() if(isnull(.)) return - faction |= new_friend.faction - faction -= FACTION_MINING + APPLY_FACTION_AND_ALLIES_FROM(src, new_friend) + remove_faction(FACTION_MINING) /mob/living/basic/mining/lobstrosity/mind_initialize() . = ..() diff --git a/code/modules/mob/living/basic/lavaland/mining.dm b/code/modules/mob/living/basic/lavaland/mining.dm index 258b897457c..59247792800 100644 --- a/code/modules/mob/living/basic/lavaland/mining.dm +++ b/code/modules/mob/living/basic/lavaland/mining.dm @@ -58,6 +58,6 @@ /mob/living/basic/mining/proc/check_ashwalker_peace_violation(datum/source, mob/living/carbon/human/possible_ashwalker) SIGNAL_HANDLER - if(!isashwalker(possible_ashwalker) || !(FACTION_ASHWALKER in faction)) + if(!isashwalker(possible_ashwalker) || !has_faction(FACTION_ASHWALKER)) return - faction.Remove(FACTION_ASHWALKER) + remove_faction(FACTION_ASHWALKER) diff --git a/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm b/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm index 14a8acdabbd..92f6156a705 100644 --- a/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm +++ b/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm @@ -31,7 +31,7 @@ GLOBAL_LIST_INIT(mook_commands, list( ///check for faction if not a ash walker, otherwise just attack /datum/targeting_strategy/basic/mook/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) - if(FACTION_ASHWALKER in living_mob.faction) + if(living_mob.has_faction(FACTION_ASHWALKER)) return FALSE return ..() diff --git a/code/modules/mob/living/basic/minebots/minebot_abilities.dm b/code/modules/mob/living/basic/minebots/minebot_abilities.dm index 6d6229d7e53..95948b328f7 100644 --- a/code/modules/mob/living/basic/minebots/minebot_abilities.dm +++ b/code/modules/mob/living/basic/minebots/minebot_abilities.dm @@ -116,7 +116,7 @@ if(isgroundlessturf(my_turf)) return FALSE var/obj/effect/mine/minebot/my_mine = new(my_turf) - my_mine.ignore_list = owner.faction.Copy() + my_mine.ignore_list = owner.get_faction() playsound(my_turf, 'sound/items/weapons/armbomb.ogg', 20) StartCooldown() return TRUE @@ -183,6 +183,6 @@ if(!isliving(on_who)) return ..() var/mob/living/stepped_mob = on_who - if(FACTION_NEUTRAL in stepped_mob.faction) + if(stepped_mob.has_faction(FACTION_NEUTRAL)) return FALSE return ..() diff --git a/code/modules/mob/living/basic/minebots/minebot_ai.dm b/code/modules/mob/living/basic/minebots/minebot_ai.dm index 69d7509f6c0..53895358d2a 100644 --- a/code/modules/mob/living/basic/minebots/minebot_ai.dm +++ b/code/modules/mob/living/basic/minebots/minebot_ai.dm @@ -74,7 +74,7 @@ controller.queue_behavior(/datum/ai_behavior/find_and_set, BB_DRONE_DEFEND, /mob/living/basic/node_drone) return var/mob/living/living_pawn = controller.pawn - if(!living_pawn.faction.Find(REF(target))) + if(!living_pawn.has_ally(target)) controller.queue_behavior(/datum/ai_behavior/befriend_target, BB_DRONE_DEFEND) return if(target.health < (target.maxHealth * 0.75) && controller.blackboard[BB_MINEBOT_REPAIR_DRONE]) diff --git a/code/modules/mob/living/basic/pets/gondolas/gondolapod.dm b/code/modules/mob/living/basic/pets/gondolas/gondolapod.dm index 11cb75895d0..d71b928fed2 100644 --- a/code/modules/mob/living/basic/pets/gondolas/gondolapod.dm +++ b/code/modules/mob/living/basic/pets/gondolas/gondolapod.dm @@ -51,13 +51,13 @@ else . += span_notice("It looks like it has already made its delivery.") -/mob/living/basic/pet/gondola/gondolapod/setOpened() +/mob/living/basic/pet/gondola/gondolapod/set_opened() opened = TRUE layer = initial(layer) update_appearance() - addtimer(CALLBACK(src, TYPE_PROC_REF(/atom/, setClosed)), 5 SECONDS) + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom/, set_closed)), 5 SECONDS) -/mob/living/basic/pet/gondola/gondolapod/setClosed() +/mob/living/basic/pet/gondola/gondolapod/set_closed() opened = FALSE layer = LOW_MOB_LAYER update_appearance() diff --git a/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_hoarding.dm b/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_hoarding.dm index bdfad843333..a4059b2d964 100644 --- a/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_hoarding.dm +++ b/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_hoarding.dm @@ -57,7 +57,7 @@ return potential_victim if(!ishuman(potential_victim)) continue - if(living_pawn.faction.Find(REF(potential_victim))) + if(living_pawn.has_ally(potential_victim)) continue //dont steal from friends if(holding_valuable(controller, potential_victim)) controller.set_blackboard_key(BB_ALWAYS_IGNORE_FACTION, TRUE) diff --git a/code/modules/mob/living/basic/pets/pet_cult/pet_cult_ai.dm b/code/modules/mob/living/basic/pets/pet_cult/pet_cult_ai.dm index 28964296264..194c774371b 100644 --- a/code/modules/mob/living/basic/pets/pet_cult/pet_cult_ai.dm +++ b/code/modules/mob/living/basic/pets/pet_cult/pet_cult_ai.dm @@ -51,7 +51,7 @@ /datum/ai_behavior/find_and_set/friendly_cultist/search_tactic(datum/ai_controller/controller, locate_path, search_range = SEARCH_TACTIC_DEFAULT_RANGE) var/mob/living/living_pawn = controller.pawn for(var/mob/living/carbon/possible_cultist in oview(search_range, controller.pawn)) - if(IS_CULTIST(possible_cultist) && !(living_pawn.faction.Find(REF(possible_cultist)))) + if(IS_CULTIST(possible_cultist) && !(living_pawn.has_ally(possible_cultist))) return possible_cultist return null diff --git a/code/modules/mob/living/basic/slime/actions.dm b/code/modules/mob/living/basic/slime/actions.dm index b96ada87025..bef26584479 100644 --- a/code/modules/mob/living/basic/slime/actions.dm +++ b/code/modules/mob/living/basic/slime/actions.dm @@ -112,7 +112,7 @@ var/list/created_slimes = list(src) var/list/slime_friends = list() - for(var/faction_member in faction) + for(var/faction_member in get_faction()) var/mob/living/possible_friend = locate(faction_member) in GLOB.mob_living_list if(QDELETED(possible_friend)) continue diff --git a/code/modules/mob/living/basic/slime/ai/behaviours.dm b/code/modules/mob/living/basic/slime/ai/behaviours.dm index 934404d88dd..92ccfef7add 100644 --- a/code/modules/mob/living/basic/slime/ai/behaviours.dm +++ b/code/modules/mob/living/basic/slime/ai/behaviours.dm @@ -29,12 +29,12 @@ // Check if the slime can drain the target /datum/ai_behavior/find_hunt_target/find_slime_food/valid_dinner(mob/living/basic/slime/hunter, mob/living/dinner, radius, datum/ai_controller/controller, seconds_per_tick) + var/static/list/slime_faction + if(isnull(slime_faction)) // This might look silly but by having this list pointer precached we can take advantage of the faster inline macro for this hot proc. + slime_faction = string_list(list(FACTION_SLIME)) - if(REF(dinner) in hunter.faction) //Don't eat our friends... - return FALSE - - var/static/list/slime_faction = list(FACTION_SLIME) - if(faction_check(slime_faction, dinner.faction)) //Don't try to eat slimy things, no matter how hungry we are. Anyone else can be betrayed. + // Macro here to squeeze as much speed as possible because this code gets exponentially HOT if people are doing a lot of xenobio. + if(FAST_FACTION_CHECK(slime_faction, dinner.get_faction(), hunter.allies, dinner.allies, FALSE)) // Don't try to eat our friends, or slimy things, no matter how hungry we are. Anyone else can be betrayed. return FALSE if(!hunter.can_feed_on(dinner, check_adjacent = FALSE)) //Are they tasty to slimes? diff --git a/code/modules/mob/living/basic/slime/feeding.dm b/code/modules/mob/living/basic/slime/feeding.dm index 5eaf02b1b03..3661bcdbd30 100644 --- a/code/modules/mob/living/basic/slime/feeding.dm +++ b/code/modules/mob/living/basic/slime/feeding.dm @@ -17,7 +17,7 @@ balloon_alert(src, "not hungry!") return FALSE - if(check_friendship && (REF(meal) in faction)) + if(check_friendship && has_faction(REF(meal))) return FALSE if(check_adjacent && (!Adjacent(meal) || !isturf(loc))) diff --git a/code/modules/mob/living/basic/space_fauna/changeling/flesh_spider.dm b/code/modules/mob/living/basic/space_fauna/changeling/flesh_spider.dm index 5e5d98afb10..c6116cd041a 100644 --- a/code/modules/mob/living/basic/space_fauna/changeling/flesh_spider.dm +++ b/code/modules/mob/living/basic/space_fauna/changeling/flesh_spider.dm @@ -33,7 +33,6 @@ unsuitable_cold_damage = 4 unsuitable_heat_damage = 4 combat_mode = TRUE - faction = list() // No allies but yourself pass_flags = PASSTABLE unique_name = TRUE lighting_cutoff_red = 22 diff --git a/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm b/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm index a45900ae02e..fd549c92ffe 100644 --- a/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm +++ b/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm @@ -119,4 +119,4 @@ /mob/living/basic/eyeball/tamed(mob/living/tamer, atom/food) spin(spintime = 2 SECONDS, speed = 1) //become passive to the humens - faction |= tamer.faction + APPLY_FACTION_AND_ALLIES_FROM(src, tamer) diff --git a/code/modules/mob/living/basic/space_fauna/lightgeist.dm b/code/modules/mob/living/basic/space_fauna/lightgeist.dm index 1ac90898bef..f59c5070bff 100644 --- a/code/modules/mob/living/basic/space_fauna/lightgeist.dm +++ b/code/modules/mob/living/basic/space_fauna/lightgeist.dm @@ -67,7 +67,7 @@ /mob/living/basic/lightgeist/melee_attack(atom/target, list/modifiers, ignore_cooldown = FALSE) . = ..() if (. && isliving(target)) - faction |= REF(target) // Anyone we heal will treat us as a friend + add_ally(target) // Anyone we heal will treat us as a friend /mob/living/basic/lightgeist/ghost() . = ..() diff --git a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm index 4314a099554..ccb86e7043c 100644 --- a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm +++ b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm @@ -21,7 +21,6 @@ response_help_simple = "pet" response_disarm_continuous = "gently pushes" response_disarm_simple = "gently push" - faction = list() ai_controller = /datum/ai_controller/basic_controller/meteor_heart habitable_atmos = null minimum_survivable_temperature = 0 diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm index 5800ada99a6..b51871c7f9d 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm @@ -175,9 +175,9 @@ /datum/reagent/rat_spit/overdose_start(mob/living/affected_mob, metabolization_ratio) . = ..() var/mob/living/carbon/victim = affected_mob - if (istype(victim) && !(FACTION_RAT in victim.faction)) + if (istype(victim) && !victim.has_faction(FACTION_RAT)) to_chat(victim, span_userdanger("With this last sip, you feel your body convulsing horribly from the contents you've ingested. As you contemplate your actions, you sense an awakened kinship with rat-kind and their newly risen leader!")) - victim.faction |= FACTION_RAT + victim.add_faction(FACTION_RAT) victim.vomit(VOMIT_CATEGORY_DEFAULT) metabolization_rate = 10 * REAGENTS_METABOLISM diff --git a/code/modules/mob/living/basic/space_fauna/spider/spider.dm b/code/modules/mob/living/basic/space_fauna/spider/spider.dm index 086c0f0a353..9d3df866c55 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/spider.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/spider.dm @@ -152,7 +152,7 @@ var/mob/living/basic/spider/giant/grown = change_mob_type(grow_as, get_turf(src), initial(grow_as.name)) ADD_TRAIT(grown, TRAIT_WAS_EVOLVED, REF(src)) - grown.faction = faction.Copy() + SET_FACTION_AND_ALLIES_FROM(grown, src) grown.directive = directive grown.set_name() grown.set_brute_loss(get_brute_loss()) diff --git a/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/lay_eggs.dm b/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/lay_eggs.dm index 5979c98448d..d60a1088b98 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/lay_eggs.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/lay_eggs.dm @@ -55,7 +55,7 @@ /datum/action/cooldown/mob_cooldown/lay_eggs/proc/lay_egg() var/obj/effect/mob_spawn/ghost_role/spider/new_eggs = new egg_type(get_turf(owner)) - new_eggs.faction = owner.faction + SET_FACTION_AND_ALLIES_FROM(new_eggs, owner) var/datum/action/cooldown/mob_cooldown/set_spider_directive/spider_directive = locate() in owner.actions if (spider_directive) new_eggs.directive = spider_directive.current_directive diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index 68cf1ba5c11..05efcfc5cef 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -81,7 +81,7 @@ /mob/living/basic/mouse/proc/make_tameable() if (tame) - faction |= FACTION_NEUTRAL + add_faction(FACTION_NEUTRAL) else var/static/list/food_types = list(/obj/item/food/cheese) AddComponent(/datum/component/tameable, food_types = food_types, tame_chance = 100) @@ -196,7 +196,7 @@ /// Called when a mouse is hand-fed some cheese, it will stop being afraid of humans /mob/living/basic/mouse/tamed(mob/living/tamer, obj/item/food/cheese/cheese) new /obj/effect/temp_visual/heart(loc) - faction |= FACTION_NEUTRAL + add_faction(FACTION_NEUTRAL) tame = TRUE try_consume_cheese(cheese) ai_controller.CancelActions() // Interrupt any current fleeing diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm index a83c1cec5dd..f5705c88494 100644 --- a/code/modules/mob/living/carbon/alien/organs.dm +++ b/code/modules/mob/living/carbon/alien/organs.dm @@ -103,11 +103,11 @@ /obj/item/organ/alien/hivenode/on_mob_insert(mob/living/carbon/organ_owner) . = ..() - organ_owner.faction |= ROLE_ALIEN + organ_owner.add_faction(ROLE_ALIEN) /obj/item/organ/alien/hivenode/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags) if(organ_owner) - organ_owner.faction -= ROLE_ALIEN + organ_owner.remove_faction(ROLE_ALIEN) return ..() //When the alien queen dies, all aliens suffer a penalty as punishment for failing to protect her. diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index b8172b2f35a..d15215a79c5 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -408,7 +408,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(inherent_factions) for(var/i in inherent_factions) - human_who_gained_species.faction += i //Using +=/-= for this in case you also gain the faction from a different source. + human_who_gained_species.add_faction(i) // All languages associated with this language holder are added with source [LANGUAGE_SPECIES] // rather than source [LANGUAGE_ATOM], so we can track what to remove if our species changes again @@ -463,7 +463,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(inherent_factions) for(var/i in inherent_factions) - human.faction -= i + human.remove_faction(i) clear_tail_moodlets(human) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index c3afec02b7a..8d586731e14 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -12,7 +12,7 @@ medhud.add_atom_to_hud(src) var/datum/atom_hud/data/diagnostic/diag_hud = GLOB.huds[DATA_HUD_DIAGNOSTIC] diag_hud.add_atom_to_hud(src) - faction += "[REF(src)]" + add_ally(src) GLOB.mob_living_list += src SSpoints_of_interest.make_point_of_interest(src) update_fov() @@ -2792,7 +2792,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) /// Proc called when TARGETED by a lazarus injector /mob/living/proc/lazarus_revive(mob/living/reviver, malfunctioning) revive(HEAL_ALL) - faction |= FACTION_NEUTRAL + add_faction(FACTION_NEUTRAL) if (!malfunctioning) befriend(reviver) var/lazarus_policy = get_policy(ROLE_LAZARUS_GOOD) || "The lazarus injector has brought you back to life! You are now friendly to everyone." @@ -2811,9 +2811,9 @@ GLOBAL_LIST_EMPTY(fire_appearances) if(QDELETED(new_friend)) return var/friend_ref = REF(new_friend) - if (faction.Find(friend_ref)) + if (has_ally(friend_ref)) return FALSE - faction |= friend_ref + add_ally(friend_ref) ai_controller?.insert_blackboard_key_lazylist(BB_FRIENDS_LIST, new_friend) SEND_SIGNAL(src, COMSIG_LIVING_BEFRIENDED, new_friend) @@ -2823,9 +2823,9 @@ GLOBAL_LIST_EMPTY(fire_appearances) /mob/living/proc/unfriend(mob/living/old_friend) SHOULD_CALL_PARENT(TRUE) var/friend_ref = REF(old_friend) - if (!faction.Find(friend_ref)) + if (!has_ally(friend_ref)) return FALSE - faction -= friend_ref + remove_ally(friend_ref) ai_controller?.remove_thing_from_blackboard_key(BB_FRIENDS_LIST, old_friend) SEND_SIGNAL(src, COMSIG_LIVING_UNFRIENDED, old_friend) diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm index 13fd3d53d4b..83da4418def 100644 --- a/code/modules/mob/living/silicon/robot/robot_model.dm +++ b/code/modules/mob/living/silicon/robot/robot_model.dm @@ -917,12 +917,12 @@ /obj/item/robot_model/syndicate/rebuild_modules() ..() var/mob/living/silicon/robot/cyborg = loc - cyborg.faction -= FACTION_SILICON //ai turrets + cyborg.remove_faction(FACTION_SILICON) //ai turrets /obj/item/robot_model/syndicate/remove_module(obj/item/removed_module) ..() var/mob/living/silicon/robot/cyborg = loc - cyborg.faction |= FACTION_SILICON //ai is your bff now! + cyborg.add_faction(FACTION_SILICON) //ai is your bff now! /obj/item/robot_model/syndicate_medical name = "Syndicate Medical" diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 3bb3398e4a8..b22e81b8907 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -57,7 +57,7 @@ if(SStts.tts_enabled) voice = pick(SStts.available_speakers) GLOB.silicon_mobs += src - faction += FACTION_SILICON + add_faction(FACTION_SILICON) if(ispath(radio)) radio = new radio(src) var/datum/atom_hud/data/diagnostic/diag_hud = GLOB.huds[DATA_HUD_DIAGNOSTIC] diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index a1b576bc18a..b68e70589e2 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -113,6 +113,10 @@ var/list/automated_announcements /// Action we use to say voice lines out loud, also we just pass anything we try to say through here just in case it plays a voice line var/datum/action/cooldown/bot_announcement/pa_system + // The faction of the bot before it inherited the pai's faction + var/list/original_faction + // The allies of the bot before it inherited the pai's faction + var/list/original_allies ///Innate access uses an internal ID card. var/obj/item/card/id/access_card = null @@ -1091,7 +1095,9 @@ Pass a positive integer as an argument to override a bot's default speed. paicard.pai.mind.transfer_to(src) to_chat(src, span_notice("You sense your form change as you are uploaded into [src].")) name = paicard.pai.name - faction = user.faction.Copy() + original_faction = get_faction() + original_allies = allies + SET_FACTION_AND_ALLIES_FROM(src, user) log_combat(user, paicard.pai, "uploaded to [initial(src.name)],") return TRUE @@ -1121,7 +1127,8 @@ Pass a positive integer as an argument to override a bot's default speed. to_chat(paicard.pai, span_notice("You feel your control fade as [paicard] ejects from [initial(src.name)].")) paicard = null name = initial(src.name) - faction = initial(faction) + set_faction(original_faction) + set_allies(original_allies) remove_all_languages(source = LANGUAGE_PAI) get_selected_language() @@ -1152,7 +1159,7 @@ Pass a positive integer as an argument to override a bot's default speed. update_appearance() /mob/living/simple_animal/bot/sentience_act() - faction -= FACTION_SILICON + remove_faction(FACTION_SILICON) /mob/living/simple_animal/bot/proc/set_path(list/newpath) path = newpath ? newpath : list() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 1974c078bac..ed89e26e6f8 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -649,7 +649,7 @@ return friends += new_friend RegisterSignal(new_friend, COMSIG_QDELETING, PROC_REF(handle_friend_del)) - faction = new_friend.faction.Copy() + SET_FACTION_AND_ALLIES_FROM(src, new_friend) /mob/living/simple_animal/hostile/lazarus_revive(mob/living/reviver, malfunctioning) . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index e796781cf4c..f8fcddc4bc7 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -384,7 +384,8 @@ While using this makes the system rely on OnFire, it still gives options for tim if(elite.stat != DEAD || elite.sentience_type != SENTIENCE_BOSS || !elite.key) user.visible_message(span_notice("It appears [elite] is unable to be revived right now. Perhaps try again later.")) return ITEM_INTERACT_BLOCKING - elite.faction = list("[REF(user)]") + elite.set_allies(list("[REF(user)]")) + elite.set_faction(null) elite.revive(HEAL_ALL) user.visible_message(span_notice("[user] stabs [elite] with [src], reviving it.")) elite.playsound_local(get_turf(elite), 'sound/effects/magic.ogg', 40, 0) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm index a75324ec642..d62fa709e77 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm @@ -135,7 +135,7 @@ return var/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/new_child = new /mob/living/simple_animal/hostile/asteroid/elite/broodmother_child(loc) new_child.GiveTarget(target) - new_child.faction = faction.Copy() + SET_FACTION_AND_ALLIES_FROM(new_child, src) visible_message(span_boldwarning("[new_child] appears below [src]!")) register_child(new_child) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm index 2aa81a09f2a..29cbb2e363c 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm @@ -196,7 +196,7 @@ var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/new_mirror = new /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror(loc) my_mirror = new_mirror my_mirror.my_master = src - my_mirror.faction = faction.Copy() + SET_FACTION_AND_ALLIES_FROM(my_mirror, src) /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror name = "herald's mirror" diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm index 4f92eeabdb4..1210cb357ad 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm @@ -172,7 +172,7 @@ visible_message(span_boldwarning("[src]'s head flies off!")) var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/newhead = new /mob/living/simple_animal/hostile/asteroid/elite/legionnairehead(loc) newhead.GiveTarget(target) - newhead.faction = faction.Copy() + SET_FACTION_AND_ALLIES_FROM(newhead, src) myhead = newhead myhead.body = src if(health < maxHealth * 0.25) @@ -257,7 +257,7 @@ move_to_delay = 2 del_on_death = 1 death_message = "crumbles away!" - faction = list() + faction = null ranged = FALSE var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/body = null diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index bf52b0a9b1b..36efed52c93 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1162,24 +1162,6 @@ /mob/proc/canUseStorage() return FALSE -/* - * Compare two lists of factions, returning true if any match - * - * If exact match is passed through we only return true if both faction lists match equally - */ -/proc/faction_check(list/faction_A, list/faction_B, exact_match) - var/list/match_list - if(exact_match) - match_list = faction_A&faction_B //only items in both lists - var/length = LAZYLEN(match_list) - if(length) - return (length == LAZYLEN(faction_A)) //if they're not the same len(gth) or we don't have a len, then this isn't an exact match. - else - match_list = faction_A&faction_B - return LAZYLEN(match_list) - return FALSE - - /** * Fully update the name of a mob * diff --git a/code/modules/mob_spawn/ghost_roles/mining_roles.dm b/code/modules/mob_spawn/ghost_roles/mining_roles.dm index 1c11cfb0fce..401366afbb6 100644 --- a/code/modules/mob_spawn/ghost_roles/mining_roles.dm +++ b/code/modules/mob_spawn/ghost_roles/mining_roles.dm @@ -320,7 +320,7 @@ implants = list(/obj/item/implant/weapons_auth) /datum/outfit/lavaland_syndicate/post_equip(mob/living/carbon/human/syndicate, visuals_only = FALSE) - syndicate.faction |= ROLE_SYNDICATE + syndicate.add_faction(ROLE_SYNDICATE) /datum/outfit/lavaland_syndicate/comms name = "Lavaland Syndicate Comms Agent" diff --git a/code/modules/mob_spawn/ghost_roles/spider_roles.dm b/code/modules/mob_spawn/ghost_roles/spider_roles.dm index 9251930808f..4c2dbfe9314 100644 --- a/code/modules/mob_spawn/ghost_roles/spider_roles.dm +++ b/code/modules/mob_spawn/ghost_roles/spider_roles.dm @@ -178,7 +178,7 @@ icon_state = "eggs" you_are_text = "You are a flesh spider." flavour_text = "An abomination of nature set upon the station by changelings. Your only goal is to kill, terrorize, and survive." - faction = list() + faction = null directive = null cluster_type = /obj/structure/spider/eggcluster/bloody potentialspawns = list( diff --git a/code/modules/mob_spawn/ghost_roles/unused_roles.dm b/code/modules/mob_spawn/ghost_roles/unused_roles.dm index f001ff2487e..abaed86e656 100644 --- a/code/modules/mob_spawn/ghost_roles/unused_roles.dm +++ b/code/modules/mob_spawn/ghost_roles/unused_roles.dm @@ -111,7 +111,7 @@ implants = list(/obj/item/implant/weapons_auth) /datum/outfit/syndicate_empty/post_equip(mob/living/carbon/human/H) - H.faction |= ROLE_SYNDICATE + H.add_faction(ROLE_SYNDICATE) //For ghost bar. /obj/effect/mob_spawn/ghost_role/human/space_bar_patron @@ -314,7 +314,7 @@ implants = list(/obj/item/implant/weapons_auth) /datum/outfit/syndicatespace/post_equip(mob/living/carbon/human/syndie_scum) - syndie_scum.faction |= ROLE_SYNDICATE + syndie_scum.add_faction(ROLE_SYNDICATE) /datum/outfit/syndicatespace/syndicrew name = "Syndicate Ship Crew Member" diff --git a/code/modules/mob_spawn/mob_spawn.dm b/code/modules/mob_spawn/mob_spawn.dm index 5816f8bb38b..479b2ff5d43 100644 --- a/code/modules/mob_spawn/mob_spawn.dm +++ b/code/modules/mob_spawn/mob_spawn.dm @@ -76,7 +76,7 @@ /obj/effect/mob_spawn/proc/special(mob/living/spawned_mob, mob/mob_possessor, apply_prefs) SHOULD_CALL_PARENT(TRUE) if(faction) - spawned_mob.faction = faction + spawned_mob.set_faction(faction) if(ishuman(spawned_mob)) var/mob/living/carbon/human/spawned_human = spawned_mob if(mob_species) diff --git a/code/modules/mod/mod_core.dm b/code/modules/mod/mod_core.dm index 174299fdc67..491c47fa1c9 100644 --- a/code/modules/mod/mod_core.dm +++ b/code/modules/mod/mod_core.dm @@ -487,7 +487,7 @@ spawn_types = list(spawned_mob_type), \ spawn_time = 5 SECONDS, \ max_spawned = 3, \ - faction = mod.wearer.faction, \ + faction = mod.wearer.get_faction(), \ ) RegisterSignal(mob_spawner, COMSIG_SPAWNER_SPAWNED, PROC_REF(new_mob)) RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(spread_flowers)) diff --git a/code/modules/mod/modules/modules_ninja.dm b/code/modules/mod/modules/modules_ninja.dm index 67a9862ddf4..d4723b04ca6 100644 --- a/code/modules/mod/modules/modules_ninja.dm +++ b/code/modules/mod/modules/modules_ninja.dm @@ -491,7 +491,7 @@ //BORG, Ninja objective converts a borg to a syndicate version /mob/living/silicon/robot/ninjadrain_act(mob/living/carbon/human/ninja, obj/item/mod/module/hacker/hacking_module) - if(!ninja || !hacking_module || (ROLE_NINJA in faction)) + if(!ninja || !hacking_module || (has_faction(ROLE_NINJA))) return NONE to_chat(src, span_danger("Warni-***BZZZZZZZZZRT*** UPLOADING SPYDERPATCHER VERSION 9.5.2...")) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 6341dc58244..350a85598e7 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -646,7 +646,7 @@ return FALSE if(ignored_factions?.len && ismob(target) && !direct_target) var/mob/target_mob = target - if(faction_check(target_mob.faction, ignored_factions)) + if(target_mob.has_faction(ignored_factions)) return FALSE if(target.density || cross_failed) //This thing blocks projectiles, hit it regardless of layer/mob stuns/etc. return TRUE diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index 9cd650d67ff..c6ecac2eb64 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -229,7 +229,7 @@ spawned_mob = create_random_mob(get_turf(holder.my_atom), mob_class) else spawned_mob = new mob_class(get_turf(holder.my_atom))//Spawn our specific mob_class - spawned_mob.faction |= mob_faction + spawned_mob.add_faction(mob_faction) ADD_TRAIT(spawned_mob, TRAIT_SPAWNED_MOB, INNATE_TRAIT) if(prob(50)) for(var/j in 1 to rand(1, 3)) diff --git a/code/modules/religion/honorbound/honorbound_trauma.dm b/code/modules/religion/honorbound/honorbound_trauma.dm index dcab9b0a876..a1797345935 100644 --- a/code/modules/religion/honorbound/honorbound_trauma.dm +++ b/code/modules/religion/honorbound/honorbound_trauma.dm @@ -104,10 +104,10 @@ /// Checks a mob for any obvious signs of evil, and applies a guilty reason for each. /datum/brain_trauma/special/honorbound/proc/check_visible_guilt(mob/living/attacked_mob) //will most likely just hit nuke ops but good catch-all. WON'T hit traitors - if(ROLE_SYNDICATE in attacked_mob.faction) + if(attacked_mob.has_faction(ROLE_SYNDICATE)) guilty(attacked_mob, "for their misaligned association with the Syndicate!") //not an antag datum check so it applies to wizard minions as well - if(ROLE_WIZARD in attacked_mob.faction) + if(attacked_mob.has_faction(ROLE_WIZARD)) guilty(attacked_mob, "for blasphemous magicks!") if(HAS_TRAIT(attacked_mob, TRAIT_CULT_HALO)) guilty(attacked_mob, "for blasphemous worship!") diff --git a/code/modules/religion/religion_sects.dm b/code/modules/religion/religion_sects.dm index 2f68a0153cf..05cf51ea433 100644 --- a/code/modules/religion/religion_sects.dm +++ b/code/modules/religion/religion_sects.dm @@ -61,7 +61,7 @@ SHOULD_CALL_PARENT(TRUE) to_chat(chap, span_boldnotice("\"[quote]\"")) to_chat(chap, span_notice("[desc]")) - chap.faction |= FACTION_HOLY + chap.add_faction(FACTION_HOLY) /// Activates if religious sect is reset by admins, should clean up anything you added on conversion. /datum/religion_sect/proc/on_deconversion(mob/living/chap) @@ -69,7 +69,7 @@ to_chat(chap, span_boldnotice("You have lost the approval of \the [name].")) if(chap.mind.holy_role == HOLY_ROLE_HIGHPRIEST) to_chat(chap, span_notice("Return to an altar to reform your sect.")) - chap.faction -= FACTION_HOLY + chap.remove_faction(FACTION_HOLY) /// Returns TRUE if the item can be sacrificed. Can be modified to fit item being tested as well as person offering. Returning TRUE will stop the attackby sequence and proceed to on_sacrifice. /datum/religion_sect/proc/can_sacrifice(obj/item/sacrifice, mob/living/chap) diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm index f041cba42bd..a8f22f5f980 100644 --- a/code/modules/research/xenobiology/crossbreeding/_misc.dm +++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm @@ -196,7 +196,7 @@ Slimecrossing Items else to_chat(user, span_warning("[pokemon] refused to enter the device.")) return - else if(!(FACTION_NEUTRAL in pokemon.faction)) + else if(!pokemon.has_faction(FACTION_NEUTRAL)) to_chat(user, span_warning("This creature is too aggressive to capture.")) return to_chat(user, span_notice("You store [pokemon] in the capture device.")) diff --git a/code/modules/research/xenobiology/crossbreeding/_potions.dm b/code/modules/research/xenobiology/crossbreeding/_potions.dm index cfc4630da7c..e9682993b2f 100644 --- a/code/modules/research/xenobiology/crossbreeding/_potions.dm +++ b/code/modules/research/xenobiology/crossbreeding/_potions.dm @@ -99,7 +99,7 @@ Slimecrossing Potions return ITEM_INTERACT_BLOCKING to_chat(user, span_notice("You feed [love_target] the love potion!")) to_chat(love_target, span_notice("You develop feelings for [user], and anyone [user.p_they()] like[user.p_s()].")) - love_target.faction |= "[REF(user)]" + love_target.add_ally(user) love_target.apply_status_effect(/datum/status_effect/in_love, user) qdel(src) return ITEM_INTERACT_SUCCESS diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index 5b08cd876c3..5087bfb5dbd 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -490,7 +490,7 @@ /datum/status_effect/stabilized/grey/tick(seconds_between_ticks) for(var/mob/living/basic/slime/slimes_in_range in range(1, get_turf(owner))) - if(!(REF(owner) in slimes_in_range.faction)) + if(!slimes_in_range.has_ally(owner)) to_chat(owner, span_notice("[linked_extract] pulses gently as it communicates with [slimes_in_range].")) slimes_in_range.befriend(owner) return ..() @@ -879,26 +879,20 @@ /datum/status_effect/stabilized/pink/on_apply() faction_name = FACTION_PINK_EXTRACT(owner) - owner.faction |= faction_name + owner.add_ally(faction_name) to_chat(owner, span_notice("[linked_extract] pulses, generating a fragile aura of peace.")) return ..() /datum/status_effect/stabilized/pink/tick(seconds_between_ticks) update_nearby_mobs() - var/has_faction = FALSE - for (var/check_faction in owner.faction) - if(check_faction != faction_name) - continue - has_faction = TRUE - break - - if(has_faction) + var/has_ally = owner.has_ally(faction_name) + if(has_ally) if(owner.has_status_effect(/datum/status_effect/brokenpeace)) - owner.faction -= faction_name + owner.remove_ally(faction_name) to_chat(owner, span_userdanger("The peace has been broken! Hostile creatures will now react to you!")) else if(!owner.has_status_effect(/datum/status_effect/brokenpeace)) to_chat(owner, span_notice("[linked_extract] pulses, generating a fragile aura of peace.")) - owner.faction |= faction_name + owner.add_ally(faction_name) return ..() /// Pacifies mobs you can see and unpacifies mobs you no longer can @@ -917,7 +911,7 @@ return // No point continuing from here if we're going to end the effect if(beast in visible_things) continue - beast.faction -= faction_name + beast.remove_ally(faction_name) beast.remove_status_effect(/datum/status_effect/pinkdamagetracker) mobs -= weak_mob @@ -930,16 +924,16 @@ continue mobs += weak_mob beast.apply_status_effect(/datum/status_effect/pinkdamagetracker) - beast.faction |= faction_name + beast.add_faction(faction_name) /datum/status_effect/stabilized/pink/on_remove() for(var/datum/weakref/weak_mob as anything in mobs) var/mob/living/beast = weak_mob.resolve() if(isnull(beast)) continue - beast.faction -= faction_name + beast.remove_faction(faction_name) beast.remove_status_effect(/datum/status_effect/pinkdamagetracker) - owner.faction -= faction_name + owner.remove_faction(faction_name) /datum/status_effect/stabilized/oil id = "stabilizedoil" diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm index 6977d4ca8e6..8ccfc9c97bb 100644 --- a/code/modules/research/xenobiology/crossbreeding/burning.dm +++ b/code/modules/research/xenobiology/crossbreeding/burning.dm @@ -243,7 +243,7 @@ Burning extracts: user.visible_message(span_danger("[src] shudders violently, and summons an army for [user]!")) for(var/i in 1 to 3) //Less than gold normally does, since it's safer and faster. var/mob/living/spawned_mob = create_random_mob(get_turf(user), HOSTILE_SPAWN) - spawned_mob.faction |= "[REF(user)]" + spawned_mob.add_ally(user) if(prob(50)) for(var/j in 1 to rand(1, 3)) step(spawned_mob, pick(NORTH,SOUTH,EAST,WEST)) diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm index c1c599da345..bfc0f0b6dc9 100644 --- a/code/modules/research/xenobiology/crossbreeding/chilling.dm +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -148,7 +148,7 @@ Chilling extracts: /obj/item/slimecross/chilling/bluespace colour = SLIME_TYPE_BLUESPACE effect_desc = "Touching people with this extract adds them to a list, when it is activated it teleports everyone on that list to the user." - var/list/allies = list() + var/list/slimepals = list() var/active = FALSE /obj/item/slimecross/chilling/bluespace/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) @@ -158,31 +158,31 @@ Chilling extracts: if(HAS_TRAIT(interacting_with, TRAIT_NO_TELEPORT)) to_chat(user, span_warning("[interacting_with] resists being linked with [src]!")) return ITEM_INTERACT_BLOCKING - if(interacting_with in allies) - allies -= interacting_with + if(interacting_with in slimepals) + slimepals -= interacting_with to_chat(user, span_notice("You unlink [src] with [interacting_with].")) else - allies += interacting_with + slimepals += interacting_with to_chat(user, span_notice("You link [src] with [interacting_with].")) return ITEM_INTERACT_SUCCESS /obj/item/slimecross/chilling/bluespace/do_effect(mob/user) - if(allies.len <= 0) + if(slimepals.len <= 0) to_chat(user, span_warning("[src] is not linked to anyone!")) return to_chat(user, span_notice("You feel [src] pulse as it begins charging bluespace energies...")) active = TRUE - for(var/mob/living/M in allies) + for(var/mob/living/M in slimepals) var/datum/status_effect/slimerecall/S = M.apply_status_effect(/datum/status_effect/slimerecall) S.target = user if(do_after(user, 10 SECONDS, target=src)) to_chat(user, span_notice("[src] shatters as it tears a hole in reality, snatching the linked individuals from the void!")) - for(var/mob/living/M in allies) + for(var/mob/living/M in slimepals) var/datum/status_effect/slimerecall/S = M.has_status_effect(/datum/status_effect/slimerecall) M.remove_status_effect(S) else to_chat(user, span_warning("[src] falls dark, dissolving into nothing as the energies fade away.")) - for(var/mob/living/M in allies) + for(var/mob/living/M in slimepals) var/datum/status_effect/slimerecall/S = M.has_status_effect(/datum/status_effect/slimerecall) if(istype(S)) S.interrupted = TRUE @@ -192,24 +192,24 @@ Chilling extracts: /obj/item/slimecross/chilling/sepia colour = SLIME_TYPE_SEPIA effect_desc = "Touching someone with it adds/removes them from a list. Activating the extract stops time for 30 seconds, and everyone on the list is immune, except the user." - var/list/allies = list() + var/list/slimepals = list() /obj/item/slimecross/chilling/sepia/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!isliving(interacting_with)) return NONE user.do_attack_animation(interacting_with) - if(interacting_with in allies) - allies -= interacting_with + if(interacting_with in slimepals) + slimepals -= interacting_with to_chat(user, span_notice("You unlink [src] with [interacting_with].")) else - allies += interacting_with + slimepals += interacting_with to_chat(user, span_notice("You link [src] with [interacting_with].")) return ITEM_INTERACT_SUCCESS /obj/item/slimecross/chilling/sepia/do_effect(mob/user) user.visible_message(span_warning("[src] shatters, freezing time itself!")) - allies -= user //support class - new /obj/effect/timestop(get_turf(user), 2, 300, allies) + slimepals -= user //support class + new /obj/effect/timestop(get_turf(user), 2, 300, slimepals) ..() /obj/item/slimecross/chilling/cerulean diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 34eb5582c51..3ec48ef314a 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -188,7 +188,7 @@ GLOBAL_LIST_INIT(slime_extract_auto_activate_reactions, init_slime_auto_activate user.visible_message(span_warning("[user] starts shaking!"),span_notice("Your [name] starts pulsing gently...")) if(do_after(user, 4 SECONDS, target = user)) var/mob/living/spawned_mob = create_random_mob(user.drop_location(), FRIENDLY_SPAWN) - spawned_mob.faction |= FACTION_NEUTRAL + spawned_mob.add_faction(FACTION_NEUTRAL) playsound(user, 'sound/effects/splat.ogg', 50, TRUE) user.visible_message(span_warning("[user] spits out [spawned_mob]!"), span_notice("You spit out [spawned_mob]!")) return 300 @@ -198,9 +198,9 @@ GLOBAL_LIST_INIT(slime_extract_auto_activate_reactions, init_slime_auto_activate if(do_after(user, 5 SECONDS, target = user)) var/mob/living/spawned_mob = create_random_mob(user.drop_location(), HOSTILE_SPAWN) if(!user.combat_mode) - spawned_mob.faction |= FACTION_NEUTRAL + spawned_mob.add_faction(FACTION_NEUTRAL) else - spawned_mob.faction |= FACTION_SLIME + spawned_mob.add_faction(FACTION_SLIME) playsound(user, 'sound/effects/splat.ogg', 50, TRUE) user.visible_message(span_warning("[user] spits out [spawned_mob]!"), span_warning("You spit out [spawned_mob]!")) return 600 @@ -871,7 +871,7 @@ GLOBAL_LIST_INIT(slime_extract_auto_activate_reactions, init_slime_auto_activate user.mind.transfer_to(switchy_mob) SEND_SIGNAL(switchy_mob, COMSIG_SIMPLEMOB_TRANSFERPOTION, user) - switchy_mob.faction = user.faction.Copy() + SET_FACTION_AND_ALLIES_FROM( switchy_mob, user) switchy_mob.copy_languages(user, LANGUAGE_MIND) user.death() to_chat(switchy_mob, span_notice("In a quick flash, you feel your consciousness flow into [switchy_mob]!")) diff --git a/code/modules/spells/spell_types/conjure/simian.dm b/code/modules/spells/spell_types/conjure/simian.dm index 1f1074cb981..fe5aad9fd7c 100644 --- a/code/modules/spells/spell_types/conjure/simian.dm +++ b/code/modules/spells/spell_types/conjure/simian.dm @@ -42,17 +42,17 @@ var/mob/living/cast_mob = cast_on if(!istype(cast_mob)) return - if(FACTION_MONKEY in cast_mob.faction) + if(cast_mob.has_faction(FACTION_MONKEY)) return - cast_mob.faction |= FACTION_MONKEY + cast_mob.add_faction(FACTION_MONKEY) addtimer(CALLBACK(src, PROC_REF(remove_monky_faction), cast_mob), 1 MINUTES) /datum/action/cooldown/spell/conjure/simian/proc/remove_monky_faction(mob/cast_mob) - cast_mob.faction -= FACTION_MONKEY + cast_mob.remove_faction(FACTION_MONKEY) /datum/action/cooldown/spell/conjure/simian/post_summon(atom/summoned_object, atom/cast_on) var/mob/living/alive_dude = summoned_object - alive_dude.faction |= list(FACTION_MONKEY) + alive_dude.add_faction(list(FACTION_MONKEY)) if(ismonkey(alive_dude)) equip_monky(alive_dude) return diff --git a/code/modules/spells/spell_types/pointed/dominate.dm b/code/modules/spells/spell_types/pointed/dominate.dm index f4dd50bb576..02d130d766a 100644 --- a/code/modules/spells/spell_types/pointed/dominate.dm +++ b/code/modules/spells/spell_types/pointed/dominate.dm @@ -30,7 +30,7 @@ return FALSE if(!animal.compare_sentience_type(SENTIENCE_ORGANIC)) // Will also return false if not a basic or simple mob, which are the only two we want anyway return FALSE - if(FACTION_CULT in animal.faction) + if(animal.has_faction(FACTION_CULT)) return FALSE if(HAS_TRAIT(animal, TRAIT_HOLY)) return FALSE @@ -46,6 +46,6 @@ var/turf/cast_turf = get_turf(cast_on) cast_on.add_atom_colour("#990000", FIXED_COLOUR_PRIORITY) - cast_on.faction |= FACTION_CULT + cast_on.add_faction(FACTION_CULT) playsound(cast_turf, 'sound/effects/ghost.ogg', 100, TRUE) new /obj/effect/temp_visual/cult/sac(cast_turf) diff --git a/code/modules/spells/spell_types/projectile/juggernaut.dm b/code/modules/spells/spell_types/projectile/juggernaut.dm index 4bfb1dd728e..151b5cedc85 100644 --- a/code/modules/spells/spell_types/projectile/juggernaut.dm +++ b/code/modules/spells/spell_types/projectile/juggernaut.dm @@ -15,5 +15,5 @@ /datum/action/cooldown/spell/basic_projectile/juggernaut/fire_projectile(atom/target, mob/caster) var/obj/projectile/magic/aoe/juggernaut/to_fire = ..() - to_fire.ignored_factions = caster.faction + to_fire.ignored_factions = caster.get_faction() return to_fire diff --git a/code/modules/unit_tests/mob_faction.dm b/code/modules/unit_tests/mob_faction.dm index be667de731d..39d6e4d7fcd 100644 --- a/code/modules/unit_tests/mob_faction.dm +++ b/code/modules/unit_tests/mob_faction.dm @@ -10,9 +10,108 @@ ) ignored += typesof(/mob/eye/imaginary_friend) ignored += typesof(/mob/living/silicon/robot/model) - ignored += typesof(/mob/eye/camera/remote/base_construction) - ignored += typesof(/mob/eye/camera/remote/shuttle_docker) + ignored += typesof(/mob/eye/camera/remote) // These will always just qdel themselves immediately if there was no creator arg + + /// We are going to add a 'test faction' here, something that won't be on any existing mobs + var/test_faction = "about_to_be_poofed" + /// Same as test_faction but for testing the list version of the proc + var/list/test_factions = list("no_bugs_here", "look_over there") + /// We are going to add a 'test ally' here, something that won't be on any existing mobs + var/test_ally = "mybffjill" + /// Same as test_ally but for testing the list version of the proc + var/list/test_allies = list("mybffrose", "plank") + + // Bare sanity checks - do the procs work? + var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent) + var/mob/living/carbon/human/dummy_two = allocate(/mob/living/carbon/human/consistent) + dummy_two.set_faction(list("copymeiguess")) + + if (dummy.faction_check_atom(dummy_two)) + TEST_FAIL("faction_check_atom() returned TRUE when it should have returned FALSE.") + // set_faction() + dummy.set_faction(test_factions) + if (dummy.get_faction() != string_list(test_factions)) + TEST_FAIL("set_faction() failed to set the factions to the correct list! Instead: ([jointext(dummy.get_faction(), ", ")]). Ensure that you are using string_list().") + // remove_faction() - list arg + dummy.remove_faction(test_factions) + if (!isnull(dummy.get_faction())) + TEST_FAIL("remove_faction() did not remove the factions properly, they should be null! Instead: ([jointext(dummy.get_faction(), ", ")]). Ensure that you are using string_list().") + // add_faction() - string arg + dummy.add_faction(test_faction) + if (dummy.get_faction() != string_list(list(test_faction))) + TEST_FAIL("add_faction() did not add the test faction! Instead: ([jointext(dummy.get_faction(), ", ")]). Ensure that you are using string_list().") + // remove_faction() - string arg + dummy.remove_faction(test_faction) + if (!isnull(dummy.get_faction())) + TEST_FAIL("remove_faction() did not remove the test faction! Instead: ([jointext(dummy.get_faction(), ", ")]). Ensure that you are using string_list().") + + // set_allies() + dummy.set_allies(test_allies) + if (!dummy.has_ally(test_allies, match_all = TRUE)) + TEST_FAIL("set_faction() failed to set the allies to the correct list! Instead: ([jointext(dummy.allies, ", ")]). Ensure that you are using string_list().") + // remove_ally() - list arg + dummy.remove_ally(test_allies) + if (!isnull(dummy.allies)) + TEST_FAIL("remove_ally() did not remove the allies properly, they should be null! Instead: ([jointext(dummy.allies, ", ")]). Ensure that you are using string_list().") + // add_ally() - string arg + dummy.add_ally(test_ally) + if (!dummy.has_ally(test_ally)) + TEST_FAIL("add_ally() did not add the test ally! Instead: ([jointext(dummy.allies, ", ")]). Ensure that you are using string_list().") + // remove_ally() - string arg + dummy.remove_ally(test_ally) + if (!isnull(dummy.allies)) + TEST_FAIL("remove_ally() did not remove the test ally! Instead: ([jointext(dummy.allies, ", ")]). Ensure that you are using string_list().") + + dummy.add_ally(dummy) // put the dummy's orgiginal ally (itself) back + + // Test adding the factions and allies of another mob + APPLY_FACTION_AND_ALLIES_FROM(dummy, dummy_two) + + // Their allies should match + if (!(dummy.has_ally(REF(dummy)) && dummy.has_ally(REF(dummy_two)))) + TEST_FAIL("apply_faction_and_allies() failed to add the correct allies. Should have both dummy's refs. Instead: ([jointext(dummy.allies, ", ")])") + // Test the list arg version too + else if (!dummy.has_ally(list(REF(dummy), REF(dummy_two)))) + TEST_FAIL("has_ally() failed to return TRUE when passed a list of allies.") + if (!dummy.faction_check_atom(dummy_two)) + TEST_FAIL("faction_check_atom() returned FALSE when it should have returned TRUE.") + + // Their faction should match + if (!(dummy.has_faction("copymeiguess"))) + TEST_FAIL("apply_faction_and_allies() failed to add the correct faction. Should have the second dummy's faction. Instead: ([jointext(dummy.get_faction(), ", ")])") + // Test the list arg version too + else if (!dummy.has_faction(dummy_two.get_faction())) + TEST_FAIL("has_faction() failed to return TRUE when passed a list of allies.") + + // Test the setting version - should be an exact match + SET_FACTION_AND_ALLIES_FROM(dummy, dummy_two) + + if (!dummy.has_ally(dummy_two) || dummy.has_ally(dummy)) + TEST_FAIL("set_faction_and_allies() failed to add the correct allies Should have just the second dummy's ref. Instead: ([jointext(dummy.get_faction(), ", ")])") + if (!(dummy.has_faction("copymeiguess"))) + TEST_FAIL("set_faction_and_allies() failed to add the correct faction. Should have the second dummy's faction. Instead: ([jointext(dummy.get_faction(), ", ")])") + for (var/mob_type in typesof(/mob) - ignored) var/mob/mob_instance = allocate(mob_type) - if(!islist(mob_instance.faction)) - TEST_FAIL("[mob_type] faction variable is not a list") + var/list/mob_faction = mob_instance.get_faction() + if(isnull(mob_faction)) + qdel(mob_instance) + continue + else if (!islist(mob_faction)) + TEST_FAIL("[mob_type] faction variable is not a list or null! Only lazy lists are supported currently (currently set to [mob_faction]).") + qdel(mob_instance) + continue + else if (!LAZYLEN(mob_faction)) + TEST_FAIL("[mob_type] faction variable is an empty list! Set to null instead, faction lists are lazy.") + qdel(mob_instance) + continue + + /// Sanity - Let's test that no mobs are mutating or not being assigned a string list somewhere along the line + var/expected_faction = string_list(mob_faction) + if(mob_faction != expected_faction) + TEST_FAIL("Faction list does not match the cached string_list()! Make sure you are using the add_faction and remove_faction procs, \ + and not editing the faction list directly anywhere. Also make sure that the faction list is getting string_list()'d in the first place. \ + e.g. your mob might be short circuiting Initialize() (or returning INITIALIZE_HINT_QDEL). Either add string_list() its faction list, \ + or add its type to the ignored list if appropriate. \ + mob: [mob_instance]([mob_instance.type]) current factions: ([jointext(mob_faction, ", ")]) expected factions: ([jointext(expected_faction, ", ")])") + qdel(mob_instance)