Adds dextrous guardian (#19254)

Added dextrous guardians to the code, able to hold and use items and store a single item within themselves.

Dextrous guardians do low damage on punches, have medium damage resist, and recalling or leashing will force them to drop any items in their hands.
This commit is contained in:
Joan Lung
2016-07-13 11:25:00 +12:00
committed by oranges
parent 7100277ca3
commit fe28096320
23 changed files with 351 additions and 169 deletions
+3 -3
View File
@@ -114,16 +114,16 @@
else if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
//if they are holding or wearing a card that has access, that works
if(src.check_access(H.get_active_hand()) || src.check_access(H.wear_id))
if(check_access(H.get_active_hand()) || src.check_access(H.wear_id))
return 1
else if(istype(M, /mob/living/carbon/monkey) || istype(M, /mob/living/carbon/alien/humanoid))
var/mob/living/carbon/george = M
//they can only hold things :(
if(src.check_access(george.get_active_hand()))
if(check_access(george.get_active_hand()))
return 1
else if(isanimal(M))
var/mob/living/simple_animal/A = M
if(check_access(A.access_card))
if(check_access(A.get_active_hand()) || check_access(A.access_card))
return 1
return 0
+1 -1
View File
@@ -247,7 +247,7 @@
S.handle_item_insertion(src)
return 1
S = M.get_item_by_slot(slot_drone_storage) //else we put in whatever is in drone storage
S = M.get_item_by_slot(slot_generic_dextrous_storage) //else we put in whatever is in drone storage
if(istype(S) && S.can_be_inserted(src,1))
S.handle_item_insertion(src)
@@ -228,3 +228,5 @@ Des: Removes all infected images from the alien.
if(see_override)
see_invisible = see_override
/mob/living/carbon/alien/can_hold_items()
return has_fine_manipulation
@@ -1077,6 +1077,9 @@
/mob/living/carbon/human/is_literate()
return 1
/mob/living/carbon/human/can_hold_items()
return TRUE
/mob/living/carbon/human/update_gravity(has_gravity,override = 0)
override = dna.species.override_float
..()
@@ -47,6 +47,8 @@
hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
unique_name = TRUE
faction = list("silicon")
dextrous = TRUE
dextrous_hud_type = /datum/hud/dextrous/drone
var/staticChoice = "static"
var/list/staticChoices = list("static", "blank", "letter", "animal")
var/picked = FALSE //Have we picked our visual appearence (+ colour if applicable)
@@ -65,7 +67,6 @@
var/seeStatic = 1 //Whether we see static instead of mobs
var/visualAppearence = MAINTDRONE //What we appear as
var/hacked = 0 //If we have laws to destroy the station
var/datum/personal_crafting/handcrafting
/mob/living/simple_animal/drone/New()
. = ..()
@@ -76,7 +77,7 @@
if(default_storage)
var/obj/item/I = new default_storage(src)
equip_to_slot_or_del(I, slot_drone_storage)
equip_to_slot_or_del(I, slot_generic_dextrous_storage)
if(default_hatmask)
var/obj/item/I = new default_hatmask(src)
equip_to_slot_or_del(I, slot_head)
@@ -91,7 +92,6 @@
else
verbs -= /mob/living/simple_animal/drone/verb/toggle_statics
handcrafting = new()
var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC]
diag_hud.add_to_hud(src)
@@ -109,9 +109,6 @@
else
holder.icon_state = "hudstat"
/mob/living/simple_animal/drone/OpenCraftingMenu()
handcrafting.ui_interact(src)
/mob/living/simple_animal/drone/Destroy()
qdel(access_card) //Otherwise it ends up on the floor!
return ..()
@@ -128,8 +125,6 @@
/mob/living/simple_animal/drone/death(gibbed)
..(gibbed)
drop_l_hand()
drop_r_hand()
if(internal_storage)
unEquip(internal_storage)
if(head)
@@ -197,17 +192,6 @@
msg += "*---------*</span>"
user << msg
/mob/living/simple_animal/drone/IsAdvancedToolUser()
return 1
/mob/living/simple_animal/drone/canUseTopic(atom/movable/M, be_close = 0)
if(incapacitated())
return 0
if(be_close && !in_range(M, src))
return 0
return 1
/mob/living/simple_animal/drone/assess_threat() //Secbots won't hunt maintenance drones.
return -10
@@ -6,42 +6,6 @@
//Drone hands
/mob/living/simple_animal/drone/activate_hand(selhand)
if(istext(selhand))
selhand = lowertext(selhand)
if(selhand == "right" || selhand == "r")
selhand = 0
if(selhand == "left" || selhand == "l")
selhand = 1
if(selhand != src.hand)
swap_hand()
else
mode()
/mob/living/simple_animal/drone/swap_hand()
var/obj/item/held_item = get_active_hand()
if(held_item)
if(istype(held_item, /obj/item/weapon/twohanded))
var/obj/item/weapon/twohanded/T = held_item
if(T.wielded == 1)
usr << "<span class='warning'>Your other hand is too busy holding the [T.name].</span>"
return
hand = !hand
if(hud_used && hud_used.inv_slots[slot_l_hand] && hud_used.inv_slots[slot_r_hand])
var/obj/screen/inventory/hand/H
H = hud_used.inv_slots[slot_l_hand]
H.update_icon()
H = hud_used.inv_slots[slot_r_hand]
H.update_icon()
/mob/living/simple_animal/drone/unEquip(obj/item/I, force)
if(..(I,force))
update_inv_hands()
@@ -63,7 +27,7 @@
if(!((I.slot_flags & SLOT_HEAD) || (I.slot_flags & SLOT_MASK)))
return 0
return 1
if(slot_drone_storage)
if(slot_generic_dextrous_storage)
if(internal_storage)
return 0
return 1
@@ -74,7 +38,7 @@
switch(slot_id)
if(slot_head)
return head
if(slot_drone_storage)
if(slot_generic_dextrous_storage)
return internal_storage
..()
@@ -103,7 +67,7 @@
if(slot_head)
head = I
update_inv_head()
if(slot_drone_storage)
if(slot_generic_dextrous_storage)
internal_storage = I
update_inv_internal_storage()
else
@@ -111,15 +75,8 @@
return
/mob/living/simple_animal/drone/stripPanelUnequip(obj/item/what, mob/who, where)
..(what, who, where, 1)
/mob/living/simple_animal/drone/stripPanelEquip(obj/item/what, mob/who, where)
..(what, who, where, 1)
/mob/living/simple_animal/drone/getBackSlot()
return slot_drone_storage
return slot_generic_dextrous_storage
/mob/living/simple_animal/drone/getBeltSlot()
return slot_drone_storage
return slot_generic_dextrous_storage
@@ -1,6 +1,9 @@
var/global/list/parasites = list() //all currently existing/living guardians
#define GUARDIAN_HANDS_LAYER 1
#define GUARDIAN_TOTAL_LAYERS 1
/mob/living/simple_animal/hostile/guardian
name = "Guardian Spirit"
real_name = "Guardian Spirit"
@@ -31,6 +34,8 @@ var/global/list/parasites = list() //all currently existing/living guardians
melee_damage_upper = 15
butcher_results = list(/obj/item/weapon/ectoplasm = 1)
AIStatus = AI_OFF
dextrous_hud_type = /datum/hud/dextrous/guardian //if we're set to dextrous, account for it.
var/list/guardian_overlays[GUARDIAN_TOTAL_LAYERS]
var/reset = 0 //if the summoner has reset the guardian already
var/cooldown = 0
var/mob/living/summoner
@@ -121,6 +126,7 @@ var/global/list/parasites = list() //all currently existing/living guardians
med_hud_set_status()
if(summoner)
if(summoner.stat == DEAD)
forceMove(summoner.loc)
src << "<span class='danger'>Your summoner has died!</span>"
visible_message("<span class='danger'><B>\The [src] dies along with its user!</B></span>")
summoner.visible_message("<span class='danger'><B>[summoner]'s body is completely consumed by the strain of sustaining [src]!</B></span>")
@@ -128,12 +134,12 @@ var/global/list/parasites = list() //all currently existing/living guardians
if(!summoner.unEquip(W))
qdel(W)
summoner.dust()
ghostize()
death(TRUE)
qdel(src)
else
src << "<span class='danger'>Your summoner has died!</span>"
visible_message("<span class='danger'><B>The [src] dies along with its user!</B></span>")
ghostize()
death(TRUE)
qdel(src)
snapback()
@@ -177,9 +183,12 @@ var/global/list/parasites = list() //all currently existing/living guardians
return 1
/mob/living/simple_animal/hostile/guardian/death()
drop_l_hand()
drop_r_hand()
..()
summoner << "<span class='danger'><B>Your [name] died somehow!</span></B>"
summoner.death()
if(summoner)
summoner << "<span class='danger'><B>Your [name] died somehow!</span></B>"
summoner.death()
/mob/living/simple_animal/hostile/guardian/update_health_hud()
if(summoner && hud_used && hud_used.healths)
@@ -221,6 +230,84 @@ var/global/list/parasites = list() //all currently existing/living guardians
ghostize()
qdel(src)
//HAND HANDLING
/mob/living/simple_animal/hostile/guardian/equip_to_slot(obj/item/I, slot)
if(!slot)
return FALSE
if(!istype(I))
return FALSE
. = TRUE
if(I == l_hand)
l_hand = null
else if(I == r_hand)
r_hand = null
update_inv_hands()
if(I.pulledby)
I.pulledby.stop_pulling()
I.screen_loc = null // will get moved if inventory is visible
I.loc = src
I.equipped(src, slot)
I.layer = ABOVE_HUD_LAYER
/mob/living/simple_animal/hostile/guardian/proc/apply_overlay(cache_index)
var/image/I = guardian_overlays[cache_index]
if(I)
add_overlay(I)
/mob/living/simple_animal/hostile/guardian/proc/remove_overlay(cache_index)
if(guardian_overlays[cache_index])
overlays -= guardian_overlays[cache_index]
guardian_overlays[cache_index] = null
/mob/living/simple_animal/hostile/guardian/proc/update_inv_hands()
remove_overlay(GUARDIAN_HANDS_LAYER)
var/list/hands_overlays = list()
if(r_hand)
var/r_state = r_hand.item_state
if(!r_state)
r_state = r_hand.icon_state
var/image/r_hand_image = r_hand.build_worn_icon(state = r_state, default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
hands_overlays += r_hand_image
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
r_hand.layer = ABOVE_HUD_LAYER
r_hand.screen_loc = ui_rhand
client.screen |= r_hand
if(l_hand)
var/l_state = l_hand.item_state
if(!l_state)
l_state = l_hand.icon_state
var/image/l_hand_image = l_hand.build_worn_icon(state = l_state, default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
hands_overlays += l_hand_image
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
l_hand.layer = ABOVE_HUD_LAYER
l_hand.screen_loc = ui_lhand
client.screen |= l_hand
if(hands_overlays.len)
guardian_overlays[GUARDIAN_HANDS_LAYER] = hands_overlays
apply_overlay(GUARDIAN_HANDS_LAYER)
/mob/living/simple_animal/hostile/guardian/update_inv_l_hand()
update_inv_hands()
/mob/living/simple_animal/hostile/guardian/update_inv_r_hand()
update_inv_hands()
/mob/living/simple_animal/hostile/guardian/regenerate_icons()
update_inv_hands()
//MANIFEST, RECALL, TOGGLE MODE/LIGHT, SHOW TYPE
/mob/living/simple_animal/hostile/guardian/proc/Manifest()
@@ -380,7 +467,7 @@ var/global/list/parasites = list() //all currently existing/living guardians
var/used_message = "<span class='holoparasite'>All the cards seem to be blank now.</span>"
var/failure_message = "<span class='holoparasitebold'>..And draw a card! It's...blank? Maybe you should try again later.</span>"
var/ling_failure = "<span class='holoparasitebold'>The deck refuses to respond to a souless creature such as you.</span>"
var/list/possible_guardians = list("Chaos", "Standard", "Ranged", "Support", "Explosive", "Lightning", "Protector", "Charger", "Assassin")
var/list/possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
var/random = TRUE
var/allowmultiple = 0
var/allowling = 1
@@ -449,6 +536,9 @@ var/global/list/parasites = list() //all currently existing/living guardians
if("Assassin")
pickedtype = /mob/living/simple_animal/hostile/guardian/assassin
if("Dextrous")
pickedtype = /mob/living/simple_animal/hostile/guardian/dextrous
var/list/guardians = user.hasparasites()
if(guardians.len && !allowmultiple)
user << "<span class='holoparasite'>You already have a [mob_name]!</span>" //nice try, bucko
@@ -493,6 +583,9 @@ var/global/list/parasites = list() //all currently existing/living guardians
/obj/item/weapon/guardiancreator/tech/choose
random = FALSE
/obj/item/weapon/guardiancreator/tech/choose/dextrous
possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
/obj/item/weapon/paper/guardian
name = "Holoparasite Guide"
icon_state = "paper_words"
@@ -0,0 +1,108 @@
//Dextrous
/mob/living/simple_animal/hostile/guardian/dextrous
melee_damage_lower = 10
melee_damage_upper = 10
damage_coeff = list(BRUTE = 0.75, BURN = 0.75, TOX = 0.75, CLONE = 0.75, STAMINA = 0, OXY = 0.75)
playstyle_string = "<span class='holoparasite'>As a <b>dextrous</b> type you can hold items, store an item within yourself, and have medium damage resistance, but do low damage on attacks. Recalling and leashing will force you to drop unstored items!</span>"
magic_fluff_string = "<span class='holoparasite'>..And draw the Drone, a dextrous master of construction and repair.</span>"
tech_fluff_string = "<span class='holoparasite'>Boot sequence complete. Dextrous combat modules loaded. Holoparasite swarm online.</span>"
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! You caught one! It can hold stuff in its fins, sort of.</span>"
dextrous = 1
environment_target_typecache = list(
/obj/machinery/door/window,
/obj/structure/window,
/obj/structure/closet,
/obj/structure/table,
/obj/structure/grille,
/obj/structure/rack,
/obj/structure/barricade,
/obj/machinery/camera) //so we can also attack cameras
var/obj/item/internal_storage //what we're storing within ourself
/mob/living/simple_animal/hostile/guardian/dextrous/death(gibbed)
..()
if(internal_storage)
unEquip(internal_storage)
/mob/living/simple_animal/hostile/guardian/dextrous/examine(mob/user)
if(dextrous)
var/msg = "<span class='info'>*---------*\nThis is \icon[src] \a <b>[src]</b>!\n"
msg += "[desc]\n"
if(l_hand && !(l_hand.flags&ABSTRACT))
if(l_hand.blood_DNA)
msg += "<span class='warning'>It is holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] blood-stained [l_hand.name] in its left hand!</span>\n"
else
msg += "It is holding \icon[l_hand] \a [l_hand] in its left hand.\n"
if(r_hand && !(r_hand.flags&ABSTRACT))
if(r_hand.blood_DNA)
msg += "<span class='warning'>It is holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] blood-stained [r_hand.name] in its right hand!</span>\n"
else
msg += "It is holding \icon[r_hand] \a [r_hand] in its right hand.\n"
if(internal_storage && !(internal_storage.flags&ABSTRACT))
if(internal_storage.blood_DNA)
msg += "<span class='warning'>It is holding \icon[internal_storage] [internal_storage.gender==PLURAL?"some":"a"] blood-stained [internal_storage.name] in its internal storage!</span>\n"
else
msg += "It is holding \icon[internal_storage] \a [internal_storage] in its internal storage.\n"
msg += "*---------*</span>"
user << msg
else
..()
/mob/living/simple_animal/hostile/guardian/dextrous/Recall()
if(loc == summoner || cooldown > world.time)
return 0
drop_l_hand()
drop_r_hand()
return ..() //lose items, then return
/mob/living/simple_animal/hostile/guardian/dextrous/snapback()
if(summoner && !(get_dist(get_turf(summoner),get_turf(src)) <= range))
drop_l_hand()
drop_r_hand()
..() //lose items, then return
//SLOT HANDLING BULLSHIT FOR INTERNAL STORAGE
/mob/living/simple_animal/hostile/guardian/dextrous/unEquip(obj/item/I, force)
if(..(I,force))
update_inv_hands()
if(I == internal_storage)
internal_storage = null
update_inv_internal_storage()
return 1
return 0
/mob/living/simple_animal/hostile/guardian/dextrous/can_equip(obj/item/I, slot)
switch(slot)
if(slot_generic_dextrous_storage)
if(internal_storage)
return 0
return 1
..()
/mob/living/simple_animal/hostile/guardian/dextrous/equip_to_slot(obj/item/I, slot)
if(!..())
return
switch(slot)
if(slot_generic_dextrous_storage)
internal_storage = I
update_inv_internal_storage()
else
src << "<span class='danger'>You are trying to equip this item to an unsupported inventory slot. Report this to a coder!</span>"
/mob/living/simple_animal/hostile/guardian/dextrous/getBackSlot()
return slot_generic_dextrous_storage
/mob/living/simple_animal/hostile/guardian/dextrous/getBeltSlot()
return slot_generic_dextrous_storage
/mob/living/simple_animal/hostile/guardian/dextrous/proc/update_inv_internal_storage()
if(internal_storage && client && hud_used && hud_used.hud_shown)
internal_storage.screen_loc = ui_id
client.screen += internal_storage
/mob/living/simple_animal/hostile/guardian/dextrous/regenerate_icons()
..()
update_inv_internal_storage()
@@ -234,7 +234,7 @@
/mob/living/simple_animal/hostile/UnarmedAttack(atom/A)
target = A
if(dextrous)
if(dextrous && !is_type_in_typecache(A, environment_target_typecache) && !ismob(A))
..()
else
AttackingTarget()
@@ -78,10 +78,13 @@
var/attacked_sound = "punch" //Played when someone punches the creature
var/dextrous = FALSE //If the creature has, and can use, hands
var/dextrous_hud_type = /datum/hud/dextrous
var/datum/personal_crafting/handcrafting
/mob/living/simple_animal/New()
..()
handcrafting = new()
verbs -= /mob/verb/observe
if(!real_name)
real_name = name
@@ -509,16 +512,25 @@
return 1
return 0
/mob/living/simple_animal/stripPanelUnequip(obj/item/what, mob/who, where, child_override)
if(!child_override)
/mob/living/simple_animal/canUseTopic(atom/movable/M, be_close = 0, no_dextery = 0)
if(incapacitated())
return 0
if(no_dextery || dextrous)
if(be_close && !in_range(M, src))
return 0
else
src << "<span class='warning'>You don't have the dexterity to do this!</span>"
return 0
return 1
/mob/living/simple_animal/stripPanelUnequip(obj/item/what, mob/who, where)
if(!canUseTopic(who, TRUE))
return
else
..()
/mob/living/simple_animal/stripPanelEquip(obj/item/what, mob/who, where, child_override)
if(!child_override)
src << "<span class='warning'>You don't have the dexterity to do this!</span>"
/mob/living/simple_animal/stripPanelEquip(obj/item/what, mob/who, where)
if(!canUseTopic(who, TRUE))
return
else
..()
@@ -584,7 +596,17 @@
//Dextrous simple mobs can use hands!
/mob/living/simple_animal/create_mob_hud()
if(client && !hud_used && dextrous)
hud_used = new /datum/hud/dextrous(src, ui_style2icon(client.prefs.UI_style))
hud_used = new dextrous_hud_type(src, ui_style2icon(client.prefs.UI_style))
/mob/living/simple_animal/OpenCraftingMenu()
if(dextrous)
handcrafting.ui_interact(src)
/mob/living/simple_animal/can_hold_items()
return dextrous
/mob/living/simple_animal/IsAdvancedToolUser()
return dextrous
/mob/living/simple_animal/activate_hand(selhand)
if(!dextrous)
+4 -1
View File
@@ -242,7 +242,7 @@ var/next_mob_id = 0
slot_ears, slot_glasses,\
slot_belt, slot_s_store,\
slot_l_store, slot_r_store,\
slot_drone_storage\
slot_generic_dextrous_storage\
)
for(var/slot in slot_priority)
@@ -938,5 +938,8 @@ var/next_mob_id = 0
/mob/proc/is_literate()
return 0
/mob/proc/can_hold_items()
return FALSE
/mob/proc/get_idcard()
return
+1 -1
View File
@@ -151,7 +151,7 @@
temp_img = icon("icons/ass/assfemale.png")
else //In case anyone ever makes the generic ass. For now I'll be using male asses.
temp_img = icon("icons/ass/assmale.png")
else if(isdrone (ass) || istype(ass,/mob/living/simple_animal/drone)) //Drones are hot
else if(isdrone(ass)) //Drones are hot
temp_img = icon("icons/ass/assdrone.png")
else
break
@@ -236,7 +236,7 @@
slot_ears, slot_glasses,\
slot_belt, slot_s_store,\
slot_l_store, slot_r_store,\
slot_drone_storage
slot_generic_dextrous_storage
)
/obj/item/weapon/reagent_containers/glass/bucket/attackby(obj/O, mob/user, params)
@@ -43,10 +43,11 @@ var/datum/events/keycard_events = new()
/obj/machinery/keycard_auth/ui_status(mob/user)
if(isanimal(user))
user << "<span class='warning'>You are too primitive to use this device!</span>"
else
return ..()
return UI_CLOSE
var/mob/living/simple_animal/A = user
if(!A.dextrous)
user << "<span class='warning'>You are too primitive to use this device!</span>"
return UI_CLOSE
return ..()
/obj/machinery/keycard_auth/ui_act(action, params)
if(..() || waiting || !allowed(usr))
+2 -2
View File
@@ -47,10 +47,10 @@
return UI_INTERACTIVE
return UI_CLOSE
/mob/living/simple_animal/drone/default_can_use_topic(src_object)
/mob/living/simple_animal/default_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
if(. > UI_CLOSE)
. = min(., shared_living_ui_distance(src_object)) // Drones can only use things they're near.
. = min(., shared_living_ui_distance(src_object)) //simple animals can only use things they're near.
/mob/living/silicon/pai/default_can_use_topic(src_object)
// pAIs can only use themselves and the owner's radio.