Here we go again

This commit is contained in:
variableundefined
2019-05-03 21:47:07 +08:00
parent 81b7fbc491
commit 6e79364b65
46 changed files with 262 additions and 2623 deletions
@@ -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" = (
-6
View File
@@ -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
+7
View File
@@ -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"
-23
View File
@@ -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
+1 -2
View File
@@ -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())
-41
View File
@@ -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)
+41
View File
@@ -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
+6 -1
View File
@@ -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)
-24
View File
@@ -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
+23 -117
View File
@@ -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
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
+3 -3
View File
@@ -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")
+11 -1
View File
@@ -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)
+6 -1
View File
@@ -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.")
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 ..()
@@ -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, "<span class='warning'>You feel something moving around inside you...</span>")
//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("<span class='warning'>[src] hatches!</span>")
M.forceMove(get_turf(src))
qdel(src)
/obj/item/organ/internal/heart/gland/plasma
cooldown_low = 1200
+2
View File
@@ -741,6 +741,8 @@
throw_item.throw_at(target, 16, 3, src)
visible_message("<span class='danger'>[src] launches [throw_item.name] at [target.name]!</span>")
/obj/machinery/vending/onTransitZ()
return
/*
* Vending machine types
*/
-30
View File
@@ -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, "<span class='interface'>SNPC verbs have been toggled on.</span>")
/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, "<span class='interface'>SNPC verbs have been toggled off.</span>")
/client/proc/toggle_advanced_interaction()
set name = "Toggle Advanced Admin Interaction"
set category = "Admin"
+1 -4
View File
@@ -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 = " <i>(snpc)</i>"
else
logout_status = M.client ? "" : " <i>(logged out)</i>"
logout_status = M.client ? "" : " <i>(logged out)</i>"
var/dname = M.real_name
if(!dname)
dname = M
@@ -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)
@@ -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.")
-85
View File
@@ -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
+1 -1
View File
@@ -69,7 +69,7 @@
visible_message("<span class='warning'>[src] crackles and buzzes violently!</span>")
/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)
+3
View File
@@ -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"
+1 -1
View File
@@ -20,4 +20,4 @@
for(var/datum/light_source/L in light_sources)
L.source_atom.update_light()
return 1
return 1
@@ -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 += "<span class='deadsay'>[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.</span>\n"
if(auto.debugexamine)
var/dodebug = auto.doing2string(auto.doing)
var/interestdebug = auto.interest2string(auto.interest)
msg += "<span class='deadsay'>[p_they(TRUE)] [p_are()] appears to be [interestdebug] and [dodebug].</span>\n"
else if(dna.species.show_ssd)
if(dna.species.show_ssd)
if(!key)
msg += "<span class='deadsay'>[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.</span>\n"
else if(!client)
@@ -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].",
"<br><br>")
/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 = {"<center><img src=ntlogo.png><br><b><font size="1">[paperwork_sentence()]</font></b></center>"}
for(var/I in 1 to rand(10, 20))
P.info += "[paperwork_sentence()] "
P.info += {"<br><br>[pick("Signed", "Sincerely", "Regards")], <font face="Times New Roman"><i>[real_name]</i></font>"}
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
@@ -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("<font color='blue'>Deleted ID due to slot contention</font>")
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
@@ -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 ..()
+9
View File
@@ -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()
+21
View File
@@ -953,6 +953,27 @@
to_chat(src, "<span class='notice'>You can taste [english_list(final_taste_list)].</span>")
/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
+4
View File
@@ -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
+1
View File
@@ -1,4 +1,5 @@
/mob/living/Logout()
update_z(null)
if(ranged_ability && client)
ranged_ability.remove_mousepointer(client)
..()
+4 -4
View File
@@ -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 += "<A HREF=?src=[UID()];botrefresh=\ref[Bot]>Query network status</A><br>"
d += "<table width='100%'><tr><td width='40%'><h3>Name</h3></td><td width='20%'><h3>Status</h3></td><td width='30%'><h3>Location</h3></td><td width='10%'><h3>Control</h3></td></tr>"
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 += "<tr><td width='30%'>[Bot.hacked ? "<span class='bad'>(!) </span>[Bot.name]" : Bot.name] ([Bot.model])</td>"
@@ -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()
@@ -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"
@@ -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)
@@ -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
@@ -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()
@@ -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
. = 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))
@@ -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()
+1
View File
@@ -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
+6 -6
View File
@@ -193,7 +193,7 @@
close_spawn_windows()
var/obj/O = locate("landmark*Observer-Start")
to_chat(src, "<span class='notice'>Now teleporting.</span>")
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
+1 -1
View File
@@ -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)
+8 -5
View File
@@ -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
+1 -1
View File
@@ -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)
+1 -8
View File
@@ -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"
-137
View File
@@ -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"
]
}