diff --git a/_maps/map_files/RandomZLevels/spacehotel.dmm b/_maps/map_files/RandomZLevels/spacehotel.dmm index 73d86c17201..56df786fab5 100644 --- a/_maps/map_files/RandomZLevels/spacehotel.dmm +++ b/_maps/map_files/RandomZLevels/spacehotel.dmm @@ -3125,7 +3125,6 @@ }, /area/awaymission/spacehotel/kitchen) "gE" = ( -/mob/living/carbon/human/interactive/away/hotel/chef, /turf/unsimulated/floor{ icon_state = "cafeteria" }, @@ -3278,7 +3277,6 @@ }, /area/awaymission/spacehotel) "ha" = ( -/mob/living/carbon/human/interactive/away/hotel/bartender, /turf/unsimulated/floor{ icon_state = "whiteyellowfull" }, @@ -4135,9 +4133,6 @@ /turf/unsimulated/floor/carpet, /area/awaymission/spacehotel) "jm" = ( -/obj/effect/spawner/snpc_squad{ - squad_type = /mob/living/carbon/human/interactive/away/hotel/guard - }, /turf/unsimulated/floor/carpet, /area/awaymission/spacehotel) "jn" = ( @@ -4489,7 +4484,6 @@ /obj/structure/chair{ dir = 8 }, -/mob/living/carbon/human/interactive/away/hotel/concierge, /turf/unsimulated/floor/carpet, /area/awaymission/spacehotel/reception) "kk" = ( diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index ba4bf0090c7..a8c6b4bd5e8 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -52,12 +52,6 @@ #define GRAB_UPGRADING 4 #define GRAB_KILL 5 - -//Hostile Mob AI Status -#define AI_ON 1 -#define AI_IDLE 2 -#define AI_OFF 3 - //Attack types for checking shields/hit reactions #define MELEE_ATTACK 1 diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 0f05c08b2f7..284b0e4d745 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -94,6 +94,13 @@ #define APPEARANCE_ALL_BODY APPEARANCE_ALL_HAIR|APPEARANCE_HEAD_ACCESSORY|APPEARANCE_MARKINGS|APPEARANCE_BODY_ACCESSORY|APPEARANCE_ALT_HEAD #define APPEARANCE_ALL 32767 +//If you add a new status, be sure to add a list for it to the simple_animals global in _globalvars/lists/mobs.dm +//Hostile Mob AI Status +#define AI_ON 1 +#define AI_IDLE 2 +#define AI_OFF 3 +#define AI_Z_OFF 4 + // Intents #define INTENT_HELP "help" #define INTENT_DISARM "disarm" diff --git a/code/__DEFINES/snpc.dm b/code/__DEFINES/snpc.dm deleted file mode 100644 index 8d4768005cd..00000000000 --- a/code/__DEFINES/snpc.dm +++ /dev/null @@ -1,23 +0,0 @@ -#define SNPC_MAX_RANGE_FIND 32 -#define SNPC_MIN_RANGE_FIND 16 -#define SNPC_FUZZY_CHANCE_HIGH 85 -#define SNPC_FUZZY_CHANCE_LOW 50 -#define SNPC_CHANCE_TALK 15 - -#define SNPC_BRUTE 1 -#define SNPC_STEALTH 2 -#define SNPC_MARTYR 3 -#define SNPC_PSYCHO 4 - -#define SNPC_INTERACTING 2 -#define SNPC_TRAVEL 4 -#define SNPC_FIGHTING 8 -#define SNPC_SPECIAL 16 - -#define TRAIT_ROBUST 2 -#define TRAIT_UNROBUST 4 -#define TRAIT_SMART 8 -#define TRAIT_DUMB 16 -#define TRAIT_MEAN 32 -#define TRAIT_FRIENDLY 64 -#define TRAIT_THIEVING 128 \ No newline at end of file diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 551b729028e..b6fcae25061 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -22,8 +22,7 @@ GLOBAL_LIST_INIT(living_mob_list, list()) //List of all alive mobs, including GLOBAL_LIST_INIT(dead_mob_list, list()) //List of all dead mobs, including clientless. Excludes /mob/new_player GLOBAL_LIST_INIT(respawnable_list, list()) //List of all mobs, dead or in mindless creatures that still be respawned. GLOBAL_LIST_INIT(non_respawnable_keys, list()) //List of ckeys that are excluded from respawning for remainder of round. -GLOBAL_LIST_INIT(simple_animal_list, list()) //List of all simple animals, including clientless -GLOBAL_LIST_INIT(snpc_list, list()) //List of all snpc's, including clientless +GLOBAL_LIST_INIT(simple_animals, list(list(), list(), list(), list())) //One for each AI_* status define, List of all simple animals, including clientless GLOBAL_LIST_INIT(bots_list, list()) //List of all bots(beepsky, medibots,etc) GLOBAL_LIST_INIT(med_hud_users, list()) diff --git a/code/controllers/Processes/npcai.dm b/code/controllers/Processes/npcai.dm deleted file mode 100644 index 127429efd34..00000000000 --- a/code/controllers/Processes/npcai.dm +++ /dev/null @@ -1,41 +0,0 @@ -var/global/datum/controller/process/npcai/npcai_master - -/datum/controller/process/npcai - var/current_cycle - -/datum/controller/process/npcai/setup() - name = "npc ai" - schedule_interval = 20 // every 2 seconds - start_delay = 16 - log_startup_progress("NPC ticker starting up.") - -/datum/controller/process/npcai/started() - ..() - if(!GLOB.simple_animal_list) - GLOB.simple_animal_list = list() - if(!GLOB.snpc_list) - GLOB.snpc_list = list() - -/datum/controller/process/npcai/statProcess() - ..() - stat(null, "[GLOB.simple_animal_list.len] simple animals") - stat(null, "[GLOB.snpc_list.len] SNPC's") - -/datum/controller/process/npcai/doWork() - for(last_object in GLOB.simple_animal_list) - var/mob/living/simple_animal/M = last_object - if(istype(M) && !QDELETED(M)) - if(!M.client && M.stat == CONSCIOUS) - try - M.process_ai() - catch(var/exception/e) - catchException(e, M) - SCHECK - else - catchBadType(M) - GLOB.simple_animal_list -= M - - current_cycle++ - - -DECLARE_GLOBAL_CONTROLLER(npcai, npcai_master) diff --git a/code/controllers/subsystem/idlenpcpool.dm b/code/controllers/subsystem/idlenpcpool.dm new file mode 100644 index 00000000000..2dad0abca0f --- /dev/null +++ b/code/controllers/subsystem/idlenpcpool.dm @@ -0,0 +1,41 @@ +SUBSYSTEM_DEF(idlenpcpool) + name = "Idling NPC Pool" + flags = SS_POST_FIRE_TIMING|SS_BACKGROUND + priority = FIRE_PRIORITY_IDLE_NPC + wait = 60 + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + + var/list/currentrun = list() + var/static/list/idle_mobs_by_zlevel[][] + +/datum/controller/subsystem/idlenpcpool/stat_entry() + var/list/idlelist = GLOB.simple_animals[AI_IDLE] + var/list/zlist = GLOB.simple_animals[AI_Z_OFF] + ..("IdleNPCS:[idlelist.len]|Z:[zlist.len]") + +/datum/controller/subsystem/idlenpcpool/Initialize(start_timeofday) + idle_mobs_by_zlevel = new /list(world.maxz,0) + return ..() + +/datum/controller/subsystem/idlenpcpool/fire(resumed = FALSE) + if(!resumed) + var/list/idlelist = GLOB.simple_animals[AI_IDLE] + src.currentrun = idlelist.Copy() + + //cache for sanic speed (lists are references anyways) + var/list/currentrun = src.currentrun + + while(currentrun.len) + var/mob/living/simple_animal/SA = currentrun[currentrun.len] + --currentrun.len + if(!SA) + GLOB.simple_animals[AI_IDLE] -= SA + continue + + if(!SA.ckey) + if(SA.stat != DEAD) + SA.handle_automated_movement() + if(SA.stat != DEAD) + SA.consider_wakeup() + if(MC_TICK_CHECK) + return \ No newline at end of file diff --git a/code/controllers/subsystem/mobs.dm b/code/controllers/subsystem/mobs.dm index d19396af767..20061d7489b 100644 --- a/code/controllers/subsystem/mobs.dm +++ b/code/controllers/subsystem/mobs.dm @@ -1,14 +1,19 @@ SUBSYSTEM_DEF(mobs) name = "Mobs" priority = FIRE_PRIORITY_MOBS - flags = SS_KEEP_TIMING | SS_NO_INIT + flags = SS_KEEP_TIMING runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME var/list/currentrun = list() + var/static/list/clients_by_zlevel[][] /datum/controller/subsystem/mobs/stat_entry() ..("P:[GLOB.mob_list.len]") +/datum/controller/subsystem/mobs/Initialize(start_timeofday) + clients_by_zlevel = new /list(world.maxz,0) + return ..() + /datum/controller/subsystem/mobs/fire(resumed = 0) var/seconds = wait * 0.1 if(!resumed) diff --git a/code/controllers/subsystem/npcai.dm b/code/controllers/subsystem/npcai.dm deleted file mode 100644 index f8fa3a5aa0f..00000000000 --- a/code/controllers/subsystem/npcai.dm +++ /dev/null @@ -1,24 +0,0 @@ -SUBSYSTEM_DEF(npcai) - name = "NPC AI" // Simple AI controller, isolated from the SNPC one (NPCPool). - flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND - priority = FIRE_PRIORITY_NPC - runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - var/list/simple_animal_list = list() - -/datum/controller/subsystem/npcai/stat_entry() - ..("SimAnimals:[simple_animal_list.len]") - -/datum/controller/subsystem/npcai/fire(resumed = FALSE) - if(!resumed) - src.simple_animal_list = simple_animal_list.Copy() - for(var/mob/living/simple_animal/M in simple_animal_list) - if(istype(M) && !QDELETED(M)) - if(!M.client && M.stat == CONSCIOUS) - M.process_ai() - if(MC_TICK_CHECK) - return - else - simple_animal_list -= M - -/datum/controller/subsystem/npcai/Recover() - simple_animal_list = SSnpcai.simple_animal_list \ No newline at end of file diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm index b06d33f6f32..0de306b12eb 100644 --- a/code/controllers/subsystem/npcpool.dm +++ b/code/controllers/subsystem/npcpool.dm @@ -1,127 +1,33 @@ -#define PROCESSING_NPCS 0 -#define PROCESSING_DELEGATES 1 -#define PROCESSING_ASSISTANTS 2 - SUBSYSTEM_DEF(npcpool) - name = "NPC Pool" - flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND - priority = FIRE_PRIORITY_NPC - runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + name = "NPC Pool" + flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND + priority = FIRE_PRIORITY_NPC + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - var/list/canBeUsed = list() - var/list/needsDelegate = list() - var/list/needsAssistant = list() - - var/list/processing = list() - var/list/currentrun = list() - var/stage + var/list/currentrun = list() /datum/controller/subsystem/npcpool/stat_entry() - ..("NPCS:[processing.len]|D:[needsDelegate.len]|A:[needsAssistant.len]|U:[canBeUsed.len]") - -/datum/controller/subsystem/npcpool/proc/stop_processing(mob/living/carbon/human/interactive/I) - processing -= I - currentrun -= I - needsDelegate -= I - canBeUsed -= I - needsAssistant -= I + var/list/activelist = GLOB.simple_animals[AI_ON] + ..("SimpleAnimals:[activelist.len]") /datum/controller/subsystem/npcpool/fire(resumed = FALSE) - //bot delegation and coordination systems - //General checklist/Tasks for delegating a task or coordinating it (for SNPCs) - // 1. Bot proximity to task target: if too far, delegate, if close, coordinate - // 2. Bot Health/status: check health with bots in local area, if their health is higher, delegate task to them, else coordinate - // 3. Process delegation: if a bot (or bots) has been delegated, assign them to the task. - // 4. Process coordination: if a bot(or bots) has been asked to coordinate, assign them to help. - // 5. Do all assignments: goes through the delegated/coordianted bots and assigns the right variables/tasks to them. - if (!resumed) - currentrun = processing.Copy() - stage = PROCESSING_NPCS - //cache for sanic speed (lists are references anyways) - var/list/cachecurrentrun = currentrun - var/list/cachecanBeUsed = canBeUsed + if(!resumed) + var/list/activelist = GLOB.simple_animals[AI_ON] + src.currentrun = activelist.Copy() - if(stage == PROCESSING_NPCS) - while(cachecurrentrun.len) - var/mob/living/carbon/human/interactive/thing = cachecurrentrun[cachecurrentrun.len] - --cachecurrentrun.len + var/list/currentrun = src.currentrun - thing.InteractiveProcess() + while(currentrun.len) + var/mob/living/simple_animal/SA = currentrun[currentrun.len] + --currentrun.len - var/checkInRange = view(SNPC_MAX_RANGE_FIND,thing) - if(thing.IsDeadOrIncap(FALSE) || !(locate(thing.TARGET) in checkInRange)) - needsDelegate += thing - else if(thing.doing & SNPC_FIGHTING) - needsAssistant += thing - else - cachecanBeUsed += thing - - if (MC_TICK_CHECK) - return - stage = PROCESSING_DELEGATES - cachecurrentrun = needsDelegate //localcache - currentrun = cachecurrentrun - - if(stage == PROCESSING_DELEGATES) - while(cachecurrentrun.len && cachecanBeUsed.len) - var/mob/living/carbon/human/interactive/check = cachecurrentrun[cachecurrentrun.len] - var/mob/living/carbon/human/interactive/candidate = cachecanBeUsed[cachecanBeUsed.len] - --cachecurrentrun.len - - var/helpProb = 0 - var/list/chfac = check.faction - var/list/canfac = candidate.faction - var/facCount = LAZYLEN(chfac) * LAZYLEN(canfac) - - for(var/C in chfac) - if(C in canfac) - helpProb = min(100,helpProb + 25) - if(helpProb >= 100) - break - - if(facCount == 1 && helpProb) - helpProb = 100 - - if(prob(helpProb) && candidate.takeDelegate(check)) - --cachecanBeUsed.len - candidate.change_eye_color(255, 0, 0) - candidate.update_icons() - - if(MC_TICK_CHECK) - return - stage = PROCESSING_ASSISTANTS - cachecurrentrun = needsAssistant //localcache - currentrun = cachecurrentrun - - //no need for the stage check - - while(cachecurrentrun.len && cachecanBeUsed.len) - var/mob/living/carbon/human/interactive/check = cachecurrentrun[cachecurrentrun.len] - var/mob/living/carbon/human/interactive/candidate = cachecanBeUsed[cachecanBeUsed.len] - --cachecurrentrun.len - - var/helpProb = 0 - var/list/chfac = check.faction - var/list/canfac = candidate.faction - var/facCount = LAZYLEN(chfac) * LAZYLEN(canfac) - - for(var/C in chfac) - if(C in canfac) - helpProb = min(100,helpProb + 25) - if(helpProb >= 100) - break - - if(facCount == 1 && helpProb) - helpProb = 100 - - if(prob(helpProb) && candidate.takeDelegate(check,FALSE)) - --cachecanBeUsed.len - candidate.change_eye_color(255, 255, 0) - candidate.update_icons() - - if(!cachecurrentrun.len || MC_TICK_CHECK) //don't change SS state if it isn't necessary - return - -/datum/controller/subsystem/npcpool/Recover() - processing = SSnpcpool.processing \ No newline at end of file + if(!SA.ckey && !SA.notransform) + if(SA.stat != DEAD) + SA.handle_automated_movement() + if(SA.stat != DEAD) + SA.handle_automated_action() + if(SA.stat != DEAD) + SA.handle_automated_speech() + if(MC_TICK_CHECK) + return \ No newline at end of file diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index eeef65bd2e2..b23c9fe030a 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -80,9 +80,9 @@ if("Mob") debug_variables(SSmobs) feedback_add_details("admin_verb","DMob") - if("NPC AI") - debug_variables(SSnpcai) - feedback_add_details("admin_verb","DNPCAI") + if("NPC Pool") + debug_variables(SSnpcpool) + feedback_add_details("admin_verb","DNPCPool") if("Shuttle") debug_variables(SSshuttle) feedback_add_details("admin_verb","DShuttle") diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 2d3f01a139d..e962365451e 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -219,7 +219,12 @@ destination.Entered(src) for(var/atom/movable/AM in destination) AM.Crossed(src) - + var/turf/oldturf = get_turf(old_loc) + var/turf/destturf = get_turf(destination) + var/old_z = (oldturf ? oldturf.z : null) + var/dest_z = (destturf ? destturf.z : null) + if(old_z != dest_z) + onTransitZ(old_z, dest_z) if(isturf(destination) && opacity) var/turf/new_loc = destination new_loc.reconsider_lights() @@ -232,6 +237,11 @@ return 1 +/atom/movable/proc/onTransitZ(old_z,new_z) + for(var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care. + var/atom/movable/AM = item + AM.onTransitZ(old_z,new_z) + /mob/living/forceMove(atom/destination) if(buckled) addtimer(CALLBACK(src, .proc/check_buckled), 1, TIMER_UNIQUE) diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm index bd934eefb44..0482a8e19ae 100644 --- a/code/game/gamemodes/blob/blobs/core.dm +++ b/code/game/gamemodes/blob/blobs/core.dm @@ -135,4 +135,9 @@ else log_debug("/obj/structure/blob/core/proc/lateblobcheck: Blob core lacks a overmind.mind.") else - log_debug("/obj/structure/blob/core/proc/lateblobcheck: Blob core lacks an overmind.") \ No newline at end of file + log_debug("/obj/structure/blob/core/proc/lateblobcheck: Blob core lacks an overmind.") + +/obj/structure/blob/core/onTransitZ(old_z, new_z) + if(overmind && is_station_level(new_z)) + overmind.forceMove(get_turf(src)) + return ..() \ No newline at end of file diff --git a/code/game/gamemodes/miniantags/abduction/gland.dm b/code/game/gamemodes/miniantags/abduction/gland.dm index fbe1774525f..2b0162829e1 100644 --- a/code/game/gamemodes/miniantags/abduction/gland.dm +++ b/code/game/gamemodes/miniantags/abduction/gland.dm @@ -320,69 +320,6 @@ for(var/mob/living/carbon/human/H in oview(3,owner)) //Blood decals for simple animals would be neat. aka Carp with blood on it. H.add_mob_blood(owner) -/obj/item/organ/internal/heart/gland/bodysnatch - cooldown_low = 600 - cooldown_high = 600 - human_only = 1 - uses = 1 - -/obj/item/organ/internal/heart/gland/bodysnatch/activate() - to_chat(owner, "You feel something moving around inside you...") - //spawn cocoon with clone greytide snpc inside - if(ishuman(owner)) - var/obj/effect/cocoon/abductor/C = new (get_turf(owner)) - C.Copy(owner) - C.Start() - owner.adjustBruteLoss(40) - owner.add_splatter_floor() - -/obj/effect/cocoon/abductor - name = "slimy cocoon" - desc = "Something is moving inside." - icon = 'icons/effects/effects.dmi' - icon_state = "cocoon_large3" - color = rgb(10,120,10) - density = 1 - var/hatch_time = 0 - -/obj/effect/cocoon/abductor/proc/Copy(mob/living/carbon/human/H) - var/mob/living/carbon/human/interactive/greytide/clone = new(src) - var/datum/dna/owner_dna = H.dna - clone.rename_character(clone.name, owner_dna.real_name) - clone.set_species(owner_dna.species.type) - clone.dna = owner_dna.Clone() - clone.body_accessory = H.body_accessory - domutcheck(clone) - - for(var/obj/item/I in clone) - if(istype(I, /obj/item/implant)) - continue - if(istype(I, /obj/item/organ)) - continue - qdel(I) - - //There's no define for this / get all items ? - var/list/slots = list(slot_back,slot_w_uniform,slot_wear_suit,\ - slot_wear_mask,slot_head,slot_shoes,slot_gloves,slot_l_ear,slot_r_ear,\ - slot_glasses,slot_belt,slot_s_store,slot_l_store,slot_r_store,slot_wear_id,slot_wear_pda) - - for(var/slot in slots) - var/obj/item/I = H.get_item_by_slot(slot) - if(I) - clone.equip_to_slot_or_del(new I.type(clone), slot) - -/obj/effect/cocoon/abductor/proc/Start() - hatch_time = world.time + 600 - START_PROCESSING(SSobj, src) - -/obj/effect/cocoon/abductor/process() - if(world.time > hatch_time) - STOP_PROCESSING(SSobj, src) - for(var/mob/M in contents) - src.visible_message("[src] hatches!") - M.forceMove(get_turf(src)) - qdel(src) - /obj/item/organ/internal/heart/gland/plasma cooldown_low = 1200 diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index d0872fa8f93..dc4b9124d77 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -741,6 +741,8 @@ throw_item.throw_at(target, 16, 3, src) visible_message("[src] launches [throw_item.name] at [target.name]!") +/obj/machinery/vending/onTransitZ() + return /* * Vending machine types */ diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 6b4072a800b..4a455cd8e5d 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -72,7 +72,6 @@ var/list/admin_verbs_admin = list( /client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */ /client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */ /client/proc/debug_variables, - /client/proc/show_snpc_verbs, /client/proc/reset_all_tcs, /*resets all telecomms scripts*/ /client/proc/toggle_mentor_chat, /client/proc/toggle_advanced_interaction, /*toggle admin ability to interact with not only machines, but also atoms such as buttons and doors*/ @@ -216,11 +215,6 @@ var/list/admin_verbs_proccall = list( /client/proc/callproc_datum, /client/proc/SDQL2_query ) -var/list/admin_verbs_snpc = list( - /client/proc/resetSNPC, - /client/proc/customiseSNPC, - /client/proc/hide_snpc_verbs -) var/list/admin_verbs_ticket = list( /client/proc/openAdminTicketUI, /client/proc/toggleticketlogs, @@ -291,8 +285,6 @@ var/list/admin_verbs_ticket = list( admin_verbs_proccall, admin_verbs_show_debug_verbs, /client/proc/readmin, - admin_verbs_snpc, - /client/proc/hide_snpc_verbs, admin_verbs_ticket ) @@ -1013,28 +1005,6 @@ var/list/admin_verbs_ticket = list( log_admin("[key_name(usr)] told everyone to man up and deal with it.") message_admins("[key_name_admin(usr)] told everyone to man up and deal with it.") -/client/proc/show_snpc_verbs() - set name = "Show SNPC Verbs" - set category = "Admin" - - if(!check_rights(R_ADMIN)) - return - - verbs += admin_verbs_snpc - verbs -= /client/proc/show_snpc_verbs - to_chat(src, "SNPC verbs have been toggled on.") - -/client/proc/hide_snpc_verbs() - set name = "Hide SNPC Verbs" - set category = "Admin" - - if(!check_rights(R_ADMIN)) - return - - verbs -= admin_verbs_snpc - verbs += /client/proc/show_snpc_verbs - to_chat(src, "SNPC verbs have been toggled off.") - /client/proc/toggle_advanced_interaction() set name = "Toggle Advanced Admin Interaction" set category = "Admin" diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 36c0e5cf90d..970defdd672 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -390,10 +390,7 @@ /datum/admins/proc/check_antagonists_line(mob/M, caption = "", close = 1) var/logout_status - if(istype(M, /mob/living/carbon/human/interactive)) - logout_status = " (snpc)" - else - logout_status = M.client ? "" : " (logged out)" + logout_status = M.client ? "" : " (logged out)" var/dname = M.real_name if(!dname) dname = M diff --git a/code/modules/awaymissions/mission_code/spacehotel.dm b/code/modules/awaymissions/mission_code/spacehotel.dm index 0328dea5b53..fc8b4f4d260 100644 --- a/code/modules/awaymissions/mission_code/spacehotel.dm +++ b/code/modules/awaymissions/mission_code/spacehotel.dm @@ -152,14 +152,6 @@ /obj/machinery/door/unpowered/hotel_door/autoclose() if(!density && !operating && autoclose) close() - -/obj/machinery/door/unpowered/hotel_door/emag_act(mob/user) - if(isliving(user) && density) - var/obj/effect/hotel_controller/H - if(H.controller) - H.controller.deploy_sec(user) - ..() - /obj/item/card/hotel_card name = "Key Card" icon_state = "guest" @@ -283,20 +275,4 @@ spawn(300) if(D.occupant == deadbeat) // they still haven't checked out... - deploy_sec(deadbeat) - checkout(roomid) - -/obj/effect/hotel_controller/proc/deploy_sec(mob/living/target) - if(!istype(target) || !istype(get_area(target), /area/awaymission/spacehotel)) - return - - var/list/secs[0] - for(var/mob/living/carbon/human/interactive/away/hotel/guard/M in get_area(src)) - if(!M.retal) - secs += M - var/mob/living/carbon/human/interactive/away/hotel/guard/S = safepick(secs) - if(!S) - return - - S.retal_target = target - S.retal = 1 + checkout(roomid) \ No newline at end of file diff --git a/code/modules/awaymissions/mission_code/spacehotel_npcs.dm b/code/modules/awaymissions/mission_code/spacehotel_npcs.dm deleted file mode 100644 index 2a524ab738c..00000000000 --- a/code/modules/awaymissions/mission_code/spacehotel_npcs.dm +++ /dev/null @@ -1,132 +0,0 @@ -/mob/living/carbon/human/interactive/away/hotel - away_area = /area/awaymission/spacehotel - override_under = /obj/item/clothing/under/mafia - chattyness = SNPC_CHANCE_TALK / 4 - -/mob/living/carbon/human/interactive/away/hotel/Initialize(mapload) - . = ..(mapload, /datum/species/skrell) - -/mob/living/carbon/human/interactive/away/hotel/doSetup() - ..() - MYID.access = list(access_syndicate) - RPID.access = list(access_syndicate) - -/mob/living/carbon/human/interactive/away/hotel/guard - default_job = /datum/job/officer - -/mob/living/carbon/human/interactive/away/hotel/guard/doSetup() - ..("Guard") - - // anti-pinata cheese - var/obj/item/implant/dust/D = new /obj/item/implant/dust(src) - D.implant(src) - - for(var/obj/item/I in get_all_slots()) - I.flags |= NODROP - -/mob/living/carbon/human/interactive/away/hotel/guard/KnockOut() - // you'll never take me alive (this triggers the implant) - emote("deathgasp") - if(stat != DEAD) - // mission failed. we'll get em next time - ..() - -/mob/living/carbon/human/interactive/away/hotel/chef - default_job = /datum/job/chef - away_area = /area/awaymission/spacehotel/kitchen - override_under = /obj/item/clothing/under/mafia/vest - -/mob/living/carbon/human/interactive/away/hotel/bartender - default_job = /datum/job/bartender - override_under = /obj/item/clothing/under/mafia/vest - -/mob/living/carbon/human/interactive/away/hotel/concierge - override_under = /obj/item/clothing/under/mafia/white - away_area = /area/awaymission/spacehotel/reception - var/list/known_guests[0] - var/obj/effect/hotel_controller/hotel - var/obj/item/card/id/last_seen_id = null - -/mob/living/carbon/human/interactive/away/hotel/concierge/random() - ..() - equip_or_collect(new /obj/item/clipboard(src), slot_l_hand) - -/mob/living/carbon/human/interactive/away/hotel/concierge/doSetup() - ..("Concierge") - -/mob/living/carbon/human/interactive/away/hotel/concierge/setup_job() - favoured_types = list(/obj/item/paper, /obj/item/clipboard) - functions += list("stamping", "concierge") - restrictedJob = 1 - -/mob/living/carbon/human/interactive/away/hotel/concierge/proc/concierge() - if(!hotel) - hotel = hotel.controller - if(!hotel) - return - - var/verbs_use = pick_list(speak_file, "verbs_use") - var/verbs_touch = pick_list(speak_file, "verbs_touch") - var/verbs_move = pick_list(speak_file, "verbs_move") - var/nouns_generic = pick_list(speak_file, "nouns_generic") - var/adjective_insult = pick_list(speak_file, "adjective_insult") - var/adjective_objects = pick_list(speak_file, "adjective_objects") - var/adjective_generic = pick_list(speak_file, "adjective_generic") - var/curse_words = pick_list(speak_file, "curse_words") - - var/found = 0 - for(var/mob/living/carbon/human/H in nearby - known_guests) - pointed(H) - known_guests += H - found = 1 - if(found) - say("Welcome to [hotel], [nouns_generic]! Please check in by [ing_verb(verbs_move)] and [ing_verb(verbs_use)] your [adjective_objects] ID onto the table.") - return - - var/obj/item/card/id - var/id_seen = 0 - for(var/obj/item/card/id/I in get_area(src)) - id_seen = 1 - if(I != last_seen_id) - id = I - if(!id_seen) - last_seen_id = null - return - if(!id) - return - var/turf/idloc = get_turf(id) - if(!Adjacent(idloc)) - tryWalk(idloc) - else - // is the last jerk that touched it over here? - var/mob/id_owner - for(var/mob/living/carbon/human/H in nearby) - if(H.ckey == id.fingerprintslast) - id_owner = H - break - - if(!id_owner) - say("Whose card is this?") - pointed(id) - return - - last_seen_id = id - // Checking in or out? - if(id_owner in hotel.guests) - // Check out - say ("Hope you enjoyed your [adjective_objects] stay at our [adjective_generic] hotel!") - hotel.checkout(hotel.guests[id_owner]) - else - // pick a room - var/obj/machinery/door/unpowered/hotel_door/D = safepick(hotel.vacant_rooms) - if(!D) - say("Sorry, all the [adjective_objects] are occupied currently.") - else - // Check in - say("$100 per 10 minutes. The cost will be automatically [past_verb(verbs_touch)] while you're checked in.") - - var/obj/item/card/hotel_card/K = hotel.checkin(D.id, id_owner, id) - if(K) - K.forceMove(idloc) - else - say("Your [adjective_insult] [curse_words] card was rejected.") diff --git a/code/modules/awaymissions/snpc.dm b/code/modules/awaymissions/snpc.dm deleted file mode 100644 index 8d65aa44a92..00000000000 --- a/code/modules/awaymissions/snpc.dm +++ /dev/null @@ -1,85 +0,0 @@ -/mob/living/carbon/human/interactive/away - var/away_area = /area/awaymission // their overriden job area - var/override_under = null // optional type for uniform, else default for job - var/squad_member = 0 // was spawned by squad - var/home_z - -/mob/living/carbon/human/interactive/away/Initialize(mapload) - . = ..() - TRAITS |= TRAIT_ROBUST - faction += "away" - -/mob/living/carbon/human/interactive/away/random() - ..() - // a little hacky but it should prevent doubled uniforms - if(ispath(override_under, /obj/item/clothing/under)) - var/old_under = w_uniform - w_uniform = null - equip_to_slot(new override_under(src), slot_w_uniform) - qdel(old_under) - -/mob/living/carbon/human/interactive/away/doSetup() - ..() - var/datum/data/pda/app/messenger/M = MYPDA.find_program(/datum/data/pda/app/messenger) - M.toff = 1 - -/mob/living/carbon/human/interactive/away/job2area() - return away_area - -/mob/living/carbon/human/interactive/away/doProcess() - if(!home_z) - home_z = get_turf(z) - if(home_z != get_turf(z)) - gib() - ..() - -/obj/effect/spawner/snpc_squad - name = "squad spawner" - icon = 'icons/mob/screen_gen.dmi' - icon_state = "x" - density = 0 - opacity = 0 - invisibility = 101 - var/squad_type = /mob/living/carbon/human/interactive/away - var/squad_size = 3 - - var/global/list/squads[0] - var/list/squad - -/obj/effect/spawner/snpc_squad/New() - START_PROCESSING(SSobj, src) - - squad = squads[squad_type] - if(!squad) - squad = list() - squads[squad_type] = squad - squad += src - -/obj/effect/spawner/snpc_squad/Destroy() - squad = null - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/effect/spawner/snpc_squad/process() - // check squad memebers - var/living = 0 - for(var/mob/living/carbon/human/interactive/away/A in squad) - if(!A.stat) - living++ - else - // see if anyone's looking, if not, despawn - var/can_despawn = 1 - for(var/mob/living/M in viewers(A, world.view + 1)) - if(M.client) - living++ // dead guy that can be seen still takes up a slot - can_despawn = 0 - break - if(can_despawn) - squad -= A - qdel(A) - - // spawn new ones - if(living < squad_size && !length(viewers(src, world.view))) - var/mob/living/carbon/human/interactive/away/A = new squad_type(loc) - squad += A - A.squad_member = 1 diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index cf8b897104c..17262ec4a7a 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -69,7 +69,7 @@ visible_message("[src] crackles and buzzes violently!") /mob/living/simple_animal/hostile/mining_drone/sentience_act() - AIStatus = AI_OFF + ..() check_friendly_fire = 0 /mob/living/simple_animal/hostile/mining_drone/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/mining/satchel_ore_boxdm.dm b/code/modules/mining/satchel_ore_boxdm.dm index 0edb81c8321..43bc1b57226 100644 --- a/code/modules/mining/satchel_ore_boxdm.dm +++ b/code/modules/mining/satchel_ore_boxdm.dm @@ -83,6 +83,9 @@ obj/structure/ore_box/ex_act(severity, target) O.forceMove(loc) CHECK_TICK +/obj/structure/ore_box/onTransitZ() + return + /obj/structure/ore_box/verb/empty_box() set name = "Empty Ore Box" set category = "Object" diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm index 922f3181c27..ca868b5e88f 100644 --- a/code/modules/mob/dead/dead.dm +++ b/code/modules/mob/dead/dead.dm @@ -20,4 +20,4 @@ for(var/datum/light_source/L in light_sources) L.source_atom.update_light() - return 1 + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index aa714f0d527..f16d04e3e86 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -315,15 +315,7 @@ msg += "[p_they(TRUE)] [p_have()] a stupid expression on [p_their()] face.\n" if(get_int_organ(/obj/item/organ/internal/brain)) - if(istype(src, /mob/living/carbon/human/interactive)) - var/mob/living/carbon/human/interactive/auto = src - if(auto.showexaminetext) - msg += "[p_they(TRUE)] [p_are()] appears to be some sort of sick automaton, [p_their()] eyes are glazed over and [p_their()] mouth is slightly agape.\n" - if(auto.debugexamine) - var/dodebug = auto.doing2string(auto.doing) - var/interestdebug = auto.interest2string(auto.interest) - msg += "[p_they(TRUE)] [p_are()] appears to be [interestdebug] and [dodebug].\n" - else if(dna.species.show_ssd) + if(dna.species.show_ssd) if(!key) msg += "[p_they(TRUE)] [p_are()] totally catatonic. The stresses of life in deep-space must have been too much for [p_them()]. Any recovery is unlikely.\n" else if(!client) diff --git a/code/modules/mob/living/carbon/human/interactive/functions.dm b/code/modules/mob/living/carbon/human/interactive/functions.dm deleted file mode 100644 index 06df994df5f..00000000000 --- a/code/modules/mob/living/carbon/human/interactive/functions.dm +++ /dev/null @@ -1,874 +0,0 @@ -/mob/living/carbon/human/interactive/proc/chatter(obj) - var/verbs_use = pick_list(speak_file, "verbs_use") - var/verbs_touch = pick_list(speak_file, "verbs_touch") - var/verbs_move = pick_list(speak_file, "verbs_move") - var/nouns_insult = pick_list(speak_file, "nouns_insult") - var/nouns_generic = pick_list(speak_file, "nouns_generic") - var/nouns_objects = pick_list(speak_file, "nouns_objects") - var/nouns_body = pick_list(speak_file, "nouns_body") - var/adjective_insult = pick_list(speak_file, "adjective_insult") - var/adjective_objects = pick_list(speak_file, "adjective_objects") - var/adjective_generic = pick_list(speak_file, "adjective_generic") - var/curse_words = pick_list(speak_file, "curse_words") - - var/chatmsg = "" - - if(prob(10)) // 10% chance to broadcast it over the radio - chatmsg = ";" - - if(prob(chattyness) || knownStrings.len < 10) // say a generic phrase, otherwise draw from our strings. - if(doing & SNPC_INTERACTING) - if(prob(chattyness)) - chatmsg += pick("This [nouns_objects] is a little [adjective_objects].", - "Well [verbs_use] my [nouns_body], this [nouns_insult] is pretty [adjective_insult].", - "[capitalize(curse_words)], what am I meant to do with this [adjective_insult] [nouns_objects].") - else if(doing & SNPC_TRAVEL) - if(prob(chattyness)) - chatmsg += pick("Oh [curse_words], [verbs_move]!", - "Time to get my [adjective_generic] [adjective_insult] [nouns_body] elsewhere.", - "I wonder if there is anything to [verbs_use] and [verbs_touch] somewhere else..") - else if(doing & SNPC_FIGHTING) - if(prob(chattyness)) - chatmsg += pick("I'm going to [verbs_use] you, you [adjective_insult] [nouns_insult]!", - "Rend and [verbs_touch], Rend and [verbs_use]!", - "You [nouns_insult], I'm going to [verbs_use] you right in the [nouns_body]. JUST YOU WAIT!") - if(prob(chattyness/2)) - chatmsg = ";" - var/what = pick(1,2,3,4,5) - switch(what) - if(1) - chatmsg += "Well [curse_words], this is a [adjective_generic] situation." - if(2) - chatmsg += "Oh [curse_words], that [nouns_insult] was one hell of an [adjective_insult] [nouns_body]." - if(3) - chatmsg += "I want to [verbs_use] that [nouns_insult] when I find them." - if(4) - chatmsg += "[pick("Innocent","Guilty","Traitorous","Honk")] until proven [adjective_generic]!" - if(5) - var/toSay = "" - for(var/i = 0; i < 5; i++) - curse_words = pick_list(speak_file, "curse_words") - toSay += "[curse_words] " - chatmsg += "Hey [nouns_generic], why don't you go [copytext(toSay, 1, length(toSay))], you [nouns_insult]!" - else if(prob(chattyness)) - chatmsg += pick(knownStrings) - if(prob(25)) // cut out some phrases now and then to make sure we're fresh and new - knownStrings -= pick(chatmsg) - - if(chatmsg != ";" && chatmsg != "") - say(chatmsg) - -/mob/living/carbon/human/interactive/proc/traitor(obj) - - if(traitorType == SNPC_PSYCHO && nearby.len) - traitorTarget = pick(nearby) - - if(prob(traitorScale)) - if(!Adjacent(traitorTarget) && !(traitorType == SNPC_PSYCHO)) - tryWalk(get_turf(traitorTarget)) - else - switch(traitorType) - if(SNPC_BRUTE) - retal = 1 - retal_target = traitorTarget - if(SNPC_STEALTH) - if(istype(traitorTarget,/mob)) // it's inside something, lets kick their shit in - var/mob/M = traitorTarget - if(!M.stat) - retal = 1 - retal_target = traitorTarget - else - var/obj/item/I = traitorTarget - I.loc = get_turf(traitorTarget) // pull it outta them - else - take_to_slot(traitorTarget) - if(SNPC_MARTYR) - custom_emote(1, "[src]'s chest opens up, revealing a large mass of explosives and tangled wires!") - if(inactivity_period <= 0) - inactivity_period = 9999 // technically infinite - if(do_after(src, 60, target = traitorTarget)) - custom_emote(1, "A fire bursts from [src]'s eyes, igniting white hot and consuming [p_their()] body in a flaming explosion!") - explosion(src, 6, 6, 6) - else - inactivity_period = 0 - custom_emote(1, "[src]'s chest closes, hiding [p_their()] insides.") - if(SNPC_PSYCHO) - var/choice = pick(typesof(/obj/item/grenade/chem_grenade) - /obj/item/grenade/chem_grenade) - - new choice(src) - - retal = 1 - retal_target = traitorTarget - -/mob/living/carbon/human/interactive/proc/botany(obj) - if(shouldModulePass()) - return - - if(enforceHome()) - return - - var/list/allContents = getAllContents() - - var/obj/item/reagent_containers/glass/beaker/bluespace/internalBeaker = locate(/obj/item/reagent_containers/glass/beaker/bluespace) in allContents - var/obj/item/storage/bag/plants/internalBag = locate(/obj/item/storage/bag/plants) in allContents - - if(!internalBag) - internalBag = new/obj/item/storage/bag/plants(src) - if(!internalBeaker) - internalBeaker = new/obj/item/reagent_containers/glass/beaker/bluespace(src) - internalBeaker.name = "Grow-U-All Super Spray" - - if(internalBeaker && internalBag) - var/obj/machinery/hydroponics/HP - - //consider the appropriate target - var/list/considered = list() - - for(var/obj/machinery/hydroponics/tester in view(12,src)) - considered[tester] = 1 - - if(!tester.myseed) - considered[tester] += 50 - if(tester.weedlevel > 0) - considered[tester] += 5 - if(tester.pestlevel > 0) - considered[tester] += 5 - if(tester.nutrilevel < tester.maxnutri) - considered[tester] += 15 - if(tester.waterlevel < tester.maxwater) - considered[tester] += 15 - if(tester.harvest || tester.dead) - considered[tester] += 100 - considered[tester] = max(1, considered[tester] - get_dist(src,tester)) - - var/index = 0 - for(var/A in considered) - ++index - if(considered[A] > considered[HP] || !HP) - HP = considered[index] - - if(HP) - TARGET = HP - if(!Adjacent(HP)) - tryWalk(get_turf(HP)) - else - if(HP.harvest || HP.dead) - HP.attack_hand(src) - else if(!HP.myseed) - var/obj/item/seeds/SEED = new /obj/item/seeds/random(src) - custom_emote(1, "[pick("gibbers","drools","slobbers","claps wildly","spits")] towards [TARGET], producing a [SEED]!") - HP.attackby(SEED, src) - else - var/change = 0 - if(HP.weedlevel > 0) - change = 1 - if(!internalBeaker.reagents.has_reagent("atrazine", 10)) - internalBeaker.reagents.add_reagent("atrazine", 10) - if(HP.pestlevel > 0) - change = 1 - if(!internalBeaker.reagents.has_reagent("diethylamine", 10)) - internalBeaker.reagents.add_reagent("diethylamine", 10) - if(HP.nutrilevel < HP.maxnutri) - change = 1 - if(!internalBeaker.reagents.has_reagent("eznutriment", 15)) - internalBeaker.reagents.add_reagent("eznutriment", 15) - if(!internalBeaker.reagents.has_reagent("diethylamine", 15)) - internalBeaker.reagents.add_reagent("diethylamine", 15) - if(HP.waterlevel < HP.maxwater) - change = 1 - if(!internalBeaker.reagents.has_reagent("holywater", 50)) - internalBeaker.reagents.add_reagent("holywater", 50) - if(change) - HP.attackby(internalBeaker,src) - - var/obj/item/reagent_containers/food/snacks/grown/GF = locate(/obj/item/reagent_containers/food/snacks/grown) in view(12,src) - if(GF) - if(!Adjacent(GF)) - tryWalk(get_turf(GF)) - else - GF.attackby(internalBag,src) - - if(internalBag.contents.len) - var/obj/machinery/smartfridge/SF = locate(/obj/machinery/smartfridge) in range(12, src) - if(!Adjacent(SF)) - tryWalk(get_turf(SF)) - else - custom_emote(1, "[pick("gibbers","drools","slobbers","claps wildly","spits")], upending the [internalBag]'s contents all over the [SF]!") - //smartfridges call updateUsrDialog when you call attackby, so we're going to have to cheese-magic-space this - for(var/obj/toLoad in internalBag.contents) - if(contents.len >= SF.max_n_of_items) - break - if(SF.accept_check(toLoad)) - SF.load(toLoad, src) - else - qdel(toLoad) // destroy everything we dont need - -/mob/living/carbon/human/interactive/proc/bartend(obj) - if(shouldModulePass()) - return - - if(enforceHome()) - return - - var/list/rangeCheck = oview(6,src) - var/obj/structure/table/RT - - var/mob/living/carbon/human/serveTarget - - for(var/mob/living/carbon/human/H in rangeCheck) - if(!locate(/obj/item/reagent_containers/food/drinks) in orange(1, H)) - serveTarget = H - - - if(serveTarget) - RT = locate(/obj/structure/table) in orange(1, serveTarget) - - if(RT && serveTarget) - if(!Adjacent(RT)) - tryWalk(get_turf(RT)) - else - var/drinkChoice = pick(typesof(/obj/item/reagent_containers/food/drinks) - /obj/item/reagent_containers/food/drinks) - if(drinkChoice) - var/obj/item/reagent_containers/food/drinks/D = new drinkChoice(get_turf(src)) - RT.attackby(D,src) - say("[pick("Something to wet your whistle!","Down the hatch, a tasty beverage!","One drink, coming right up!","Tasty liquid for your oral intake!","Enjoy!")]") - custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")], serving up a [D]!") - -/mob/living/carbon/human/interactive/proc/shitcurity(obj) - var/list/allContents = getAllContents() - - if(retal && TARGET) - if(Adjacent(TARGET)) - var/obj/item/restraints/R = locate() in allContents - if(R) - R.attack(TARGET, src) // go go bluespace restraint launcher! - else if(TARGET in oview(7, src)) - var/obj/item/gun/G = locate() in allContents - if(G) - G.afterattack(TARGET, src) - -/mob/living/carbon/human/interactive/proc/clowning(obj) - if(shouldModulePass()) - return - var/list/allContents = getAllContents() - var/list/rangeCheck = oview(12, src) - - var/mob/living/carbon/human/clownTarget - var/list/clownPriority = list() - - var/obj/item/reagent_containers/spray/S - if(!locate(/obj/item/reagent_containers/spray) in allContents) - new/obj/item/reagent_containers/spray(src) - else - S = locate(/obj/item/reagent_containers/spray) in allContents - - for(var/mob/living/carbon/human/C in rangeCheck) - var/pranksNearby = 100 - for(var/turf/simulated/T in orange(1, C)) - for(var/obj/item/A in T) - if(istype(A,/obj/item/soap) || istype(A,/obj/item/reagent_containers/food/snacks/grown/banana) || istype(A,/obj/item/grown/bananapeel)) - pranksNearby-- - if(T.wet) - pranksNearby -= 10 - clownPriority[C] = pranksNearby - - for(var/A in clownPriority) - if(!clownTarget) - clownTarget = A - else - if(clownPriority[A] > clownPriority[clownTarget]) - clownTarget = clownPriority[A] - - if(clownTarget) - if(!Adjacent(clownTarget)) - tryWalk(clownTarget) - else - var/hasPranked = 0 - for(var/A in allContents) - if(prob(smartness/2) && !hasPranked) - if(istype(A,/obj/item/soap)) - npcDrop(A) - hasPranked = 1 - if(istype(A,/obj/item/reagent_containers/food/snacks/grown/banana)) - var/obj/item/reagent_containers/food/snacks/B = A - B.attack(src, src) - if(istype(A,/obj/item/grown/bananapeel)) - npcDrop(A) - hasPranked = 1 - if(!hasPranked) - if(S.reagents.total_volume <= 5) - S.reagents.add_reagent("water", 25) - S.afterattack(get_turf(pick(orange(1, clownTarget))),src) - - -/mob/living/carbon/human/interactive/proc/healpeople(obj) - var/shouldTryHeal = 0 - var/obj/item/stack/medical/M - - var/list/allContents = getAllContents() - - for(var/A in allContents) - if(istype(A,/obj/item/stack/medical)) - shouldTryHeal = 1 - M = A - - var/obj/item/reagent_containers/hypospray/HPS - - if(!locate(/obj/item/reagent_containers/hypospray) in allContents) - new/obj/item/reagent_containers/hypospray(src) - else - HPS = locate(/obj/item/reagent_containers/hypospray) in allContents - if(!shouldTryHeal) - shouldTryHeal = 2 // we have no stackables to use, lets use our internal hypospray instead - - if(shouldTryHeal == 1) - for(var/mob/living/carbon/human/C in nearby) - if(istype(C,/mob/living/carbon/human)) //I haven't the foggiest clue why this is turning up non-carbons but sure here whatever - if(C.health <= 75) - if(get_dist(src,C) <= 2) - src.say("Wait, [C], let me heal you!") - M.attack(C,src) - sleep(25) - else - tryWalk(get_turf(C)) - else if(shouldTryHeal == 2) - if(HPS) - if(HPS.reagents.total_volume <= 0) - HPS.reagents.add_reagent("omnizine",30) - for(var/mob/living/carbon/human/C in nearby) - if(istype(C,/mob/living/carbon/human)) - if(C.health <= 75 && C.reagents.get_reagent_amount("omnizine") <= 0) // make sure they wont be overdosing - if(get_dist(src,C) <= 2) - src.say("Wait, [C], let me heal you!") - HPS.attack(C,src) - sleep(25) - else - tryWalk(get_turf(C)) - - -/mob/living/carbon/human/interactive/proc/dojanitor(obj) - if(shouldModulePass()) - return - var/list/allContents = getAllContents() - //now with bluespace magic! - var/obj/item/reagent_containers/spray/SP = locate() in allContents - if(!SP) - SP = new /obj/item/reagent_containers/spray(src) - var/obj/item/soap/SO = locate() in allContents - if(!SO) - SO = new /obj/item/soap(src) - - if(SP.reagents.total_volume <= 5) - SP.reagents.add_reagent("cleaner", 25) // bluespess water delivery for AI - - var/obj/effect/decal/cleanable/TC - TC = locate(/obj/effect/decal/cleanable) in view(6, src) - - if(TC) - if(!Adjacent(TC)) - tryWalk(TC) - else - var/turf/T = get_turf(TC) - if(T && !T.density) - SP.afterattack(TC, src, 1) - else - SO.afterattack(TC, src, 1) - qdel(TC) - -// START COOKING MODULE -/mob/living/carbon/human/interactive/proc/refundrecipe(list/ingredients) - for(var/obj/I in ingredients) - I.loc = contents - -// Ingredients may be in the rangeCheck or inside the chef's inventory. -// As they are checked off, they are moved to a seperate list as to not be counted twice -// If the recipe fails (eg somebody else took an ingredient before it was picked up) the ingredients are dumped back to inventory -// That way, the chef has a better chance of making a recipe next ptick, if he has more stuff on him -/mob/living/carbon/human/interactive/proc/makerecipe(datum/recipe/R, allContents, rangeCheck) - set background = 1 - - var/list/ingredients[0] - - for(var/P in R.items) - var/obj/item/I = locate(P) in allContents - if(I) - ingredients += I - I.forceMove(null) - continue - - I = locate(P) in rangeCheck - TARGET = I - if(I && !Adjacent(I)) - tryWalk(get_turf(I)) - sleep(get_dist(src, I)) - if(!I || !(I in rangeCheck)) - refundrecipe(ingredients) - return 0 - custom_emote(1, "[pick("gibbers","drools","slobbers","claps wildly","spits")], picking up [I].") - ingredients += I - I.forceMove(null) - - // cheaply cook the ingredients into result - sleep(R.time) - for(var/obj/I in ingredients) - qdel(I) - ingredients.Cut() - var/result = new R.result(get_turf(src)) - custom_emote(1, "[pick("gibbers","drools","slobbers","claps wildly","spits")] and, with a bang, \a [result] is cooked!") - return 1 - -/mob/living/carbon/human/interactive/proc/souschef(obj) - if(shouldModulePass() || enforceHome() || prob(SNPC_FUZZY_CHANCE_HIGH) || prob(SNPC_FUZZY_CHANCE_HIGH)) - return - - if(doing & SNPC_SPECIAL) - return - doing |= SNPC_SPECIAL - - var/static/list/customableTypes = list(/obj/item/reagent_containers/food/snacks/customizable,/obj/item/reagent_containers/food/snacks/breadslice,/obj/item/reagent_containers/food/snacks/bun,/obj/item/reagent_containers/food/snacks/sliceable/flatdough,/obj/item/reagent_containers/food/snacks/boiledspaghetti,/obj/item/trash/plate,/obj/item/trash/bowl) - - var/static/list/rawtypes = list(/obj/item/reagent_containers/food/snacks/grown, /obj/item/reagent_containers/food/snacks/rawcutlet, /obj/item/reagent_containers/food/snacks/rawsticks, /obj/item/reagent_containers/food/snacks/salmonmeat, /obj/item/reagent_containers/food/snacks/carpmeat, /obj/item/reagent_containers/food/snacks/catfishmeat, /obj/item/reagent_containers/food/snacks/spaghetti, /obj/item/reagent_containers/food/snacks/dough, /obj/item/reagent_containers/food/snacks/sliceable/flatdough, /obj/item/reagent_containers/food/snacks/doughslice, /obj/item/reagent_containers/food/snacks/meat, /obj/item/reagent_containers/food/snacks/boiledrice, /obj/item/reagent_containers/food/snacks/cheesewedge, /obj/item/reagent_containers/food/snacks/raw_bacon) - - try - var/list/allContents = getAllContents() - var/list/rangeCheck = view(6, src) - - //Bluespace in some inbuilt tools - var/obj/item/kitchen/rollingpin/RP = locate() in allContents - if(!RP) - RP = new /obj/item/kitchen/rollingpin(src) - - var/obj/item/kitchen/knife/KK = locate() in allContents - if(!KK) - KK = new /obj/item/kitchen/knife(src) - - var/global/list/available_recipes - if(!available_recipes) - available_recipes = list() - for(var/type in subtypesof(/datum/recipe)) - var/datum/recipe/recipe = new type - if(recipe.result) // Ignore recipe subtypes that lack a result - available_recipes += recipe - else - qdel(recipe) - - var/foundCookable = 0 - - //Make some basic custom food - var/foundCustom - for(var/customType in customableTypes) - var/A = locate(customType) in rangeCheck - var/obj/item/reagent_containers/food/snacks/customizable/I = A - if(A && (!istype(I) || I.ingredients.len <= 3)) - foundCustom = A // this will eventually wittle down to 0 - break - - var/obj/machinery/smartfridge/SF = locate(/obj/machinery/smartfridge) in rangeCheck - if(SF) - if(SF.contents.len > 0) - if(!Adjacent(SF)) - tryWalk(get_turf(SF)) - else - custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")], grabbing various foodstuffs from [SF] and sticking them in its mouth!") - for(var/obj/item/A in SF.contents) - if(prob(smartness/2)) - var/count = SF.item_quants[A.name] - if(count) - SF.item_quants[A.name] = count - 1 - A.forceMove(src) - - if(foundCustom) - var/obj/item/reagent_containers/food/snacks/FC = foundCustom - for(var/obj/item/reagent_containers/food/snacks/toMake in allContents) - if(prob(smartness)) - if(FC.reagents) - if(toMake.reagents) - var/raw = 0 - for(var/type in rawtypes) - if(istype(toMake, type)) - raw = 1 - break - if(!raw) - npcDrop(toMake) - FC.attackby(toMake, src) - allContents -= toMake - break - else - qdel(FC) // this food is usless, toss it - - // Process tool-based ingredients - var/obj/item/reagent_containers/food/snacks/dough/D = locate() in rangeCheck - var/obj/item/reagent_containers/food/snacks/sliceable/flatdough/FD = locate() in rangeCheck - var/obj/item/reagent_containers/food/snacks/rawcutlet/RC = locate() in rangeCheck - var/obj/item/reagent_containers/food/snacks/sliceable/cheesewheel/CW = locate() in rangeCheck - var/obj/item/reagent_containers/food/snacks/grown/potato/PO = locate() in rangeCheck - var/obj/item/reagent_containers/food/snacks/meat/ME = locate() in rangeCheck - var/obj/item/reagent_containers/food/snacks/raw_bacon/RB = locate() in rangeCheck - - if(D) - TARGET = D - if(prob(50)) - tryWalk(get_turf(D)) - sleep(get_dist(src, D)) - D.attackby(RP, src) - foundCookable = 1 - else if(FD) - TARGET = FD - if(prob(50)) - tryWalk(get_turf(FD)) - sleep(get_dist(src, FD)) - FD.attackby(KK, src) - foundCookable = 1 - else if(RC) - TARGET = RC - if(prob(50)) - tryWalk(get_turf(RC)) - sleep(get_dist(src, RC)) - RC.attackby(KK, src) - foundCookable = 1 - else if(CW) - TARGET = CW - if(prob(50)) - tryWalk(get_turf(CW)) - sleep(get_dist(src, CW)) - CW.attackby(KK, src) - foundCookable = 1 - else if(PO) - TARGET = PO - if(prob(50)) - tryWalk(get_turf(PO)) - sleep(get_dist(src, PO)) - PO.attackby(KK, src) - foundCookable = 1 - else if(ME) - TARGET = ME - if(prob(50)) - tryWalk(get_turf(ME)) - sleep(get_dist(src, ME)) - ME.attackby(KK, src) - foundCookable = 1 - else if(RB) - TARGET = RB - if(prob(50)) - tryWalk(get_turf(RB)) - sleep(get_dist(src, RB)) - RB.attackby(KK, src) - foundCookable = 1 - - // refresh - allContents = getAllContents() - rangeCheck = view(6, src) - - // Find most complex recipe we can cook - var/ingredientZone = rangeCheck + allContents - var/highest_count = 0 - var/datum/recipe/winner = null - for(var/datum/recipe/R in available_recipes) - if(R.check_items(ingredientZone) >= 0) - var/count = (R.items ? R.items.len : 0) - if(count > highest_count) - highest_count = count - winner = R - - // make winner - if(winner) - if(makerecipe(winner, allContents, rangeCheck)) - foundCookable = 1 - - // refresh - allContents = getAllContents() - rangeCheck = view(6, src) - - // dont display our ingredients - var/list/finishedList = list() - for(var/obj/item/reagent_containers/food/snacks/toDisplay in allContents) - var/raw = 0 - for(var/type in rawtypes) - if(istype(toDisplay, type)) - raw = 1 - break - if(!raw) - finishedList += toDisplay - - for(var/obj/item/reagent_containers/food/snacks/toGrab in rangeCheck) - if(!(locate(/obj/structure/table/reinforced) in get_turf(toGrab))) //it's not being displayed - var/raw = 0 - for(var/type in rawtypes) - if(istype(toGrab, type)) - raw = 1 - break - if(!raw) - foundCookable = 1 - if(!Adjacent(toGrab)) - tryWalk(toGrab) - else - finishedList += toGrab - toGrab.forceMove(src) - - if(finishedList.len) - var/obj/structure/table/reinforced/RT - - for(var/obj/structure/table/reinforced/toCheck in rangeCheck) - var/counted = 0 - for(var/obj/item/reagent_containers/food/snacks/S in get_turf(toCheck)) - ++counted - if(counted < 12) // make sure theres not too much food here - RT = toCheck - break - - if(RT) - foundCookable = 1 - if(!Adjacent(RT)) - tryWalk(get_turf(RT)) - else - for(var/obj/item/reagent_containers/food/snacks/toPlop in finishedList) - RT.attackby(toPlop,src) - - if(!foundCookable) - var/chosenType = pick(rawtypes) - - var/obj/item/reagent_containers/food/snacks/newSnack = new chosenType(get_turf(src)) - TARGET = newSnack - newSnack.reagents.remove_any((newSnack.reagents.total_volume/2)-1) - newSnack.name = "synthetic [newSnack.name]" - custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as [p_they()] vomit[p_s()] [newSnack] from [p_their()] mouth!") - catch(var/exception/e) - log_runtime(e, src, "Caught in SNPC cooking module") - doing &= ~SNPC_SPECIAL -// END COOKING MODULE - -/mob/living/carbon/human/interactive/proc/combat(obj) - set background = 1 - enforce_hands() - if(canmove) - if((graytide || (TRAITS & TRAIT_MEAN)) || retal) - interest += targetInterestShift - a_intent = INTENT_HARM - zone_sel.selecting = pick("chest","r_leg","l_leg","r_arm","l_arm","head") - doing |= SNPC_FIGHTING - if(retal) - TARGET = retal_target - else - var/mob/living/M = locate(/mob/living) in oview(7, src) - if(!M) - doing = doing & ~SNPC_FIGHTING - else if(M != src && !compareFaction(M.faction)) - TARGET = M - - //no infighting - if(retal) - if(retal_target) - if(compareFaction(retal_target.faction)) - retal = 0 - retal_target = null - TARGET = null - doing = 0 - - //ensure we're using the best object possible - - var/obj/item/best - var/foundFav = 0 - var/list/allContents = getAllContents() - for(var/test in allContents) - for(var/a in favoured_types) - if(ispath(test,a) && !(doing & SNPC_FIGHTING)) // if we're not in combat and we find our favourite things, use them (for people like janitor and doctors) - best = test - foundFav = 1 - return - if(!foundFav) - if(istype(test,/obj/item)) - var/obj/item/R = test - if(R.force > 2) // make sure we don't equip any non-weaponlike items, ie bags and stuff - if(!best) - best = R - else - if(best.force < R.force) - best = R - if(istype(R, /obj/item/gun)) - var/obj/item/gun/G = R - if(G.can_shoot()) - best = R - break // gun with ammo? screw the rest - if(best && best != main_hand) - take_to_slot(best,1) - - if(TARGET && (doing & SNPC_FIGHTING)) // this is a redundancy check - var/mob/living/M = TARGET - if(istype(M,/mob/living)) - if(M.health > 1 && (M in oview(src, 6))) - //THROWING OBJECTS - for(var/A in allContents) - if(istype(A,/obj/item/gun)) // guns are for shooting, not throwing. - continue - if(prob(robustness)) - if(istype(A,/obj/item)) - var/obj/item/W = A - if(W.throwforce > 19) // Only throw worthwile stuff, no more lobbing wrenches at wenches - npcDrop(W, 1) - throw_item(TARGET) - if(istype(A,/obj/item/grenade)) // Allahu ackbar! ALLAHU ACKBARR!! - var/obj/item/grenade/G = A - G.attack_self(src) - if(prob(smartness)) - npcDrop(G, 1) - sleep(15) - throw_item(TARGET) - - if(!main_hand && other_hand) - swap_hands() - if(main_hand) - if(main_hand.force != 0) - if(istype(main_hand,/obj/item/gun)) - var/obj/item/gun/G = main_hand - if(G.can_trigger_gun(src)) - var/shouldFire = 1 - if(istype(main_hand, /obj/item/gun/energy)) - var/obj/item/gun/energy/P = main_hand - var/stunning = 0 - for(var/A in P.ammo_type) - if(ispath(A,/obj/item/ammo_casing/energy/electrode)) - stunning = 1 - var/mob/stunCheck = TARGET - if(stunning && stunCheck.stunned) - shouldFire = 0 - if(shouldFire) - if(!G.can_shoot()) - G.shoot_with_empty_chamber(src) - npcDrop(G, 1) - else - G.process_fire(TARGET, src) - else - if(get_dist(src,TARGET) > 6) - if(!walk2derpless(TARGET)) - timeout++ - else - var/obj/item/W = main_hand - W.attack(TARGET, src) - else - npcDrop(G, 1) - else - if(targetRange(TARGET) > 2) - tryWalk(TARGET) - else - if(Adjacent(TARGET)) - a_intent = pick(INTENT_DISARM, INTENT_HARM) - M.attack_hand(src) - timeout++ - else if(timeout >= 10 || !(targetRange(M) > 14)) - doing = doing & ~SNPC_FIGHTING - timeout = 0 - TARGET = null - retal = 0 - retal_target = null - else - timeout++ - -/mob/living/carbon/human/interactive/proc/past_verb(word) - if(copytext(word, length(word)) == "e") - return "[word]d" - else - return "[word]ed" - -/mob/living/carbon/human/interactive/proc/ing_verb(word) - if(copytext(word, length(word)) == "e") - return "[copytext(word, 1, length(word))]ing" - else - return "[word]ing" - -/mob/living/carbon/human/interactive/proc/paperwork_sentence() - var/verbs_use = pick_list(speak_file, "verbs_use") - var/verbs_touch = pick_list(speak_file, "verbs_touch") - var/verbs_move = pick_list(speak_file, "verbs_move") - var/nouns_insult = pick_list(speak_file, "nouns_insult") - var/nouns_generic = pick_list(speak_file, "nouns_generic") - var/nouns_objects = pick_list(speak_file, "nouns_objects") - var/nouns_body = pick_list(speak_file, "nouns_body") - var/adjective_insult = pick_list(speak_file, "adjective_insult") - var/adjective_objects = pick_list(speak_file, "adjective_objects") - var/adjective_generic = pick_list(speak_file, "adjective_generic") - var/curse_words = pick_list(speak_file, "curse_words") - var/result = pick("fired", "promoted", "demoted", "terminated", "incinerated", "sent to CentCom", "borged") - - return pick( - "The [adjective_insult] [pick(command_positions)] [past_verb(verbs_touch)] the [adjective_objects] [nouns_objects] and was [result].", - "The [adjective_generic] [pick(engineering_positions)] [past_verb(verbs_touch)] the [adjective_insult] [nouns_objects]. [capitalize(curse_words)], the [nouns_insult] was [result].", - "The [adjective_insult] [pick(security_positions)] [past_verb(verbs_touch)] the [adjective_generic] [nouns_insult] [pick(support_positions)]'s [nouns_body] and had to be [result].", - "Medical had to [verbs_use] the [adjective_generic] [pick(command_positions)]'s [adjective_objects] [nouns_body] after the incident.", - "I demand that [nouns_generic] respond with a [adjective_generic] update ASAP.", - "Would like an update from [nouns_generic] regarding the [adjective_insult] [pick(command_positions)] being [result].", - "The [pick(medical_positions)] needs to [verbs_move] faster when the crew's [adjective_objects] [nouns_body]s are injured, or they will be [result].", - "[capitalize(curse_words)] [adjective_insult] [curse_words].", - "

") - -/mob/living/carbon/human/interactive/proc/pickStamp(allContents) - var/list/stamps[0] - for(var/obj/item/stamp/S in allContents) - stamps += S - if(stamps.len) - return pick(stamps) - - // just make one, maybe - if(prob(SNPC_FUZZY_CHANCE_LOW / 2)) - for(var/p in favoured_types) - if(ispath(p, /obj/item/stamp)) - return new p(src) - return null - -/mob/living/carbon/human/interactive/proc/paperwork(obj) - set background = 1 - - if(shouldModulePass() || !prob(SNPC_FUZZY_CHANCE_LOW / 4)) - return - - var/list/allContents = getAllContents() - - var/obj/item/paper/P = locate() in allContents - var/obj/item/stamp/S = pickStamp(allContents) - var/mob/living/carbon/human/H = locate() in nearby - - if(!P) - P = new /obj/item/paper(src) - - if(P && S && H) - if(!P.stamped || !P.stamped.len) - // generate form - P.name = pick("Inspection Report", "Re: Crew", "Complaint", "To: CentCom") - P.info = {"

[paperwork_sentence()]
"} - for(var/I in 1 to rand(10, 20)) - P.info += "[paperwork_sentence()] " - P.info += {"

[pick("Signed", "Sincerely", "Regards")], [real_name]"} - P.update_icon() - P.stamp(S) - custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] and throws [P] on the ground!") - npcDrop(P) - P.throw_at(H, P.throw_range, P.throw_speed, src) - -/mob/living/carbon/human/interactive/proc/stamping(obj) - if(shouldModulePass()) - return - - var/list/allContents = getAllContents() - var/list/rangeCheck = view(7, src) - - var/obj/item/stamp/S = pickStamp(allContents) - if(!S) - return - - // stamp a paper we're holding, and drop it - var/obj/item/paper/P = locate() in allContents - if(P) - if(!P.stamped || !P.stamped.len) - P.stamp(S) - custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as they stamp \the [P] with \a [S]!") - npcDrop(P, 1) - return - - // stamp a paper in the world - for(var/obj/item/paper/A in rangeCheck) - if(!A.stamped || !A.stamped.len) - if(!Adjacent(A)) - tryWalk(A) - else - A.stamp(S) - custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as they stamp \the [A] with \a [S]!") - return diff --git a/code/modules/mob/living/carbon/human/interactive/interactive.dm b/code/modules/mob/living/carbon/human/interactive/interactive.dm deleted file mode 100644 index 69dfa740b09..00000000000 --- a/code/modules/mob/living/carbon/human/interactive/interactive.dm +++ /dev/null @@ -1,960 +0,0 @@ -/* - NPC VAR EXPLANATIONS (for modules and other things) - - doing = their current action, SNPC_INTERACTING, SNPC_TRAVEL or SNPC_FIGHTING - interest = how interested the NPC is in the situation, if they are idle, this drops - timeout = this is internal - TARGET = their current target - LAST_TARGET = their last target - nearby = a list of nearby mobs - best_force = the highest force object, used for checking when to swap items - retal = this is internal - retal_target = this is internal - update_hands = this is a bool (1/0) to determine if the NPC should update what is in his hands - - MYID = their ID card - MYPDA = their PDA - main_hand = what is in their "main" hand (chosen from left > right) - TRAITS = the traits assigned to this npc - mymjob = the job assigned to the npc - - robustness = the chance for the npc to hit something - smartness = the inverse chance for an npc to do stupid things - attitude = the chance for an npc to do rude or mean things - slyness = the chance for an npc to do naughty things ie thieving - - functions = the list of procs that the npc will use for modules - - graytide = shitmin var to make them go psycho -*/ -/mob/living/carbon/human/interactive - name = "interactive station member" - var/doing = 0 - var/interest = 10 - var/maxInterest = 10 - var/timeout = 0 - var/inactivity_period = 0 - var/atom/TARGET = null - var/atom/LAST_TARGET = null - var/list/nearby = list() - var/best_force = 0 - var/retal = 0 - var/mob/retal_target = null - var/update_hands = 0 - var/list/blacklistItems = list() // items we should be ignoring - var/maxStepsTick = 6 // step as many times as we can per frame - //Job and mind data - var/obj/item/card/id/MYID - var/obj/item/card/id/RPID // the "real" idea they use - var/obj/item/pda/MYPDA - var/obj/item/main_hand - var/obj/item/other_hand - var/TRAITS = 0 - var/obj/item/card/id/Path_ID - var/default_job = /datum/job/civilian // the type for the default job - var/datum/job/myjob - var/list/myPath = list() - faction = list("synth") - //trait vars - var/robustness = 50 - var/smartness = 50 - var/attitude = 50 - var/slyness = 50 - var/graytide = 0 - var/list/favoured_types = list() // allow a mob to favour a type, and hold onto them - var/chattyness = SNPC_CHANCE_TALK - var/targetInterestShift = 5 // how much a good action should "reward" the npc - //modules - var/list/functions = list("nearbyscan","combat","shitcurity","chatter") - var/restrictedJob = 0 - var/forceProcess = 0 - var/speak_file = "npc_chatter.json" - var/debugexamine = FALSE //If we show debug info in our examine - var/showexaminetext = TRUE //If we show our telltale examine text - - var/voice_saved = FALSE - - var/list/knownStrings = list() - - //snpc traitor variables - - var/isTraitor = 0 - var/traitorTarget - var/traitorScale = 0 // our ability as a traitor - var/traitorType = 0 - - -/// SNPC voice handling - -/mob/living/carbon/human/interactive/proc/loadVoice() - var/savefile/S = new /savefile("data/npc_saves/snpc.sav") - S["knownStrings"] >> knownStrings - - if(isnull(knownStrings)) - knownStrings = list() - -/mob/living/carbon/human/interactive/proc/saveVoice() - if(voice_saved) - return - var/savefile/S = new /savefile("data/npc_saves/snpc.sav") - S["knownStrings"] << knownStrings - -//botPool funcs -/mob/living/carbon/human/interactive/proc/takeDelegate(mob/living/carbon/human/interactive/from,doReset=TRUE) - change_eye_color(255, 0, 0) - if(from == src) - return FALSE - TARGET = from.TARGET - LAST_TARGET = from.LAST_TARGET - retal = from.retal - retal_target = from.retal_target - doing = from.doing - // - timeout = 0 - inactivity_period = 0 - interest = maxInterest - // - update_icons() - if(doReset) - from.TARGET = null - from.LAST_TARGET = null - from.retal = 0 - from.retal_target = null - from.doing = 0 - return TRUE - -//end pool funcs - -/mob/living/carbon/human/interactive/proc/random() - //this is here because this has no client/prefs/brain whatever. - age = rand(AGE_MIN, AGE_MAX) - change_gender(pick("male", "female")) - rename_character(real_name, dna.species.get_random_name(gender)) - //job handling - myjob = new default_job() - job = myjob.title - mind.assigned_role = job - myjob.equip(src) - -/mob/living/carbon/human/interactive/proc/reset() - walk(src, 0) - timeout = 100 - retal = 0 - doing = 0 - inactivity_period = 0 - -/client/proc/resetSNPC(mob/living/carbon/human/interactive/T in SSnpcpool.processing) - set name = "Reset SNPC" - set desc = "Reset the SNPC" - set category = "Debug" - - if(!holder) - return - - if(istype(T)) - T.reset() - -/client/proc/customiseSNPC(mob/living/carbon/human/interactive/T in SSnpcpool.processing) - set name = "Customize SNPC" - set desc = "Customize the SNPC" - set category = "Debug" - - if(!holder) - return - - if(!istype(T)) - return - - var/list/jobs[0] - for(var/datum/job/j in SSjobs.occupations) - if(j.title != "AI" && j.title != "Cyborg") - jobs[j.title] = j - jobs = sortAssoc(jobs) - var/job_name = input("Choose Job") as null|anything in jobs - - if(job_name) - var/datum/job/cjob = jobs[job_name] - var/alt_title = input("Choose Alt Title") in (list(job_name) + cjob.alt_titles) - - T.myjob = cjob - T.job = cjob.title - T.mind.assigned_role = cjob.title - for(var/obj/item/I in T) - if(istype(I, /obj/item/implant)) - continue - if(istype(I, /obj/item/organ)) - continue - qdel(I) - T.myjob.equip(T) - T.doSetup(alt_title) - - var/shouldDoppel = input("Do you want the SNPC to disguise themself as a crewmember?") as anything in list("Yes", "No") - if(shouldDoppel == "Yes") - var/list/validchoices = list() - for(var/mob/living/carbon/human/M in GLOB.mob_list) - validchoices += M - - var/mob/living/carbon/human/chosen = input("Which crewmember?") as null|anything in validchoices - - if(chosen) - var/datum/dna/toDoppel = chosen.dna - - T.real_name = toDoppel.real_name - T.set_species(chosen.dna.species.type) - T.dna = toDoppel.Clone() - T.body_accessory = chosen.body_accessory - T.UpdateAppearance() - domutcheck(T) - - var/doTrait = input("Do you want the SNPC to be a traitor?") as anything in list("Yes", "No") - if(doTrait == "Yes") - var/list/tType = list("Brute" = SNPC_BRUTE, "Stealth" = SNPC_STEALTH, "Martyr" = SNPC_MARTYR, "Psycho" = SNPC_PSYCHO) - var/cType = input("Choose the traitor personality.") as null|anything in tType - if(cType) - var/value = tType[cType] - T.makeTraitor(value) - - var/doTele = input("Place the SNPC in their department?") as anything in list("Yes", "No") - if(doTele == "Yes") - T.loc = pick(get_area_turfs(T.job2area(T.myjob))) - - T.revive() - -/mob/living/carbon/human/interactive/proc/doSetup(alt_title = null) - Path_ID = new /obj/item/card/id(src) - - var/datum/job/captain/C = new/datum/job/captain - Path_ID.access = C.get_access() - - if(!alt_title) - alt_title = job - - MYID = new(src) - MYID.name = "[real_name]'s ID Card ([alt_title])" - MYID.assignment = "[alt_title]" - MYID.rank = job - MYID.sex = capitalize(gender) - MYID.age = age - MYID.registered_name = real_name - MYID.photo = get_id_photo(src) - MYID.access = Path_ID.access.Copy() // Automatons have strange powers... strange indeed - - RPID = new(src) - RPID.name = "[real_name]'s ID Card ([alt_title])" - RPID.assignment = "[alt_title]" - RPID.rank = job - RPID.sex = capitalize(gender) - RPID.age = age - RPID.registered_name = real_name - RPID.photo = get_id_photo(src) - RPID.access = myjob.get_access() - - if(wear_id) - qdel(wear_id) - if(!equip_to_slot_or_del(MYID, slot_wear_id)) - create_attack_log("Deleted ID due to slot contention") - if(wear_pda) - MYPDA = wear_pda - else - MYPDA = new(src) - equip_to_slot_or_del(MYPDA, slot_wear_pda) - MYPDA.owner = real_name - MYPDA.ownjob = alt_title - MYPDA.ownrank = job - MYPDA.name = "PDA-[real_name] ([alt_title])" - zone_sel.selecting = "chest" - //arms - if(prob((SNPC_FUZZY_CHANCE_LOW+SNPC_FUZZY_CHANCE_HIGH)/4)) - var/obj/item/organ/external/R = bodyparts_by_name["r_arm"] - if(R) - R.robotize(make_tough = 1) - else - var/obj/item/organ/external/L = bodyparts_by_name["l_arm"] - if(L) - L.robotize(make_tough = 1) - //legs - if(prob((SNPC_FUZZY_CHANCE_LOW+SNPC_FUZZY_CHANCE_HIGH)/4)) - var/obj/item/organ/external/R = bodyparts_by_name["r_leg"] - if(R) - R.robotize(make_tough = 1) - else - var/obj/item/organ/external/L = bodyparts_by_name["l_leg"] - if(L) - L.robotize(make_tough = 1) - UpdateDamageIcon() - regenerate_icons() - - hand = 0 - functions = list("nearbyscan", "combat", "shitcurity", "chatter") // stop customize adding multiple copies of a function - setup_job(job) - - if(TRAITS & TRAIT_ROBUST) - robustness = 75 - else if(TRAITS & TRAIT_UNROBUST) - robustness = 25 - - //modifiers are prob chances, lower = smarter - if(TRAITS & TRAIT_SMART) - smartness = 75 - else if(TRAITS & TRAIT_DUMB) - disabilities |= CLUMSY - smartness = 25 - - if(TRAITS & TRAIT_MEAN) - attitude = 75 - else if(TRAITS & TRAIT_FRIENDLY) - attitude = 1 - - if(TRAITS & TRAIT_THIEVING) - slyness = 75 - -/mob/living/carbon/human/interactive/proc/InteractiveProcess() - if(ticker.current_state == GAME_STATE_FINISHED) - saveVoice() - voice_saved = TRUE - doProcess() - -/mob/living/carbon/human/interactive/proc/setup_job(thejob) - switch(thejob) - if("Civilian") - favoured_types = list(/obj/item/clothing, /obj/item) - if("Captain", "Head of Personnel") - favoured_types = list(/obj/item/clothing, /obj/item/stamp/captain,/obj/item/disk/nuclear) - if("Nanotrasen Representative") - favoured_types = list(/obj/item/clothing, /obj/item/stamp/centcom, /obj/item/paper, /obj/item/melee/classic_baton/ntcane) - functions += "paperwork" - if("Magistrate", "Internal Affairs Agent") - favoured_types = list(/obj/item/clothing, /obj/item/stamp/law, /obj/item/paper) - functions += "paperwork" - if("Quartermaster", "Cargo Technician") - favoured_types = list(/obj/item/clothing, /obj/item/stamp/granted, /obj/item/stamp/denied, /obj/item/paper, /obj/item/clipboard) - functions += "stamping" - if("Chef") - favoured_types = list(/obj/item/reagent_containers/food, /obj/item/kitchen) - functions += "souschef" - restrictedJob = 1 - if("Bartender") - favoured_types = list(/obj/item/reagent_containers/food, /obj/item/kitchen) - functions += "bartend" - restrictedJob = 1 - if("Station Engineer", "Chief Engineer", "Life Support Specialist", "Mechanic") - favoured_types = list(/obj/item/stack, /obj/item, /obj/item/clothing) - if("Chief Medical Officer", "Medical Doctor", "Chemist", "Virologist", "Geneticist", "Psychiatrist", "Paramedic", "Brig Physician") - favoured_types = list(/obj/item/reagent_containers/glass/beaker, /obj/item/storage/firstaid, /obj/item/stack/medical, /obj/item/reagent_containers/syringe) - functions += "healpeople" - if("Research Director", "Scientist", "Roboticist") - favoured_types = list(/obj/item/reagent_containers/glass/beaker, /obj/item/stack, /obj/item/reagent_containers) - if("Head of Security", "Warden", "Security Officer", "Detective", "Security Pod Pilot", "Blueshield") - favoured_types = list(/obj/item/clothing, /obj/item, /obj/item/restraints) - if("Janitor") - favoured_types = list(/obj/item/mop, /obj/item/reagent_containers/glass/bucket, /obj/item/reagent_containers/spray/cleaner, /obj/effect/decal/cleanable) - functions += "dojanitor" - if("Clown") - favoured_types = list(/obj/item/soap, /obj/item/reagent_containers/food/snacks/grown/banana, /obj/item/grown/bananapeel) - functions += "clowning" - if("Botanist") - favoured_types = list(/obj/machinery/hydroponics, /obj/item/reagent_containers, /obj/item) - functions += "botany" - restrictedJob = 1 - else - favoured_types = list(/obj/item/clothing) - -/mob/living/carbon/human/interactive/proc/makeTraitor(var/inPers) - isTraitor = 1 - traitorScale = (slyness + smartness) + rand(-10,10) - traitorType = inPers - - ticker.mode.traitors += mind - mind.special_role = SPECIAL_ROLE_TRAITOR - var/datum/mindslaves/slaved = new() - slaved.masters += mind - mind.som = slaved - ticker.mode.update_traitor_icons_added(mind) - - switch(traitorType) - if(SNPC_BRUTE) // SMASH KILL RAAARGH - var/datum/objective/assassinate/A = new - A.owner = mind - A.find_target() - mind.objectives += A - traitorTarget = A.target.current - if(SNPC_STEALTH) // Shhh we is sneekies - var/datum/objective/steal/S = new - S.owner = mind - S.find_target() - mind.objectives += S - traitorTarget = locate(S.steal_target.typepath) in world - if(SNPC_MARTYR) // MY LIFE FOR SPESZUL - var/targetType = pick(/obj/structure/particle_accelerator, /obj/machinery/gravity_generator/main, /obj/machinery/power/smes) - traitorTarget = locate(targetType) in world - var/datum/objective/O = new("Destroy \the [traitorTarget].") - O.owner = mind - mind.objectives += O - if(SNPC_PSYCHO) // YOU'RE LIKE A FLESH BICYLE AND I WANT TO DISMANTLE YOU - var/datum/objective/hijack/H = new - H.owner = mind - mind.objectives += H - traitorTarget = null - - functions += "traitor" - faction -= "neutral" - faction += "hostile" - -/mob/living/carbon/human/interactive/create_mob_hud() - if(!hud_used) - hud_used = new /datum/hud/human(src) - -/mob/living/carbon/human/interactive/Initialize() - ..() - return INITIALIZE_HINT_LATELOAD - -/mob/living/carbon/human/interactive/LateInitialize() - . = ..() - GLOB.snpc_list += src - - create_mob_hud() - - sync_mind() - random() - doSetup() - START_PROCESSING(SSnpcpool, src) - loadVoice() - GLOB.hear_radio_list += src - - // a little bit of variation to make individuals more unique - robustness += rand(-10, 10) - smartness += rand(-10, 10) - attitude += rand(-10, 10) - slyness += rand(-10, 10) - - doProcess() - -/mob/living/carbon/human/interactive/Destroy() - SSnpcpool.stop_processing(src) - return ..() - -/mob/living/carbon/human/interactive/proc/retalTarget(mob/living/target) - var/mob/living/M = target - if(istype(M)) - if(health > 0) - if(M.a_intent == INTENT_HELP && !incapacitated()) - chatter() - if(istype(target, /mob/living/carbon) && !retal && prob(SNPC_FUZZY_CHANCE_LOW)) - var/mob/living/carbon/C = target - if(!Adjacent(target)) - tryWalk(target) - else - C.help_shake_act(src) - if(M.a_intent == INTENT_HARM) - retal = 1 - retal_target = target - -//Retaliation clauses - -/mob/living/carbon/human/interactive/attacked_by(obj/item/I, mob/living/user, def_zone) - ..() - retalTarget(user) - -/mob/living/carbon/human/interactive/hitby(atom/movable/AM, skipcatch, hitpush, blocked) - ..() - var/mob/living/carbon/C = locate(/mob/living/carbon) in view(SNPC_MIN_RANGE_FIND, src) - if(C) - retalTarget(C) - -/mob/living/carbon/human/interactive/bullet_act(obj/item/projectile/P) - ..() - retalTarget(P.firer) - -/mob/living/carbon/human/interactive/attack_hand(mob/living/carbon/human/M) - ..() - retalTarget(M) - -/mob/living/carbon/human/interactive/show_inv(mob/user) - ..() - retalTarget(user) - -/mob/living/carbon/human/interactive/can_inject(mob/user, error_msg, target_zone, var/penetrate_thick = 0) - ..() - retalTarget(user) - -//THESE EXIST FOR DEBUGGING OF THE DOING/INTEREST SYSTEM EASILY -/mob/living/carbon/human/interactive/proc/doing2string(doin) - var/toReturn = "" - if(!doin) - toReturn = "not doing anything" - if(doin & SNPC_INTERACTING) - toReturn += "interacting with something, " - if(doin & SNPC_FIGHTING) - toReturn += "engaging in combat, " - if(doin & SNPC_TRAVEL) - toReturn += "and going somewhere" - return toReturn - -/mob/living/carbon/human/interactive/proc/interest2string(inter) - var/toReturn = "Flatlined" - if(inter >= 0 && inter <= 25) - toReturn = "Very Bored" - if(inter >= 26 && inter <= 50) - toReturn = "Bored" - if(inter >= 51 && inter <= 75) - toReturn = "Content" - if(inter >= 76) - toReturn = "Excited" - return toReturn -//END DEBUG - -/mob/living/carbon/human/interactive/proc/IsDeadOrIncap(checkDead = TRUE) - if(!canmove) - return 1 - if(health <= 0 && checkDead) - return 1 - if(restrained()) - return 1 - if(paralysis) - return 1 - if(stunned) - return 1 - if(stat) - return 1 - if(inactivity_period > 0) - return 1 - return 0 - -/mob/living/carbon/human/interactive/proc/enforce_hands() - if(main_hand) - if(main_hand.loc != src) - main_hand = null - if(other_hand) - if(other_hand.loc != src) - other_hand = null - if(hand) - if(!l_hand) - main_hand = null - if(r_hand) - swap_hands() - else - if(!r_hand) - main_hand = null - if(l_hand) - swap_hands() - -/mob/living/carbon/human/interactive/proc/swap_hands() - hand = !hand - var/obj/item/T = other_hand - main_hand = other_hand - other_hand = T - update_hands = 1 - -/mob/living/carbon/human/interactive/proc/take_to_slot(obj/item/G, var/hands=0) - var/list/slots = list("left pocket" = slot_l_store, "right pocket" = slot_r_store, "left hand" = slot_l_hand, "right hand" = slot_r_hand) - if(hands) - slots = list("left hand" = slot_l_hand, "right hand" = slot_r_hand) - G.loc = src - if(G.force && G.force > best_force) - best_force = G.force - equip_in_one_of_slots(G, slots) - update_hands = 1 - -/mob/living/carbon/human/interactive/proc/insert_into_backpack() - var/list/slots = list(slot_l_store, slot_r_store, slot_l_hand, slot_r_hand) - var/obj/item/I = get_item_by_slot(pick(slots)) - var/obj/item/storage/BP = get_item_by_slot(slot_back) - if(back && BP && I) - // hack to allow SNPCs to "sticky grab" items without losing their inventorying - var/oldnodrop = I.flags | NODROP - I.flags &= ~NODROP - if(BP.can_be_inserted(I)) - BP.handle_item_insertion(I) - I.flags |= oldnodrop - else - unEquip(I,TRUE) - update_hands = 1 - -/mob/living/carbon/human/interactive/proc/targetRange(towhere) - return get_dist(get_turf(towhere), get_turf(src)) - -/mob/living/carbon/human/interactive/death() - // Only execute the below if we successfully died - . = ..() - if(!.) - return FALSE - saveVoice() - -/mob/living/carbon/human/interactive/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol) - if(!istype(speaker, /mob/living/carbon/human/interactive)) - knownStrings |= html_decode(multilingual_to_message(message_pieces)) - ..() - -/mob/living/carbon/human/interactive/hear_radio(list/message_pieces, verb = "says", part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target) - if(!istype(speaker, /mob/living/carbon/human/interactive)) - knownStrings |= html_decode(multilingual_to_message(message_pieces)) - ..() - -/mob/living/carbon/human/interactive/proc/doProcess() - set waitfor = FALSE - if(IsDeadOrIncap()) - reset() - return - //--------------------------- - //---- interest flow control - if(interest < 0 || inactivity_period < 0) - if(interest < 0) - interest = 0 - if(inactivity_period < 0) - inactivity_period = 0 - if(interest > maxInterest) - interest = maxInterest - //--------------------------- - //VIEW FUNCTIONS - - //doorscan is now integrated into life and runs before all other procs - var/mistake_chance = (100 - smartness) / 2 - spawn(0) - for(var/dir in alldirs) - var/turf/T = get_step(src, dir) - if(T) - for(var/obj/machinery/door/D in T.contents) - if(!istype(D,/obj/machinery/door/poddoor) && D.density) - spawn(0) - if(istype(D,/obj/machinery/door/airlock)) - var/obj/machinery/door/airlock/AL = D - if(!AL.CanAStarPass(RPID)) // only crack open doors we can't get through - inactivity_period = 20 - AL.panel_open = 1 - AL.update_icon() - AL.shock(src, mistake_chance) - sleep(5) - if(QDELETED(AL)) - return - AL.unlock() - if(prob(mistake_chance)) - if(!AL.wires.IsIndexCut(AIRLOCK_WIRE_DOOR_BOLTS)) - AL.wires.CutWireIndex(AIRLOCK_WIRE_DOOR_BOLTS) - else - if(AL.wires.IsIndexCut(AIRLOCK_WIRE_DOOR_BOLTS)) - AL.wires.CutWireIndex(AIRLOCK_WIRE_DOOR_BOLTS, 1) - if(AL.locked) - AL.wires.UpdatePulsed(AIRLOCK_WIRE_DOOR_BOLTS) - if(!AL.wires.IsIndexCut(AIRLOCK_WIRE_MAIN_POWER1)) - AL.wires.CutWireIndex(AIRLOCK_WIRE_MAIN_POWER1) - if(prob(mistake_chance) && !AL.wires.IsIndexCut(AIRLOCK_WIRE_SAFETY)) - AL.wires.CutWireIndex(AIRLOCK_WIRE_SAFETY) - if(prob(mistake_chance) && !AL.wires.IsIndexCut(AIRLOCK_WIRE_ELECTRIFY)) - AL.wires.CutWireIndex(AIRLOCK_WIRE_ELECTRIFY) - sleep(5) - if(QDELETED(AL)) - return - AL.panel_open = 0 - AL.update_icon() - D.open() - - if(update_hands) - if(l_hand || r_hand) - if(l_hand) - hand = 1 - main_hand = l_hand - if(r_hand) - other_hand = r_hand - else if(r_hand) - hand = 0 - main_hand = r_hand - if(l_hand) //this technically shouldnt occur, but its a redundancy - other_hand = l_hand - update_icons() - update_hands = 0 - - if(grabbed_by.len > 0) - for(var/obj/item/grab/G in grabbed_by) - if(Adjacent(G)) - a_intent = INTENT_DISARM - G.assailant.attack_hand(src) - inactivity_period = 10 - - if(buckled) - resist() - inactivity_period = 10 - - //proc functions - for(var/Proc in functions) - if(!IsDeadOrIncap()) - INVOKE_ASYNC(src, Proc) - - - //target interaction stays hardcoded - - if(TARGET && (TARGET in blacklistItems)) // don't use blacklisted items - TARGET = null - - if(TARGET && Adjacent(TARGET)) - doing |= SNPC_INTERACTING - //--------DOORS - if(istype(TARGET, /obj/machinery/door)) - var/obj/machinery/door/D = TARGET - if(D.check_access(MYID) && !istype(D,/obj/machinery/door/poddoor)) - inactivity_period = 10 - D.open() - var/turf/T = get_step(get_step(D.loc, dir), dir) //recursion yo - tryWalk(T) - //THIEVING SKILLS - insert_into_backpack() // dump random item into backpack to make space - //---------ITEMS - if(istype(TARGET, /obj/item)) - var/obj/item/I = TARGET - if(I.anchored) - TARGET = null - else if(istype(TARGET, /obj/item)) - var/obj/item/W = TARGET - if(W.force >= best_force || prob((SNPC_FUZZY_CHANCE_LOW + SNPC_FUZZY_CHANCE_HIGH) / 2) || favouredObjIn(list(W))) - if(!l_hand || !r_hand) - put_in_hands(W) - else - insert_into_backpack() - else - if(!l_hand || !r_hand) - put_in_hands(TARGET) - else - insert_into_backpack() - //---------FASHION - if(istype(TARGET, /obj/item/clothing)) - drop_item() - dressup(TARGET) - update_hands = 1 - if(MYPDA in loc) - equip_to_appropriate_slot(MYPDA) - if(MYID in loc) - equip_to_appropriate_slot(MYID) - //THIEVING SKILLS END - //-------------TOUCH ME - if(istype(TARGET, /obj/structure)) - var/obj/structure/STR = TARGET - if(main_hand) - var/obj/item/W = main_hand - STR.attackby(W, src) - else - STR.attack_hand(src) - interest += targetInterestShift - doing = doing & ~SNPC_INTERACTING - timeout = 0 - TARGET = null - else - if(TARGET) - tryWalk(TARGET) - timeout++ - - if(doing == 0) - interest-- - else - interest++ - - if(inactivity_period > 0) - inactivity_period-- - - if(interest <= 0 || timeout >= 10) // facilitate boredom functions - TARGET = null - doing = 0 - timeout = 0 - myPath = list() - - //this is boring, lets move - if(!doing && !IsDeadOrIncap() && !TARGET) - doing |= SNPC_TRAVEL - if(!isTraitor || !traitorTarget || get_dist(src, traitorTarget) >= SNPC_MAX_RANGE_FIND || get_dist(src, traitorTarget) <= 1) - var/choice = rand(1,50) - switch(choice) - if(1 to 30) - //chance to chase an item - TARGET = locate(/obj/item) in favouredObjIn(oview(SNPC_MIN_RANGE_FIND, src)) - if(31 to 40) - TARGET = safepick(get_area_turfs(job2area(myjob))) - if(41 to 45) - TARGET = pick(target_filter(favouredObjIn(urange(SNPC_MAX_RANGE_FIND, src, 1)))) - if(46 to 50) - TARGET = pick(target_filter(oview(SNPC_MIN_RANGE_FIND, src))) - else - TARGET = traitorTarget - tryWalk(TARGET) - LAST_TARGET = TARGET - -/mob/living/carbon/human/interactive/proc/dressup(obj/item/clothing/C) - set waitfor = FALSE - inactivity_period = 12 - sleep(5) - if(!QDELETED(C) && !QDELETED(src)) - take_to_slot(C,1) - if(!equip_to_appropriate_slot(C)) - var/obj/item/I = get_item_by_slot(C) - unEquip(I) - sleep(5) - if(!QDELETED(src) && !QDELETED(C)) - equip_to_appropriate_slot(C) - -/mob/living/carbon/human/interactive/proc/favouredObjIn(list/inList) - var/list/outList = list() - for(var/i in inList) - for(var/path in favoured_types) - if(istype(i, path)) - outList += i - if(!outList.len) - outList = inList - return outList - -/mob/living/carbon/human/interactive/proc/tryWalk(turf/inTarget) - if(restrictedJob) // we're a job that has to stay in our home - if(!(get_turf(inTarget) in get_area_turfs(job2area(myjob)))) - TARGET = null - return - - if(!IsDeadOrIncap()) - if(!walk2derpless(inTarget)) - timeout++ - else - timeout++ - -/mob/living/carbon/human/interactive/proc/getGoodPath(target, maxtries=512) - set background = 1 - var/turf/end = get_turf(target) - - var/turf/current = get_turf(src) - - var/list/path = list() - var/tries = 0 - while(current != end && tries < maxtries) - var/turf/shortest = current - for(var/turf/T in view(current,1)) - var/foundDense = 0 - for(var/atom/A in T) - if(A.density) - foundDense = 1 - if(T.density == 0 && !foundDense) - if(get_dist(T, target) < get_dist(shortest,target)) - shortest = T - else - tries++ - else - tries++ - current = shortest - path += shortest - return path - -/mob/living/carbon/human/interactive/proc/walk2derpless(target) - set background = 1 - if(!target) - return 0 - - if(myPath.len <= 0) - myPath = get_path_to(src, get_turf(target), /turf/proc/Distance, SNPC_MAX_RANGE_FIND + 1, 250,1, id=Path_ID, simulated_only = 0) - - if(myPath) - if(myPath.len > 0) - doing = doing & ~SNPC_TRAVEL - for(var/i = 0; i < maxStepsTick; ++i) - if(!IsDeadOrIncap()) - if(myPath.len >= 1) - walk_to(src,myPath[1],0,5) - myPath -= myPath[1] - return 1 - return 0 - -/mob/living/carbon/human/interactive/proc/job2area(target) - var/datum/job/T = target - switch(T.title) - if("Civilian", "Paramedic") - return /area/hallway/primary - if("Captain", "Head of Personnel", "Blueshield") - return /area/bridge - if("Bartender") - return /area/crew_quarters/bar - if("Chef") - return /area/crew_quarters/kitchen - if("Station Engineer", "Chief Engineer", "Mechanic") - return /area/engine - if("Life Support Specialist") - return /area/atmos - if("Chief Medical Officer", "Medical Doctor", "Chemist", "Virologist", "Psychiatrist") - return /area/medical - if("Geneticist") - return /area/medical/genetics - if("Research Director", "Scientist") - return /area/toxins - if("Roboticist") - return /area/assembly/robotics - if("Head of Security", "Warden", "Security Officer", "Detective", "Security Pod Pilot", "Brig Physician", "Magistrate", "Internal Affairs Agent") - return /area/security - if("Botanist") - return /area/hydroponics - else - return pick(/area/hallway, /area/crew_quarters) - -/mob/living/carbon/human/interactive/proc/target_filter(target) - var/list/filtered_targets = list(/area, /turf, /obj/machinery/door, /atom/movable/lighting_overlay, /obj/structure/cable, /obj/machinery/atmospherics, /obj/item/radio/intercom) - var/list/L = target - for(var/atom/A in target) // added a bunch of "junk" that clogs up the general find procs - if(is_type_in_list(A,filtered_targets)) - L -= A - return L - -/mob/living/carbon/human/interactive/proc/shouldModulePass() // returns 1 if the npc is in anything "primary" - if(doing & (SNPC_FIGHTING | SNPC_SPECIAL)) - return 1 - if(retal) - return 1 - return 0 - -/mob/living/carbon/human/interactive/proc/getAllContents() - var/list/allContents = list() - for(var/atom/A in contents) - allContents += A - if(A.contents.len) - for(var/atom/B in A) - allContents += B - return allContents - -/mob/living/carbon/human/interactive/proc/enforceHome() - var/list/validHome = get_area_turfs(job2area(myjob)) - - if(TARGET) - var/atom/tcheck = TARGET - if(tcheck) - if(!(get_turf(tcheck) in validHome)) - TARGET = null - return 1 - - if(!(get_turf(src) in validHome) && validHome.len) - tryWalk(pick(get_area_turfs(job2area(myjob)))) - return 1 - return 0 - -/mob/living/carbon/human/interactive/proc/npcDrop(obj/item/A, blacklist = 0) - if(blacklist) - blacklistItems += A - unEquip(A) - enforce_hands() - update_icons() - -/mob/living/carbon/human/interactive/proc/compareFaction(list/targetFactions) - var/hasSame = 0 - - for(var/A in targetFactions) - if(A in faction) - hasSame = 1 - - return hasSame - -/mob/living/carbon/human/interactive/proc/nearbyscan(obj) - nearby = list() - for(var/mob/living/M in view(4,src)) - if(M != src) - nearby += M - -/mob/living/carbon/human/interactive/rename_character(oldname, newname) - if(!..()) - return 0 - - if(oldname) - if(MYID) - MYID.registered_name = newname - MYID.name = "[newname]'s ID Card ([MYID.assignment])" - if(RPID) - RPID.registered_name = MYID.registered_name - RPID.name = MYID.name - return 1 diff --git a/code/modules/mob/living/carbon/human/interactive/prefabs.dm b/code/modules/mob/living/carbon/human/interactive/prefabs.dm deleted file mode 100644 index cee716b66ec..00000000000 --- a/code/modules/mob/living/carbon/human/interactive/prefabs.dm +++ /dev/null @@ -1,24 +0,0 @@ -/mob/living/carbon/human/interactive/angry/Initialize(mapload) - TRAITS |= TRAIT_ROBUST - TRAITS |= TRAIT_MEAN - faction += "bot_angry" - return ..() - -/mob/living/carbon/human/interactive/friendly/Initialize(mapload) - TRAITS |= TRAIT_FRIENDLY - TRAITS |= TRAIT_UNROBUST - faction += "bot_friendly" - faction += "neutral" - functions -= "combat" - return ..() - -/mob/living/carbon/human/interactive/greytide/Initialize(mapload) - TRAITS |= TRAIT_ROBUST - TRAITS |= TRAIT_MEAN - TRAITS |= TRAIT_THIEVING - TRAITS |= TRAIT_DUMB - maxInterest = 5 // really short attention span - targetInterestShift = 2 // likewise - faction += "bot_grey" - graytide = 1 - return ..() diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index d28e728c82c..d66f3dbf815 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -8,6 +8,15 @@ return 0 var/datum/gas_mixture/environment = loc.return_air() + if(client || registered_z) // This is a temporary error tracker to make sure we've caught everything + var/turf/T = get_turf(src) + if(client && registered_z != T.z) + message_admins("[src] [ADMIN_FLW(src, "FLW")] has somehow ended up in Z-level [T.z] despite being registered in Z-level [registered_z]. If you could ask them how that happened and notify the coders, it would be appreciated.") + log_game("Z-TRACKING: [src] has somehow ended up in Z-level [T.z] despite being registered in Z-level [registered_z].") + update_z(T.z) + else if (!client && registered_z) + log_game("Z-TRACKING: [src] of type [src.type] has a Z-registration despite not having a client.") + update_z(null) if(stat != DEAD) //Chemicals in the body handle_chemicals_in_body() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 52fde3d0d9e..3000fd5b085 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -953,6 +953,27 @@ to_chat(src, "You can taste [english_list(final_taste_list)].") +/mob/living/proc/update_z(new_z) // 1+ to register, null to unregister + if(registered_z != new_z) + if(registered_z) + SSmobs.clients_by_zlevel[registered_z] -= src + if(client) + if(new_z) + SSmobs.clients_by_zlevel[new_z] += src + for (var/I in length(SSidlenpcpool.idle_mobs_by_zlevel[new_z]) to 1 step -1) //Backwards loop because we're removing (guarantees optimal rather than worst-case performance), it's fine to use .len here but doesn't compile on 511 + var/mob/living/simple_animal/SA = SSidlenpcpool.idle_mobs_by_zlevel[new_z][I] + if (SA) + SA.toggle_ai(AI_ON) // Guarantees responsiveness for when appearing right next to mobs + else + SSidlenpcpool.idle_mobs_by_zlevel[new_z] -= SA + registered_z = new_z + else + registered_z = null + +/mob/living/onTransitZ(old_z,new_z) + ..() + update_z(new_z) + /mob/living/proc/owns_soul() if(mind) return mind.soulOwner == mind diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm index d1157b662fa..d8e27df91fe 100644 --- a/code/modules/mob/living/login.dm +++ b/code/modules/mob/living/login.dm @@ -5,6 +5,10 @@ update_stat("mob login") update_sight() + var/turf/T = get_turf(src) + if(isturf(T)) + update_z(T.z) + //If they're SSD, remove it so they can wake back up. player_logged = 0 //Vents diff --git a/code/modules/mob/living/logout.dm b/code/modules/mob/living/logout.dm index 87384669a7c..e1c33f89a7e 100644 --- a/code/modules/mob/living/logout.dm +++ b/code/modules/mob/living/logout.dm @@ -1,4 +1,5 @@ /mob/living/Logout() + update_z(null) if(ranged_ability && client) ranged_ability.remove_mousepointer(client) ..() diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index ccf319b0884..ae7fcf56a9d 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -634,7 +634,7 @@ var/list/ai_verbs_default = list( return if(href_list["trackbot"]) - var/mob/living/simple_animal/bot/target = locate(href_list["trackbot"]) in GLOB.simple_animal_list + var/mob/living/simple_animal/bot/target = locate(href_list["trackbot"]) in GLOB.simple_animals if(target) ai_actual_track(target) else @@ -642,7 +642,7 @@ var/list/ai_verbs_default = list( return if(href_list["callbot"]) //Command a bot to move to a selected location. - Bot = locate(href_list["callbot"]) in GLOB.simple_animal_list + Bot = locate(href_list["callbot"]) in GLOB.simple_animals if(!Bot || Bot.remote_disabled || control_disabled) return //True if there is no bot found, the bot is manually emagged, or the AI is carded with wireless off. waypoint_mode = 1 @@ -650,7 +650,7 @@ var/list/ai_verbs_default = list( return if(href_list["interface"]) //Remotely connect to a bot! - Bot = locate(href_list["interface"]) in GLOB.simple_animal_list + Bot = locate(href_list["interface"]) in GLOB.simple_animals if(!Bot || Bot.remote_disabled || control_disabled) return Bot.attack_ai(src) @@ -746,7 +746,7 @@ var/list/ai_verbs_default = list( d += "Query network status
" d += "" - for(var/mob/living/simple_animal/bot/Bot in GLOB.simple_animal_list) + for(var/mob/living/simple_animal/bot/Bot in GLOB.simple_animals) if(is_ai_allowed(Bot.z) && !Bot.remote_disabled) //Only non-emagged bots on the allowed Z-level are detected! bot_area = get_area(Bot) d += "" diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index 3ff26f7850c..970ac596482 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -451,7 +451,7 @@ response_harm = "kicks" gold_core_spawnable = CHEM_MOB_SPAWN_INVALID -/mob/living/simple_animal/pet/corgi/Ian/process_ai() +/mob/living/simple_animal/pet/corgi/Ian/Life() ..() //Feeding, chasing food, FOOOOODDDD @@ -578,7 +578,7 @@ return ..() -/mob/living/simple_animal/pet/corgi/Lisa/process_ai() +/mob/living/simple_animal/pet/corgi/Lisa/Life() ..() make_babies() diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index ae19106e1af..869c663e312 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -54,9 +54,8 @@ else if(prob(5)) emote("snuffles") -/mob/living/simple_animal/mouse/process_ai() +/mob/living/simple_animal/mouse/Life() ..() - if(prob(0.5)) stat = UNCONSCIOUS icon_state = "mouse_[mouse_color]_sleep" diff --git a/code/modules/mob/living/simple_animal/friendly/pug.dm b/code/modules/mob/living/simple_animal/friendly/pug.dm index e1e16ef42b2..36ce34094a0 100644 --- a/code/modules/mob/living/simple_animal/friendly/pug.dm +++ b/code/modules/mob/living/simple_animal/friendly/pug.dm @@ -19,7 +19,7 @@ see_in_dark = 5 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY -/mob/living/simple_animal/pet/pug/process_ai() +/mob/living/simple_animal/pet/pug/Life() ..() if(!resting && !buckled) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 50568fb37d0..852d7c406d1 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -30,8 +30,6 @@ var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction - var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever) - //typecache of things this mob will attack in DestroySurroundings() if it has environment_smash var/list/environment_target_typecache = list( /obj/machinery/door/window, @@ -66,12 +64,6 @@ walk(src, 0) return 0 -/mob/living/simple_animal/hostile/process_ai() - ..() - if(!AICanContinue()) - return 0 - return 1 - /mob/living/simple_animal/hostile/handle_automated_action() if(AIStatus == AI_OFF) return 0 @@ -83,7 +75,7 @@ DestroySurroundings() if(!MoveToTarget(possible_targets)) //if we lose our target if(AIShouldSleep(possible_targets)) // we try to acquire a new one - AIStatus = AI_IDLE // otherwise we go idle + toggle_ai(AI_IDLE) // otherwise we go idle return 1 /mob/living/simple_animal/hostile/attacked_by(obj/item/I, mob/living/user) @@ -264,8 +256,8 @@ if(search_objects)//Turn off item searching and ignore whatever item we were looking at, we're more concerned with fight or flight search_objects = 0 target = null - if(AIStatus == AI_IDLE) - AIStatus = AI_ON + if(AIStatus != AI_ON && AIStatus != AI_OFF) + toggle_ai(AI_ON) FindTarget() else if(target != null && prob(40))//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one FindTarget() @@ -401,9 +393,43 @@ if(AI_IDLE) if(FindTarget(possible_targets, 1)) . = 1 - AIStatus = AI_ON //Wake up for more than one Life() cycle. + toggle_ai(AI_ON) //Wake up for more than one Life() cycle. else . = 0 /mob/living/simple_animal/hostile/proc/AIShouldSleep(var/list/possible_targets) return !FindTarget(possible_targets, 1) + +/mob/living/simple_animal/hostile/consider_wakeup() + ..() + var/list/tlist + var/turf/T = get_turf(src) + + if(!T) + return + + if(!length(SSmobs.clients_by_zlevel[T.z])) // It's fine to use .len here but doesn't compile on 511 + toggle_ai(AI_Z_OFF) + return + + var/cheap_search = isturf(T) && !(T.z == 1) // The original check for SSmapping's station z level trait, unfortunately it isn't here. + if(cheap_search) + tlist = ListTargetsLazy(T.z) + else + tlist = ListTargets() + + if(AIStatus == AI_IDLE && FindTarget(tlist, 1)) + if(cheap_search) //Try again with full effort + FindTarget() + toggle_ai(AI_ON) + +/mob/living/simple_animal/hostile/proc/ListTargetsLazy(var/_Z)//Step 1, find out what we can see + var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha, /obj/spacepod)) + . = list() + for(var/I in SSmobs.clients_by_zlevel[_Z]) + var/mob/M = I + if(get_dist(M, src) < vision_range) + if(isturf(M.loc)) + . += M + else if(M.loc.type in hostile_machines) + . += M.loc \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm index 81b384f56b7..60b0f7277c8 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm @@ -142,7 +142,7 @@ var/pre_attack = 0 loot = list(/obj/item/asteroid/goliath_hide{layer = 4.1}) -/mob/living/simple_animal/hostile/asteroid/goliath/process_ai() +/mob/living/simple_animal/hostile/asteroid/goliath/Life() ..() handle_preattack() diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index b4019cff988..867b0eb5073 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -80,10 +80,14 @@ var/deathmessage = "" var/death_sound = null //The sound played on death + var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever) + var/can_have_ai = TRUE //once we have become sentient, we can never go back + var/shouldwakeup = FALSE //convenience var for forcibly waking up an idling AI on next check. + /mob/living/simple_animal/Initialize() ..() - GLOB.simple_animal_list += src + GLOB.simple_animals[AIStatus] += src verbs -= /mob/verb/observe if(!can_hide) verbs -= /mob/living/simple_animal/verb/hide @@ -97,7 +101,18 @@ collar.forceMove(loc) collar = null master_commander = null - GLOB.simple_animal_list -= src + GLOB.simple_animals[AIStatus] -= src + if(SSnpcpool.state == SS_PAUSED && LAZYLEN(SSnpcpool.currentrun)) + SSnpcpool.currentrun -= src + + if(nest) + nest.spawned_mobs -= src + nest = null + + var/turf/T = get_turf(src) + if (T && AIStatus == AI_Z_OFF) + SSidlenpcpool.idle_mobs_by_zlevel[T.z] -= src + return ..() /mob/living/simple_animal/Login() @@ -111,12 +126,6 @@ health = Clamp(health, 0, maxHealth) med_hud_set_status() - -/mob/living/simple_animal/proc/process_ai() - handle_automated_movement() - handle_automated_action() - handle_automated_speech() - /mob/living/simple_animal/lay_down() ..() handle_resting_state_icons() @@ -562,6 +571,8 @@ /* End Inventory */ /mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion + toggle_ai(AI_OFF) + can_have_ai = FALSE return /mob/living/simple_animal/update_sight() @@ -581,4 +592,37 @@ return /mob/living/simple_animal/can_hear() - . = TRUE \ No newline at end of file + . = TRUE + +/mob/living/simple_animal/proc/consider_wakeup() + if(pulledby || shouldwakeup) + toggle_ai(AI_ON) + +/mob/living/simple_animal/adjustHealth(amount, updating_health = TRUE, forced = FALSE) + . = ..() + if(!ckey && !stat)//Not unconscious + if(AIStatus == AI_IDLE) + toggle_ai(AI_ON) + +/mob/living/simple_animal/proc/toggle_ai(togglestatus) + if(!can_have_ai && (togglestatus != AI_OFF)) + return + if(AIStatus != togglestatus) + if(togglestatus > 0 && togglestatus < 5) + if(togglestatus == AI_Z_OFF || AIStatus == AI_Z_OFF) + var/turf/T = get_turf(src) + if(AIStatus == AI_Z_OFF) + SSidlenpcpool.idle_mobs_by_zlevel[T.z] -= src + else + SSidlenpcpool.idle_mobs_by_zlevel[T.z] += src + GLOB.simple_animals[AIStatus] -= src + GLOB.simple_animals[togglestatus] += src + AIStatus = togglestatus + else + stack_trace("Something attempted to set simple animals AI to an invalid state: [togglestatus]") + +/mob/living/simple_animal/onTransitZ(old_z, new_z) + ..() + if(AIStatus == AI_Z_OFF) + SSidlenpcpool.idle_mobs_by_zlevel[old_z] -= src + toggle_ai(initial(AIStatus)) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/spawner.dm b/code/modules/mob/living/simple_animal/spawner.dm index 7a17dfb202b..686a20cee36 100644 --- a/code/modules/mob/living/simple_animal/spawner.dm +++ b/code/modules/mob/living/simple_animal/spawner.dm @@ -29,7 +29,7 @@ spawned_mobs = null return ..() -/mob/living/simple_animal/hostile/spawner/process_ai() +/mob/living/simple_animal/hostile/spawner/Life() ..() spawn_mob() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 3e9ff0b7ba6..6a078ff2ba9 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -202,3 +202,4 @@ var/list/tkgrabbed_objects = list() // Assoc list of items to TK grabs var/forced_look = null // This can either be a numerical direction or a soft object reference (UID). It makes the mob always face towards the selected thing. + var/registered_z \ No newline at end of file diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index a46b9a94fc7..bbc3d6d7abe 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -193,7 +193,7 @@ close_spawn_windows() var/obj/O = locate("landmark*Observer-Start") to_chat(src, "Now teleporting.") - observer.loc = O.loc + observer.forceMove(O.loc) observer.timeofdeath = world.time // Set the time of death so that the respawn timer works correctly. client.prefs.update_preview_icon(1) observer.icon = client.prefs.preview_icon @@ -344,27 +344,27 @@ else if(IsSyndicateCommand(rank)) character.loc = pick(syndicateofficer) else - character.loc = pick(aroomwarp) + character.forceMove(pick(aroomwarp)) join_message = "has arrived" else if(spawning_at) S = spawntypes[spawning_at] if(S && istype(S)) if(S.check_job_spawning(rank)) - character.loc = pick(S.turfs) + character.forceMove(pick(S.turfs)) join_message = S.msg else to_chat(character, "Your chosen spawnpoint ([S.display_name]) is unavailable for your chosen job. Spawning you at the Arrivals shuttle instead.") - character.loc = pick(latejoin) + character.forceMove(pick(latejoin)) join_message = "has arrived on the station" else - character.loc = pick(latejoin) + character.forceMove(pick(latejoin)) join_message = "has arrived on the station" character.lastarea = get_area(loc) // Moving wheelchair if they have one if(character.buckled && istype(character.buckled, /obj/structure/chair/wheelchair)) - character.buckled.loc = character.loc + character.buckled.forceMove(character.loc) character.buckled.dir = character.dir character = SSjobs.EquipRank(character, rank, 1) //equips the human diff --git a/code/modules/pda/cart_apps.dm b/code/modules/pda/cart_apps.dm index de2414da743..a66e72d17a3 100644 --- a/code/modules/pda/cart_apps.dm +++ b/code/modules/pda/cart_apps.dm @@ -392,7 +392,7 @@ BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null) var/CbotData[0] - for(var/mob/living/simple_animal/bot/cleanbot/B in GLOB.simple_animal_list) + for(var/mob/living/simple_animal/bot/cleanbot/B in GLOB.simple_animals) var/turf/bl = get_turf(B) if(bl) if(bl.z != cl.z) diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 44edebdca50..c130ea1d447 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -1,9 +1,12 @@ // Shuttle on-movement // -/atom/movable/proc/onShuttleMove(turf/T1, rotation) - if(rotation) - shuttleRotate(rotation) - forceMove(T1) - return 1 +/atom/movable/proc/onShuttleMove(turf/oldT, turf/T1, rotation) + var/turf/newT = get_turf(src) + if(newT.z != oldT.z) + onTransitZ(oldT.z, newT.z) + if(rotation) + shuttleRotate(rotation) + forceMove(T1) + return 1 /atom/movable/lighting_overlay/onShuttleMove() return 0 diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index f3c0249941b..5c6445b2927 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -501,7 +501,7 @@ //move mobile to new location for(var/atom/movable/AM in T0) - AM.onShuttleMove(T1, rotation) + AM.onShuttleMove(T0, T1, rotation) if(rotation) T1.shuttleRotate(rotation) diff --git a/paradise.dme b/paradise.dme index 1b7a691c820..271e872ba5a 100644 --- a/paradise.dme +++ b/paradise.dme @@ -57,7 +57,6 @@ #include "code\__DEFINES\rolebans.dm" #include "code\__DEFINES\shuttle.dm" #include "code\__DEFINES\sight.dm" -#include "code\__DEFINES\snpc.dm" #include "code\__DEFINES\sound.dm" #include "code\__DEFINES\stat.dm" #include "code\__DEFINES\station_goals.dm" @@ -199,7 +198,6 @@ #include "code\controllers\subsystem.dm" #include "code\controllers\verbs.dm" #include "code\controllers\Processes\lighting.dm" -#include "code\controllers\Processes\npcai.dm" #include "code\controllers\Processes\ticker.dm" #include "code\controllers\ProcessScheduler\core\process.dm" #include "code\controllers\ProcessScheduler\core\processScheduler.dm" @@ -212,6 +210,7 @@ #include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\holiday.dm" #include "code\controllers\subsystem\icon_smooth.dm" +#include "code\controllers\subsystem\idlenpcpool.dm" #include "code\controllers\subsystem\jobs.dm" #include "code\controllers\subsystem\machinery.dm" #include "code\controllers\subsystem\mapping.dm" @@ -219,7 +218,6 @@ #include "code\controllers\subsystem\nano_mob_hunter.dm" #include "code\controllers\subsystem\nanoui.dm" #include "code\controllers\subsystem\nightshift.dm" -#include "code\controllers\subsystem\npcai.dm" #include "code\controllers\subsystem\npcpool.dm" #include "code\controllers\subsystem\overlays.dm" #include "code\controllers\subsystem\radio.dm" @@ -1237,7 +1235,6 @@ #include "code\modules\awaymissions\loot.dm" #include "code\modules\awaymissions\map_rng.dm" #include "code\modules\awaymissions\pamphlet.dm" -#include "code\modules\awaymissions\snpc.dm" #include "code\modules\awaymissions\trigger.dm" #include "code\modules\awaymissions\zlevel.dm" #include "code\modules\awaymissions\zvis.dm" @@ -1253,7 +1250,6 @@ #include "code\modules\awaymissions\mission_code\evil_santa.dm" #include "code\modules\awaymissions\mission_code\spacebattle.dm" #include "code\modules\awaymissions\mission_code\spacehotel.dm" -#include "code\modules\awaymissions\mission_code\spacehotel_npcs.dm" #include "code\modules\awaymissions\mission_code\stationCollision.dm" #include "code\modules\awaymissions\mission_code\UO71-terrorspiders.dm" #include "code\modules\awaymissions\mission_code\wildwest.dm" @@ -1746,9 +1742,6 @@ #include "code\modules\mob\living\carbon\human\status_procs.dm" #include "code\modules\mob\living\carbon\human\update_icons.dm" #include "code\modules\mob\living\carbon\human\update_stat.dm" -#include "code\modules\mob\living\carbon\human\interactive\functions.dm" -#include "code\modules\mob\living\carbon\human\interactive\interactive.dm" -#include "code\modules\mob\living\carbon\human\interactive\prefabs.dm" #include "code\modules\mob\living\carbon\human\species\_species.dm" #include "code\modules\mob\living\carbon\human\species\abductor.dm" #include "code\modules\mob\living\carbon\human\species\diona.dm" diff --git a/strings/npc_chatter.json b/strings/npc_chatter.json deleted file mode 100644 index 833cb68605e..00000000000 --- a/strings/npc_chatter.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "nouns_insult": [ - "gaylord", - "shitcurity", - "noob", - "comdom", - "greyshirt", - "tator", - "lingbin", - "bitch", - "whorelord", - "cluwne", - "monkey", - "cheesemonger", - "milkdrinker" - ], - "adjective_objects": [ - "big", - "small", - "tiny", - "round", - "square", - "oblong", - "colorful", - "dull", - "shiny", - "sparkling", - "blinking", - "awful" - ], - "verbs_use": [ - "touch", - "hold", - "poke", - "punch", - "smash", - "assault", - "wrench", - "tickle", - "modify", - "whack", - "beat", - "tackle", - "destroy" - ], - "nouns_objects": [ - "thing", - "tool", - "whatever", - "potential murder weapon", - "object", - "toy", - "device", - "whatever" - ], - "nouns_generic": [ - "you", - "you there", - "guy", - "person", - "dude", - "jerk", - "officer" - ], - "curse_words": [ - "damn", - "shit", - "arse", - "ass", - "wank", - "jerk", - "bitch" - ], - "adjective_generic": [ - "nice", - "pretty", - "ugly", - "bad", - "okay", - "stupid" - ], - "verbs_move": [ - "run", - "jog", - "leg it", - "slide", - "cheese it", - "walk", - "stroll", - "fly", - "scoot", - "yakkety", - "speed", - "fuck off", - "escape" - ], - "verbs_touch": [ - "pat", - "mess with", - "absorb", - "sneeze on", - "inject", - "rip", - "slap", - "grab", - "choke" - ], - "adjective_insult": [ - "ugly", - "repulsive", - "dumb", - "asian", - "mongoloid", - "childish", - "captain-like", - "monkey-like", - "whoreish", - "dimwit", - "jerk-face", - "vomit-inducer" - ], - "nouns_body": [ - "ass", - "head", - "face", - "arms", - "fingers", - "toes", - "chest", - "eyes", - "nails", - "groin", - "stomach", - "intestines", - "head" - ] -}

Name

Status

Location

Control

[Bot.hacked ? "(!) [Bot.name]" : Bot.name] ([Bot.model])