mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-11 07:03:30 +01:00
Thrown items can be targeted, has miss chance...
...based on distance, similar to projectiles. Conflicts: code/defines/obj.dm code/game/machinery/kitchen/smartfridge.dm code/game/machinery/vending.dm code/game/mecha/equipment/weapons/weapons.dm code/modules/games/cards.dm code/modules/mob/living/carbon/carbon.dm code/modules/mob/living/living_defense.dm
This commit is contained in:
@@ -141,7 +141,7 @@ var/const/tk_maxrange = 15
|
||||
|
||||
else
|
||||
apply_focus_overlay()
|
||||
focus.throw_at(target, 10, 1)
|
||||
focus.throw_at(target, 10, 1, user)
|
||||
last_throw = world.time
|
||||
return
|
||||
|
||||
|
||||
+1
-3
@@ -387,9 +387,7 @@ var/global/list/PDA_Manifest = list()
|
||||
throw_speed = 1
|
||||
throw_range = 20
|
||||
flags = FPRINT | TABLEPASS | CONDUCT
|
||||
// afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
|
||||
// user.drop_item()
|
||||
// src.throw_at(target, throw_range, throw_speed)
|
||||
|
||||
|
||||
/obj/effect/stop
|
||||
var/victim = null
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
var/l_move_time = 1
|
||||
var/m_flag = 1
|
||||
var/throwing = 0
|
||||
var/thrower
|
||||
var/turf/throw_source = null
|
||||
var/throw_speed = 2
|
||||
var/throw_range = 7
|
||||
var/moved_recently = 0
|
||||
@@ -83,11 +85,13 @@
|
||||
if(A.density && !A.throwpass) // **TODO: Better behaviour for windows which are dense, but shouldn't always stop movement
|
||||
src.throw_impact(A,speed)
|
||||
|
||||
/atom/movable/proc/throw_at(atom/target, range, speed)
|
||||
/atom/movable/proc/throw_at(atom/target, range, speed, thrower)
|
||||
if(!target || !src) return 0
|
||||
//use a modified version of Bresenham's algorithm to get from the atom's current position to that of the target
|
||||
|
||||
src.throwing = 1
|
||||
src.thrower = thrower
|
||||
src.throw_source = get_turf(src) //store the origin turf
|
||||
|
||||
if(usr)
|
||||
if(M_HULK in usr.mutations)
|
||||
@@ -176,6 +180,8 @@
|
||||
//done throwing, either because it hit something or it finished moving
|
||||
if(isobj(src)) src.throw_impact(get_turf(src),speed)
|
||||
src.throwing = 0
|
||||
src.thrower = null
|
||||
src.throw_source = null
|
||||
|
||||
|
||||
//Overlays
|
||||
|
||||
@@ -396,7 +396,7 @@
|
||||
if ( emagged ) // Warning, hungry humans detected: throw fertilizer at them
|
||||
spawn(0)
|
||||
fert.loc = src.loc
|
||||
fert.throw_at(target, 16, 3)
|
||||
fert.throw_at(target, 16, 3, src)
|
||||
src.visible_message("\red <b>[src] launches [fert.name] at [target.name]!</b>")
|
||||
flick("farmbot_broke", src)
|
||||
spawn (FARMBOT_EMAG_DELAY)
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
var/obj/item/meatslab = allmeat[i]
|
||||
var/turf/Tx = locate(src.x - i, src.y, src.z)
|
||||
meatslab.loc = src.loc
|
||||
meatslab.throw_at(Tx,i,3)
|
||||
meatslab.throw_at(Tx,i,3,src)
|
||||
if (!Tx.density)
|
||||
new /obj/effect/decal/cleanable/blood/gibs(Tx,i)
|
||||
src.operating = 0
|
||||
|
||||
@@ -203,5 +203,3 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -545,7 +545,7 @@
|
||||
if (!throw_item)
|
||||
return 0
|
||||
spawn(0)
|
||||
throw_item.throw_at(target, 16, shoot_speed)
|
||||
throw_item.throw_at(target, 16, 3, src)
|
||||
src.visible_message("\red <b>[src] launches [throw_item.name] at [target.name]!</b>")
|
||||
return 1
|
||||
|
||||
|
||||
@@ -475,7 +475,7 @@
|
||||
return
|
||||
else if(target!=locked)
|
||||
if(locked in view(chassis))
|
||||
locked.throw_at(target, 14, 1.5)
|
||||
locked.throw_at(target, 14, 1.5, chassis)
|
||||
locked = null
|
||||
send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
|
||||
set_ready_state(0)
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
var/obj/item/missile/M = new projectile(chassis.loc)
|
||||
M.primed = 1
|
||||
playsound(chassis, fire_sound, 50, 1)
|
||||
M.throw_at(target, missile_range, missile_speed)
|
||||
M.throw_at(target, missile_range, missile_speed, chassis)
|
||||
projectiles--
|
||||
log_message("Fired from [src.name], targeting [target].")
|
||||
do_after_cooldown()
|
||||
@@ -349,7 +349,7 @@
|
||||
set_ready_state(0)
|
||||
var/obj/item/weapon/grenade/flashbang/F = new projectile(chassis.loc)
|
||||
playsound(chassis, fire_sound, 50, 1)
|
||||
F.throw_at(target, missile_range, missile_speed)
|
||||
F.throw_at(target, missile_range, missile_speed, chassis)
|
||||
projectiles--
|
||||
log_message("Fired from [src.name], targeting [target].")
|
||||
spawn(det_time)
|
||||
@@ -391,7 +391,7 @@
|
||||
set_ready_state(0)
|
||||
var/obj/item/weapon/bananapeel/B = new projectile(chassis.loc)
|
||||
playsound(chassis, fire_sound, 60, 1)
|
||||
B.throw_at(target, missile_range, missile_speed)
|
||||
B.throw_at(target, missile_range, missile_speed, chassis)
|
||||
projectiles--
|
||||
log_message("Bananed from [src.name], targeting [target]. HONK!")
|
||||
do_after_cooldown()
|
||||
@@ -422,8 +422,8 @@
|
||||
var/obj/item/device/assembly/mousetrap/M = new projectile(chassis.loc)
|
||||
M.secured = 1
|
||||
playsound(chassis, fire_sound, 60, 1)
|
||||
M.throw_at(target, missile_range, missile_speed)
|
||||
M.throw_at(target, missile_range, missile_speed, chassis)
|
||||
projectiles--
|
||||
log_message("Launched a mouse-trap from [src.name], targeting [target]. HONK!")
|
||||
do_after_cooldown()
|
||||
return
|
||||
return
|
||||
|
||||
@@ -151,16 +151,19 @@
|
||||
C = usr.buckled
|
||||
var/obj/B = usr.buckled
|
||||
var/movementdirection = turn(direction,180)
|
||||
if(C) C.propelled = 1
|
||||
B.Move(get_step(usr,movementdirection), movementdirection)
|
||||
sleep(1)
|
||||
if(C) C.propelled = 4
|
||||
B.Move(get_step(usr,movementdirection), movementdirection)
|
||||
sleep(1)
|
||||
B.Move(get_step(usr,movementdirection), movementdirection)
|
||||
if(C) C.propelled = 3
|
||||
sleep(1)
|
||||
B.Move(get_step(usr,movementdirection), movementdirection)
|
||||
sleep(1)
|
||||
B.Move(get_step(usr,movementdirection), movementdirection)
|
||||
if(C) C.propelled = 2
|
||||
sleep(2)
|
||||
B.Move(get_step(usr,movementdirection), movementdirection)
|
||||
if(C) C.propelled = 1
|
||||
sleep(2)
|
||||
B.Move(get_step(usr,movementdirection), movementdirection)
|
||||
if(C) C.propelled = 0
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
if(propelled)
|
||||
var/mob/living/occupant = buckled_mob
|
||||
unbuckle()
|
||||
occupant.throw_at(A, 3, 2)
|
||||
occupant.throw_at(A, 3, propelled)
|
||||
occupant.apply_effect(6, STUN, 0)
|
||||
occupant.apply_effect(6, WEAKEN, 0)
|
||||
occupant.apply_effect(6, STUTTER, 0)
|
||||
|
||||
@@ -136,7 +136,12 @@
|
||||
if(propelled || (pulling && (pulling.a_intent == "harm")))
|
||||
var/mob/living/occupant = buckled_mob
|
||||
unbuckle()
|
||||
occupant.throw_at(A, 3, 2)
|
||||
|
||||
if (pulling && (pulling.a_intent == "hurt"))
|
||||
occupant.throw_at(A, 3, 3, pulling)
|
||||
else if (propelled)
|
||||
occupant.throw_at(A, 3, propelled)
|
||||
|
||||
occupant.apply_effect(6, STUN, 0)
|
||||
occupant.apply_effect(6, WEAKEN, 0)
|
||||
occupant.apply_effect(6, STUTTER, 0)
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/datum/playingcard
|
||||
var/name = "playing card"
|
||||
var/card_icon = "card_back"
|
||||
|
||||
/obj/item/weapon/deck
|
||||
name = "deck of cards"
|
||||
desc = "A simple deck of playing cards."
|
||||
icon = 'icons/obj/playing_cards.dmi'
|
||||
icon_state = "deck"
|
||||
w_class = 2
|
||||
|
||||
var/list/cards = list()
|
||||
|
||||
/obj/item/weapon/deck/New()
|
||||
..()
|
||||
|
||||
var/datum/playingcard/P
|
||||
for(var/suit in list("spades","clubs","diamonds","hearts"))
|
||||
|
||||
var/colour
|
||||
if(suit == "spades" || suit == "clubs")
|
||||
colour = "black_"
|
||||
else
|
||||
colour = "red_"
|
||||
|
||||
for(var/number in list("ace","two","three","four","five","six","seven","eight","nine","ten"))
|
||||
P = new()
|
||||
P.name = "[number] of [suit]"
|
||||
P.card_icon = "[colour]num"
|
||||
cards += P
|
||||
|
||||
for(var/number in list("jack","queen","king"))
|
||||
P = new()
|
||||
P.name = "[number] of [suit]"
|
||||
P.card_icon = "[colour]col"
|
||||
cards += P
|
||||
|
||||
|
||||
for(var/i = 0,i<2,i++)
|
||||
P = new()
|
||||
P.name = "joker"
|
||||
P.card_icon = "joker"
|
||||
cards += P
|
||||
|
||||
/obj/item/weapon/deck/attackby(obj/O as obj, mob/user as mob)
|
||||
if(istype(O,/obj/item/weapon/hand))
|
||||
var/obj/item/weapon/hand/H = O
|
||||
for(var/datum/playingcard/P in H.cards)
|
||||
cards += P
|
||||
del(O)
|
||||
user << "You place your cards on the bottom of the deck."
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/weapon/deck/verb/draw_card()
|
||||
|
||||
set category = "Object"
|
||||
set name = "Draw"
|
||||
set desc = "Draw a card from a deck."
|
||||
set src in oview(1)
|
||||
|
||||
if(usr.stat || !Adjacent(usr)) return
|
||||
|
||||
if(!istype(usr,/mob/living/carbon))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/user = usr
|
||||
|
||||
if(!cards.len)
|
||||
usr << "There are no cards in the deck."
|
||||
return
|
||||
|
||||
var/obj/item/weapon/hand/H
|
||||
if(user.l_hand && istype(user.l_hand,/obj/item/weapon/hand))
|
||||
H = user.l_hand
|
||||
else if(user.r_hand && istype(user.r_hand,/obj/item/weapon/hand))
|
||||
H = user.r_hand
|
||||
else
|
||||
H = new(get_turf(src))
|
||||
user.put_in_hands(H)
|
||||
|
||||
if(!H || !user) return
|
||||
|
||||
var/datum/playingcard/P = cards[1]
|
||||
H.cards += P
|
||||
cards -= P
|
||||
H.update_icon()
|
||||
user.visible_message("\The [user] draws a card.")
|
||||
user << "It's the [P]."
|
||||
|
||||
/obj/item/weapon/deck/verb/deal_card()
|
||||
|
||||
set category = "Object"
|
||||
set name = "Deal"
|
||||
set desc = "Deal a card from a deck."
|
||||
|
||||
if(usr.stat || !Adjacent(usr)) return
|
||||
|
||||
if(!cards.len)
|
||||
usr << "There are no cards in the deck."
|
||||
return
|
||||
|
||||
var/list/players = list()
|
||||
for(var/mob/living/player in orange(3))
|
||||
if(!player.stat)
|
||||
players += player
|
||||
players -= usr
|
||||
|
||||
var/mob/living/M = input("Who do you wish to deal a card?") as null|anything in players
|
||||
if(!usr || !src || !M) return
|
||||
|
||||
var/obj/item/weapon/hand/H = new(get_turf(src))
|
||||
|
||||
H.cards += cards[1]
|
||||
cards -= cards[1]
|
||||
H.concealed = 1
|
||||
H.update_icon()
|
||||
usr.visible_message("\The [usr] deals a card to \the [M].")
|
||||
H.throw_at(get_step(M,M.dir),10,1,H)
|
||||
|
||||
/obj/item/weapon/hand/attackby(obj/O as obj, mob/user as mob)
|
||||
if(istype(O,/obj/item/weapon/hand))
|
||||
var/obj/item/weapon/hand/H = O
|
||||
for(var/datum/playingcard/P in H.cards)
|
||||
cards += P
|
||||
del(O)
|
||||
user.put_in_hands(src)
|
||||
update_icon()
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/weapon/deck/attack_self(var/mob/user as mob)
|
||||
|
||||
var/list/newcards = list()
|
||||
while(cards.len)
|
||||
var/datum/playingcard/P = pick(cards)
|
||||
newcards += P
|
||||
cards -= P
|
||||
cards = newcards
|
||||
user.visible_message("\The [user] shuffles [src].")
|
||||
|
||||
/obj/item/weapon/hand
|
||||
name = "hand of cards"
|
||||
desc = "Some playing cards."
|
||||
icon = 'icons/obj/playing_cards.dmi'
|
||||
icon_state = "empty"
|
||||
w_class = 1
|
||||
|
||||
var/concealed = 0
|
||||
var/list/cards = list()
|
||||
|
||||
/obj/item/weapon/hand/verb/discard()
|
||||
|
||||
set category = "Object"
|
||||
set name = "Discard"
|
||||
set desc = "Place a card from your hand in front of you."
|
||||
|
||||
var/list/to_discard = list()
|
||||
for(var/datum/playingcard/P in cards)
|
||||
to_discard[P.name] = P
|
||||
var/discarding = input("Which card do you wish to put down?") as null|anything in to_discard
|
||||
|
||||
if(!discarding || !to_discard[discarding] || !usr || !src) return
|
||||
|
||||
var/datum/playingcard/card = to_discard[discarding]
|
||||
del(to_discard)
|
||||
|
||||
var/obj/item/weapon/hand/H = new(src.loc)
|
||||
H.cards += card
|
||||
cards -= card
|
||||
H.concealed = 0
|
||||
H.update_icon()
|
||||
usr.visible_message("\The [usr] plays \the [discarding].")
|
||||
H.loc = get_step(usr,usr.dir)
|
||||
|
||||
if(!cards.len)
|
||||
del(src)
|
||||
|
||||
/obj/item/weapon/hand/attack_self(var/mob/user as mob)
|
||||
concealed = !concealed
|
||||
update_icon()
|
||||
user.visible_message("\The [user] [concealed ? "conceals" : "reveals"] their hand.")
|
||||
|
||||
/obj/item/weapon/hand/examine()
|
||||
..()
|
||||
if((!concealed || src.loc == usr) && cards.len)
|
||||
usr << "It contains: "
|
||||
for(var/datum/playingcard/P in cards)
|
||||
usr << "The [P.name]."
|
||||
|
||||
/obj/item/weapon/hand/update_icon()
|
||||
|
||||
if(!cards.len)
|
||||
del(src)
|
||||
return
|
||||
else if(cards.len > 1)
|
||||
name = "hand of cards"
|
||||
desc = "Some playing cards."
|
||||
else
|
||||
name = "a playing card"
|
||||
desc = "A playing card."
|
||||
|
||||
overlays.Cut()
|
||||
|
||||
|
||||
if(cards.len == 1)
|
||||
var/datum/playingcard/P = cards[1]
|
||||
var/image/I = new(src.icon, (concealed ? "card_back" : "[P.card_icon]") )
|
||||
I.pixel_x += (-5+rand(10))
|
||||
I.pixel_y += (-5+rand(10))
|
||||
overlays += I
|
||||
return
|
||||
|
||||
var/origin = -12
|
||||
var/offset = Floor(32/cards.len)
|
||||
|
||||
var/i = 0
|
||||
for(var/datum/playingcard/P in cards)
|
||||
var/image/I = new(src.icon, (concealed ? "card_back" : "[P.card_icon]") )
|
||||
I.pixel_x = origin+(offset*i)
|
||||
overlays += I
|
||||
i++
|
||||
@@ -416,7 +416,7 @@
|
||||
*/
|
||||
|
||||
|
||||
item.throw_at(target, item.throw_range, item.throw_speed)
|
||||
item.throw_at(target, item.throw_range, item.throw_speed, src)
|
||||
|
||||
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
..()
|
||||
|
||||
@@ -1548,7 +1548,7 @@
|
||||
status_flags |= LEAPING
|
||||
|
||||
src.visible_message("<span class='warning'><b>\The [src]</b> leaps at [T]!</span>")
|
||||
src.throw_at(get_step(get_turf(T),get_turf(src)), 5, 1)
|
||||
src.throw_at(get_step(get_turf(T),get_turf(src)), 5, 1, src)
|
||||
playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1)
|
||||
|
||||
sleep(5)
|
||||
|
||||
@@ -72,7 +72,6 @@
|
||||
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5)//Standardization and logging -Sieve
|
||||
if(istype(AM,/obj/))
|
||||
var/obj/O = AM
|
||||
var/zone = ran_zone("chest",75)//Hits a random part of the body, geared towards the chest
|
||||
var/dtype = BRUTE
|
||||
if(istype(O,/obj/item/weapon))
|
||||
var/obj/item/weapon/W = O
|
||||
@@ -84,14 +83,25 @@
|
||||
|
||||
var/throw_damage = O.throwforce*(speed/5)
|
||||
|
||||
var/zone
|
||||
if (istype(O.thrower, /mob/living))
|
||||
var/mob/living/L = O.thrower
|
||||
zone = check_zone(L.zone_sel.selecting)
|
||||
else
|
||||
zone = ran_zone("chest",75) //Hits a random part of the body, geared towards the chest
|
||||
|
||||
//def_zone = get_zone_with_miss_chance(zone, src, 15*AM.throwing_dist_travelled)
|
||||
zone = get_zone_with_miss_chance(zone, src) //TODO: store the location of the thrower and adjust miss chance with distance
|
||||
if (O.throw_source)
|
||||
var/distance = get_dist(O.throw_source, loc)
|
||||
zone = get_zone_with_miss_chance(zone, src, min(15*(distance-2), 0))
|
||||
else
|
||||
zone = get_zone_with_miss_chance(zone, src, 15)
|
||||
|
||||
if(!zone)
|
||||
visible_message("\blue \The [AM] misses [src] narrowly!")
|
||||
visible_message("\blue \The [O] misses [src] narrowly!")
|
||||
return
|
||||
|
||||
AM.throwing = 0 //it hit, so stop moving
|
||||
O.throwing = 0 //it hit, so stop moving
|
||||
|
||||
if (istype(src, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = src
|
||||
@@ -148,7 +158,7 @@
|
||||
|
||||
//This is called when the mob is thrown into a dense turf
|
||||
/mob/living/proc/turf_collision(var/turf/T, var/speed)
|
||||
src.take_organ_damage(speed*4)
|
||||
src.take_organ_damage(speed*5)
|
||||
|
||||
/mob/living/proc/near_wall(var/direction,var/distance=1)
|
||||
var/turf/T = get_step(get_turf(src),direction)
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
|
||||
user.visible_message("\red [user] fires [src]!", "\red You fire [src]!")
|
||||
spike.loc = get_turf(src)
|
||||
spike.throw_at(target,10,fire_force)
|
||||
spike.throw_at(target,10,fire_force,user)
|
||||
spike = null
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
|
||||
var/obj/item/weapon/arrow/A = arrow
|
||||
A.loc = get_turf(user)
|
||||
A.throw_at(target,10,tension*release_speed)
|
||||
A.throw_at(target,10,tension*release_speed,user)
|
||||
arrow = null
|
||||
tension = 0
|
||||
icon_state = "crossbow"
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
user.visible_message("<span class='danger'>[user] fires [src] and launches [object] at [target]!</span>","<span class='danger'>You fire [src] and launch [object] at [target]!</span>")
|
||||
|
||||
src.remove_from_storage(object,user.loc)
|
||||
object.throw_at(target,10,speed)
|
||||
object.throw_at(target,10,speed,user)
|
||||
|
||||
var/lost_gas_amount = tank.air_contents.total_moles*(pressure_setting/100)
|
||||
var/datum/gas_mixture/removed = tank.air_contents.remove(lost_gas_amount)
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
var/obj/item/missile/M = new projectile(user.loc)
|
||||
playsound(user.loc, 'sound/effects/bang.ogg', 50, 1)
|
||||
M.primed = 1
|
||||
M.throw_at(target, missile_range, missile_speed)
|
||||
M.throw_at(target, missile_range, missile_speed,user)
|
||||
message_admins("[key_name_admin(user)] fired a rocket from a rocket launcher ([src.name]).")
|
||||
log_game("[key_name_admin(user)] used a rocket launcher ([src.name]).")
|
||||
rockets -= I
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
var/obj/item/weapon/grenade/chem_grenade/F = grenades[1] //Now with less copypasta!
|
||||
grenades -= F
|
||||
F.loc = user.loc
|
||||
F.throw_at(target, 30, 2)
|
||||
F.throw_at(target, 30, 2, user)
|
||||
message_admins("[key_name_admin(user)] fired a grenade ([F.name]) from a grenade launcher ([src.name]).")
|
||||
log_game("[key_name_admin(user)] used a grenade ([src.name]).")
|
||||
F.active = 1
|
||||
|
||||
Reference in New Issue
Block a user