forked from tgstation/tgstation
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds telekinesis to click code. Fixes issue tgstation#1202, tgstation…
…#1129, tgstation#247. This adds two atom procs, attack_tk() and attack_self_tk(). attack_tk is used as per attack_hand; attack_self_tk exists on all atoms (not just items) but is similar to the item proc, but without the assumption that it is in the user's hand. Removes the functionality where entering throw mode would create a tk grab, as it is redundant. As a default, attack_tk does the following: * Creates a telekinetic throw for items and un-anchored objects * Does an attack_hand (paw, animal, etc) for anchored objects * Does nothing to mobs As a default, attack_self_tk does nothing. An attack_self_tk was added to closets to open and close them since that's a common thing. The following items have added attack_tk procs: * Fire axe cabinet, extinguisher cabinet, and bedsheet bin will drop into their square instead of putting it in your hand * Doors only open telekinetically if they require no access * Chairs will rotate if nobody is buckled to them * Filing cabinets will remove a paper at random. * Tables and racks return to prevent telehulk smash This is INCOMPLETE. Adding proper TK interaction to everything is something best done in pieces. In particular, interacting with mobs and items both open up the floodgates for bugs, so we/I need to decide how we want it to go before we commit, and then fix bugs along the way. Stumbling forward, fixing bugs, and then changing course halfway would be a bad idea.
- Loading branch information
Showing
22 changed files
with
341 additions
and
185 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
305 changes: 177 additions & 128 deletions
305
code/game/objects/items/tk_grab.dm → code/_onclick/telekinesis.dm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,128 +1,177 @@ | ||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 | ||
|
||
/obj/item/tk_grab | ||
name = "Telekinetic Grab" | ||
desc = "Magic" | ||
icon = 'icons/obj/magic.dmi'//Needs sprites | ||
icon_state = "2" | ||
flags = USEDELAY | NOBLUDGEON | ||
//item_state = null | ||
w_class = 10.0 | ||
layer = 20 | ||
|
||
var/last_throw = 0 | ||
var/obj/focus = null | ||
var/mob/living/host = null | ||
|
||
|
||
dropped(mob/user as mob) | ||
del(src) | ||
return | ||
|
||
|
||
//stops TK grabs being equipped anywhere but into hands | ||
equipped(var/mob/user, var/slot) | ||
if( (slot == slot_l_hand) || (slot== slot_r_hand) ) return | ||
del(src) | ||
return | ||
|
||
/* | ||
attack_self(mob/user as mob) | ||
if(!istype(focus,/obj/item)) return | ||
if(!check_path()) return//No clear path | ||
user.put_in_hands(focus) | ||
add_fingerprint(user) | ||
user.update_inv_l_hand(0) | ||
user.update_inv_r_hand() | ||
spawn(0) | ||
del(src) | ||
return | ||
*/ | ||
|
||
afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)//TODO: go over this | ||
if(!target || !user) return | ||
if(last_throw+3 > world.time) return | ||
if(!host) | ||
del(src) | ||
return | ||
if(!(TK in host.mutations)) | ||
del(src) | ||
return | ||
if(isobj(target)) | ||
if(!target.loc || !isturf(target.loc)) | ||
del(src) | ||
return | ||
if(!focus) | ||
focus_object(target, user) | ||
return | ||
var/focusturf = get_turf(focus) | ||
if(get_dist(focusturf, target) <= 1 && !istype(target, /turf)) | ||
target.attackby(focus, user, user:get_organ_target()) | ||
|
||
else if(get_dist(focusturf, target) <= 16) | ||
apply_focus_overlay() | ||
focus.throw_at(target, 10, 1) | ||
last_throw = world.time | ||
return | ||
|
||
|
||
proc/focus_object(var/obj/target, var/mob/living/user) | ||
if(!istype(target,/obj)) return//Cant throw non objects atm might let it do mobs later | ||
if(target.anchored) | ||
target.attack_hand(user) // you can use shit now! | ||
return//No throwing anchored things | ||
if(!isturf(target.loc)) | ||
return | ||
focus = target | ||
update_icon() | ||
apply_focus_overlay() | ||
return | ||
|
||
|
||
proc/apply_focus_overlay() | ||
if(!focus) return | ||
var/obj/effect/overlay/O = new /obj/effect/overlay(locate(focus.x,focus.y,focus.z)) | ||
O.name = "sparkles" | ||
O.anchored = 1 | ||
O.density = 0 | ||
O.layer = FLY_LAYER | ||
O.dir = pick(cardinal) | ||
O.icon = 'icons/effects/effects.dmi' | ||
O.icon_state = "nothing" | ||
flick("empdisable",O) | ||
spawn(5) | ||
O.delete() | ||
return | ||
|
||
|
||
update_icon() | ||
overlays.Cut() | ||
if(focus && focus.icon && focus.icon_state) | ||
overlays += icon(focus.icon,focus.icon_state) | ||
return | ||
|
||
/*Not quite done likely needs to use something thats not get_step_to | ||
proc/check_path() | ||
var/turf/ref = get_turf(src.loc) | ||
var/turf/target = get_turf(focus.loc) | ||
if(!ref || !target) return 0 | ||
var/distance = get_dist(ref, target) | ||
if(distance >= 10) return 0 | ||
for(var/i = 1 to distance) | ||
ref = get_step_to(ref, target, 0) | ||
if(ref != target) return 0 | ||
return 1 | ||
*/ | ||
|
||
//equip_to_slot_or_del(obj/item/W, slot, del_on_fail = 1) | ||
/* | ||
if(istype(user, /mob/living/carbon)) | ||
if(user:mutations & TK && get_dist(source, user) <= 7) | ||
if(user:get_active_hand()) return 0 | ||
var/X = source:x | ||
var/Y = source:y | ||
var/Z = source:z | ||
*/ | ||
|
||
/* | ||
Telekinesis | ||
This needs more thinking out, but I might as well. | ||
*/ | ||
|
||
// click on atom with an empty hand, not Adjacent | ||
/atom/proc/attack_tk(mob/user) | ||
if(user.stat) return | ||
user.UnarmedAttack(src) // attack_hand, attack_paw, etc | ||
return | ||
|
||
// click on atom with itself using a tk_grab, by default do nothing | ||
/atom/proc/attack_self_tk(mob/user) | ||
return | ||
|
||
/obj/attack_tk(mob/user) | ||
if(user.stat) return | ||
if(anchored) | ||
..() | ||
return | ||
|
||
var/obj/item/tk_grab/O = new(src) | ||
user.put_in_active_hand(O) | ||
O.host = user | ||
O.focus_object(src) | ||
return | ||
|
||
/obj/item/attack_tk(mob/user) | ||
if(user.stat || !isturf(loc)) return | ||
if((TK in user.mutations) && !user.get_active_hand()) // both should already be true to get here | ||
var/obj/item/tk_grab/O = new(src) | ||
user.put_in_active_hand(O) | ||
O.host = user | ||
O.focus_object(src) | ||
else | ||
warning("Strange attack_tk(): TK([TK in user.mutations]) empty hand([!user.get_active_hand()])") | ||
return | ||
|
||
|
||
/mob/attack_tk(mob/user) | ||
return // needs more thinking about | ||
|
||
|
||
/obj/item/tk_grab | ||
name = "Telekinetic Grab" | ||
desc = "Magic" | ||
icon = 'icons/obj/magic.dmi'//Needs sprites | ||
icon_state = "2" | ||
flags = USEDELAY | NOBLUDGEON | ||
//item_state = null | ||
w_class = 10.0 | ||
layer = 20 | ||
|
||
var/last_throw = 0 | ||
var/obj/focus = null | ||
var/mob/living/host = null | ||
|
||
|
||
dropped(mob/user as mob) | ||
if(focus && user && loc != user && loc != user.loc) // drop_item() gets called when you tk-attack a table/closet with an item | ||
if(focus.Adjacent(loc)) | ||
focus.loc = loc | ||
|
||
del(src) | ||
return | ||
|
||
|
||
//stops TK grabs being equipped anywhere but into hands | ||
equipped(var/mob/user, var/slot) | ||
if( (slot == slot_l_hand) || (slot== slot_r_hand) ) return | ||
del(src) | ||
return | ||
|
||
|
||
attack_self(mob/user as mob) | ||
if(focus) | ||
focus.attack_self_tk(user) | ||
|
||
afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)//TODO: go over this | ||
if(!target || !user) return | ||
if(last_throw+3 > world.time) return | ||
if(!host) | ||
del(src) | ||
return | ||
if(!(TK in host.mutations)) | ||
del(src) | ||
return | ||
if(isobj(target)) | ||
if(!target.loc || !isturf(target.loc)) | ||
del(src) | ||
return | ||
if(!focus) | ||
focus_object(target, user) | ||
return | ||
|
||
if(target == focus) | ||
target.attack_self_tk(user) | ||
return // todo: something like attack_self not laden with assumptions inherent to attack_self | ||
|
||
var/focusturf = get_turf(focus) | ||
if(get_dist(focusturf, target) <= 1 && !istype(target, /turf)) | ||
target.attackby(focus, user, user:get_organ_target()) | ||
|
||
else if(get_dist(focusturf, target) <= 16) | ||
apply_focus_overlay() | ||
focus.throw_at(target, 10, 1) | ||
last_throw = world.time | ||
return | ||
|
||
attack(mob/living/M as mob, mob/living/user as mob, def_zone) | ||
if(focus && focus.Adjacent(M)) | ||
if(istype(focus,/obj/item)) | ||
var/obj/item/I = focus | ||
I.attack(M,user,def_zone) | ||
return | ||
|
||
|
||
proc/focus_object(var/obj/target, var/mob/living/user) | ||
if(!istype(target,/obj)) return//Cant throw non objects atm might let it do mobs later | ||
if(target.anchored) | ||
target.attack_hand(user) // you can use shit now! | ||
return//No throwing anchored things | ||
if(!isturf(target.loc)) | ||
return | ||
focus = target | ||
update_icon() | ||
apply_focus_overlay() | ||
return | ||
|
||
|
||
proc/apply_focus_overlay() | ||
if(!focus) return | ||
var/obj/effect/overlay/O = new /obj/effect/overlay(locate(focus.x,focus.y,focus.z)) | ||
O.name = "sparkles" | ||
O.anchored = 1 | ||
O.density = 0 | ||
O.layer = FLY_LAYER | ||
O.dir = pick(cardinal) | ||
O.icon = 'icons/effects/effects.dmi' | ||
O.icon_state = "nothing" | ||
flick("empdisable",O) | ||
spawn(5) | ||
O.delete() | ||
return | ||
|
||
|
||
update_icon() | ||
overlays.Cut() | ||
if(focus && focus.icon && focus.icon_state) | ||
overlays += icon(focus.icon,focus.icon_state) | ||
return | ||
|
||
/*Not quite done likely needs to use something thats not get_step_to | ||
proc/check_path() | ||
var/turf/ref = get_turf(src.loc) | ||
var/turf/target = get_turf(focus.loc) | ||
if(!ref || !target) return 0 | ||
var/distance = get_dist(ref, target) | ||
if(distance >= 10) return 0 | ||
for(var/i = 1 to distance) | ||
ref = get_step_to(ref, target, 0) | ||
if(ref != target) return 0 | ||
return 1 | ||
*/ | ||
|
||
//equip_to_slot_or_del(obj/item/W, slot, del_on_fail = 1) | ||
/* | ||
if(istype(user, /mob/living/carbon)) | ||
if(user:mutations & TK && get_dist(source, user) <= 7) | ||
if(user:get_active_hand()) return 0 | ||
var/X = source:x | ||
var/Y = source:y | ||
var/Z = source:z | ||
*/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.