pAI and Held Mob Locations (#510)

Fixes #489
This commit is contained in:
NanakoAC
2016-07-12 15:11:35 +03:00
committed by skull132
parent 6e00593de0
commit c7a5186ef3
7 changed files with 393 additions and 40 deletions
+71 -37
View File
@@ -12,6 +12,10 @@
var/name_dead
var/isalive
var/last_loc_general//This stores a general location of the object. Ie, a container or a mob
var/last_loc_specific//This stores specific extra information about the location, pocket, hand, worn on head, etc. Only relevant to mobs
var/checkverb
/obj/item/weapon/holder/New()
if (!item_state)
item_state = icon_state
@@ -25,17 +29,18 @@
/obj/item/weapon/holder/process()
if(!get_holding_mob())
if (!(istype(loc,/obj/item/weapon/storage)))//Mobs bug out if placed directly into a container
if(!get_holding_mob())
for(var/mob/M in contents)
for(var/mob/M in contents)
var/atom/movable/mob_container
mob_container = M
mob_container.loc = src.loc//if the holder was placed into a disposal, this should place the animal in the disposal
//mob_container.forceMove(get_turf(src))
M.reset_view()
qdel(src)
var/atom/movable/mob_container
mob_container = M
mob_container.loc = src.loc//if the holder was placed into a disposal, this should place the animal in the disposal
M.reset_view()
M.verbs -= /mob/living/proc/get_holder_location
qdel(src)
return
if (isalive && contained.stat == DEAD)
held_death(1)//If we get here, it means the mob died sometime after we picked it up. We pass in 1 so that we can play its deathmessage
@@ -43,22 +48,31 @@
for(var/mob/M in src.contents)
M.attackby(W,user)
/obj/item/weapon/holder/proc/get_holding_mob()
//This function will return the mob which is holding this holder, or null if it's not held
//It recurses up the hierarchy out of containers until it reaches a mob, or aturf, or hits the limit
var/x = 0//As a safety, we'll crawl up a maximum of five layers
var/atom/a = src
while (x < 5)
x++
a = a.loc
if (istype(a, /turf))
return null//We must be on a table or a floor, or maybe in a wall. Either way we're not held.
/obj/item/weapon/holder/dropped(mob/user)
///When an object is put into a container, drop fires twice.
//once with it on the floor, and then once in the container
//This conditional allows us to ignore that first one. Handling of mobs dropped on the floor is done in process
if (istype(loc, /turf))
return
if (istype(loc, /obj/item/weapon/storage)) //The second drop reads the container its placed into as the location
update_location()
/obj/item/weapon/holder/equipped(var/mob/user, var/slot)
..()
update_location(slot)
/obj/item/weapon/holder/proc/update_location(var/slotnumber = null)
if (!slotnumber)
if (istype(loc, /mob))
slotnumber = get_equip_slot()
report_onmob_location(1, slotnumber, contained)
if (istype(a, /mob))
return a
//If none of the above are true, we must be inside a box or backpack or something. Keep recursing up.
return null//If we get here, the holder must be buried many layers deep in nested containers. Shouldn't happen
/obj/item/weapon/holder/attack_self(mob/M as mob)
@@ -115,22 +129,43 @@
grabber << "Your hand is full!"
return
src.verbs += /mob/living/proc/get_holder_location//This has to be before we move the mob into the holder
var/obj/item/weapon/holder/H = new holder_type(loc)
src.loc = H
H.name = loc.name
H.attack_hand(grabber)
H.contained = src
if (src.stat == DEAD)
H.held_death()//We've scooped up an animal that's already dead. use the proper dead icons
else
H.isalive = 1//We note that the mob is alive when picked up. If it dies later, we can know that its death happened while held, and play its deathmessage for it
spawn(2)
var/obj/item/weapon/holder/H = new holder_type(loc)
src.loc = H
H.name = loc.name
grabber << "You scoop up [src]."
src << "[grabber] scoops you up."
grabber.status_flags |= PASSEMOTES
return
H.contained = src
if (src.stat == DEAD)
H.held_death()//We've scooped up an animal that's already dead. use the proper dead icons
else
H.isalive = 1//We note that the mob is alive when picked up. If it dies later, we can know that its death happened while held, and play its deathmessage for it
grabber << "You scoop up [src]."
src << "[grabber] scoops you up."
grabber.status_flags |= PASSEMOTES
H.attack_hand(grabber)//We put this last to prevent some race conditions
return
/mob/living/proc/get_holder_location()
set category = "Abilities"
set name = "Check held location"
set desc = "Find out where on their person, someone is holding you."
if (!usr.get_holding_mob())
src << "Nobody is holding you!"
return
if (istype(usr.loc, /obj/item/weapon/holder))
var/obj/item/weapon/holder/H = usr.loc
H.report_onmob_location(0, H.get_equip_slot(), src)
//Mob specific holders.
//w_class mainly determines whether they can fit in trashbags. <=2 can, >=3 cannot
@@ -227,7 +262,6 @@
origin_tech = "biotech=2"
w_class = 1
/obj/item/weapon/holder/mouse/white
icon_state = "mouse_white"
icon_state_dead = "mouse_white_dead"
+24 -2
View File
@@ -72,7 +72,15 @@
var/current_pda_messaging = null
/mob/living/silicon/pai/New(var/obj/item/device/paicard)
/mob/living/silicon/pai/New(var/obj/item/device/paicard/newlocation)
var/obj/item/device/paicard/paicard
if (istype(newlocation, /obj/item/device/paicard))
paicard = newlocation
else
//If we get here, then we must have been created by adminspawning.
//so lets assist with debugging by creating our own card and adding ourself to it
paicard = new/obj/item/device/paicard(newlocation)
paicard.pai = src
canmove = 0
src.loc = paicard
@@ -333,6 +341,17 @@
verbs -= /mob/living/silicon/pai/proc/choose_chassis
verbs += /mob/living/proc/hide
/mob/living/silicon/pai/verb/get_onmob_location()
set category = "pAI Commands"
set name = "Check location"
set desc = "Find out where on their person, someone is holding you."
if (!get_holding_mob())
src << "Nobody is holding you!"
return
card.report_onmob_location(0, card.get_equip_slot(), src)
/mob/living/silicon/pai/proc/choose_verbs()
set category = "pAI Commands"
set name = "Choose Speech Verbs"
@@ -389,7 +408,8 @@
src.stop_pulling()
src.client.perspective = EYE_PERSPECTIVE
src.client.eye = card
src.client.eye = src
//Changed the client eye to follow the mob itself instead of the card that contains it. This makes examining work, and the camera still follows wherever the card goes
//stop resting
resting = 0
@@ -417,3 +437,5 @@
// No binary for pAIs.
/mob/living/silicon/pai/binarycheck()
return 0
+23
View File
@@ -94,6 +94,29 @@
else
M.show_message(message, 1, blind_message, 2)
// Designed for mobs contained inside things, where a normal visible message wont actually be visible
// Useful for visible actions by pAIs, and held mobs
// Broadcaster is the place the action will be seen/heard from, mobs in sight of THAT will see the message. This is generally the object or mob that src is contained in
// message is the message output to anyone who can see e.g. "[src] does something!"
// self_message (optional) is what the src mob sees e.g. "You do something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
/mob/proc/contained_visible_message(var/atom/broadcaster, var/message, var/self_message, var/blind_message)
var/self_served = 0
for(var/mob/M in viewers(broadcaster))
if(self_message && M==src)
M.show_message(self_message, 1, blind_message, 2)
self_served = 1
else if(M.see_invisible < invisibility) // Cannot view the invisible, but you can hear it.
if(blind_message)
M.show_message(blind_message, 2)
else
M.show_message(message, 1, blind_message, 2)
if (!self_served)
src.show_message(self_message, 1, blind_message, 2)
// Show a message to all mobs in sight of this atom
// Use for objects performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
+214
View File
@@ -720,4 +720,218 @@ proc/is_blind(A)
src.visible_message("<span class='warning'>[src] retches, attempting to vomit!</span>","<span class='warning'>You gag and collapse as you feel the urge to vomit, but there's nothing in your stomach!</span>")
Weaken(4)
/obj/proc/get_equip_slot()
//This function is called by an object which is somewhere on a humanoid mob
//It will return the number of the equipment slot its in
if (!istype(loc, /mob/living/carbon/human))//This function is for finding where we are on a human. not valid otherwise
return null
var/mob/living/carbon/human/H = loc
//Now we check various slots on the mob, the order of these is optimised based on how likely we are to be in that slot
if (H.l_hand == src)
return slot_l_hand
else if (H.r_hand == src)
return slot_r_hand
else if (H.l_store == src)
return slot_l_store
else if (H.r_store == src)
return slot_r_store
else if (H.head == src)
return slot_head
else if (H.wear_suit == src)
return slot_wear_suit
else if (H.s_store == src)
return slot_s_store
else if (H.wear_mask == src)
return slot_wear_mask
else if (H.wear_id == src)
return slot_wear_id
else if (H.w_uniform == src)
return slot_w_uniform
else if (H.gloves == src)
return slot_gloves
else if (H.belt == src)
return slot_belt
else if (H.back == src)
return slot_back
else if (H.r_ear == src)
return slot_r_ear
else if (H.l_ear == src)
return slot_l_ear
else if (H.shoes == src)
return slot_shoes
else
return null//We failed to find the slot
/* Variables to check
l_hand
r_hand
head
l_store //Left and right pockets
r_store
s_store //Suit storage?
wear_mask,
wear_id
w_uniform //the uniform
wear_suit
gloves
belt
back
r_ear
l_ear
shoes
*/
/obj/proc/report_onmob_location(var/justmoved, var/slot = null, var/mob/reportto)
var/mob/living/carbon/human/H//The person who the item is on
var/newlocation
var/preposition= ""
var/action = ""
var/action3 = ""
if (istype(loc, /mob/living/carbon/human))//This function is for finding where we are on a human. not valid otherwise
H = loc
else
H = get_holding_mob()
if (slot != null)
if (slot_l_hand == slot)
if (justmoved)
action += "now "
preposition = "in"
action += "being held"
action3 = "holds"
newlocation = "left hand"
else if (slot_r_hand == slot)
if (justmoved)
action += "now "
preposition = "in"
action += "being held"
action3 = "holds"
newlocation = "right hand"
else if (slot_l_store == slot)
if (justmoved)
preposition = "into"
action = "placed"
action3 = "places"
else
preposition = "inside"
newlocation = "left pocket"
else if (slot_r_store == slot)
if (justmoved)
preposition = "into"
action = "placed"
action3 = "places"
else
preposition = "inside"
newlocation = "right pocket"
else if (slot_s_store == slot)
if (justmoved)
preposition = "into"
action = "placed"
action3 = "places"
else
preposition = "inside"
newlocation = "suit storage"
else
if (justmoved)
action += "now "
action += "being worn"
if (slot_head == slot)
preposition = "as"
action3 = "wears"
newlocation = "hat"
else if (slot_wear_suit == slot)
preposition = "over"
action3 = "wears"
newlocation = "uniform"
else if (slot_wear_mask == slot)
preposition = "on"
action3 = "wears"
newlocation = "face"
else if (slot_wear_id == slot)
preposition = "as"
action3 = "wears"
newlocation = "ID"
else if (slot_w_uniform == slot)
preposition = "on"
action3 = "wears"
newlocation = "body"
else if (slot_gloves == slot)
preposition = "on"
action3 = "wears"
newlocation = "hands"
else if (slot_belt == slot)
preposition = "around"
action3 = "wears"
newlocation = "waist"
else if (slot_back == slot)
preposition = "on"
action3 = "wears"
newlocation = "back"
else if (slot_r_ear == slot)
preposition = "on"
action3 = "wears"
newlocation = "right shoulder"//Ill use ear slots for wearing mobs on the shoulder in future
else if (slot_l_ear == slot)
preposition = "on"
action3 = "wears"
newlocation = "left shoulder"
else if (slot_shoes == slot)
preposition = "on"
action3 = "wears"
newlocation = "feet"
else if (istype(loc,/obj/item/device/pda))
var/obj/item/device/pda/S = loc
newlocation = S.name
if (justmoved)
preposition = "into"
action = "slotted"
action3 = "slots"
else
action = "installed"
preposition = "in"
else if (istype(loc,/obj/item/weapon/storage))
var/obj/item/weapon/storage/S = loc
newlocation = S.name
if (justmoved)
preposition = "into"
action = "placed"
action3 = "places"
else
action = "tucked"
preposition = "inside"
if (justmoved)
reportto.contained_visible_message(H, "<span class='notice'>[H] [action3] [reportto] [preposition] their [newlocation]</span>", "<span class='notice'>You are [action] [preposition] [H]'s [newlocation]</span>", "", 1)
else
reportto << "<span class='notice'>You are [action] [preposition] [H]'s [newlocation]</span>"
/atom/proc/get_holding_mob()
//This function will return the mob which is holding this holder, or null if it's not held
//It recurses up the hierarchy out of containers until it reaches a mob, or aturf, or hits the limit
var/x = 0//As a safety, we'll crawl up a maximum of five layers
var/atom/a = src
while (x < 5)
x++
a = a.loc
if (istype(a, /turf))
return null//We must be on a table or a floor, or maybe in a wall. Either way we're not held.
if (istype(a, /mob))
return a
//If none of the above are true, we must be inside a box or backpack or something. Keep recursing up.
return null//If we get here, the holder must be buried many layers deep in nested containers. Shouldn't happen
#undef SAFE_PERP