mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-11 15:14:27 +01:00
Here we go again
This commit is contained in:
@@ -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" = (
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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.")
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 ..()
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,4 +1,5 @@
|
||||
/mob/living/Logout()
|
||||
update_z(null)
|
||||
if(ranged_ability && client)
|
||||
ranged_ability.remove_mousepointer(client)
|
||||
..()
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user