mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-13 03:33:21 +00:00
- Laser cannons / Heavy laser cannons should now not be all mixed up.
- Fixed a bug where the station heads and security crew could be revolutionaries and cultists on game start.
- If you somehow drop the "Off Hand" that appears if you equip a fire axe, it will be deleted. No more silly "Off Hand" items lying around the station, yay!
- If you threw a fire axe when it was wielded, it would would stay wieled.
- Metroids should now, theoretically, not be able to phase through thin windows and glass doors. There's probably still going to be some Metroids phasing through thin glass doors if the right circumstances are met (BYOND pathfinding problem, will eventually migrate Metroid pathfinding to SS13's A* system.
- Fixed up some of Firecage's half-assed sprites. The decloner projectile in specific.
Misc:
- Portable turrets can now be equipped with EVERY (except the "plasma gun" because it's stupid anyway) energy gun possible. I want to see laser cannons turrets, emagged energy crossbow turrets, and shock revolver turrets, people!
- The decloner is no longer called "decloner" because that term really doesn't make any sense anyway. Does it imply that everyone in existence is actually a clone? While that does sound kind of cool, it's actually pretty stupid, so I changed the name but kept the path type "/obj/item/weapon/gun/energy/decloner".
git-svn-id: http://tgstation13.googlecode.com/svn/trunk@1936 316c924e-a436-60f5-8080-3fe189b3f50e
203 lines
5.8 KiB
Plaintext
203 lines
5.8 KiB
Plaintext
/mob/living/carbon/proc/toggle_throw_mode()
|
|
if (src.in_throw_mode)
|
|
throw_mode_off()
|
|
else
|
|
throw_mode_on()
|
|
|
|
/mob/living/carbon/proc/throw_mode_off()
|
|
src.in_throw_mode = 0
|
|
src.throw_icon.icon_state = "act_throw_off"
|
|
|
|
/mob/living/carbon/proc/throw_mode_on()
|
|
src.in_throw_mode = 1
|
|
src.throw_icon.icon_state = "act_throw_on"
|
|
|
|
/mob/living/carbon/proc/throw_item(atom/target)
|
|
src.throw_mode_off()
|
|
|
|
if(usr.stat)
|
|
return
|
|
if(target.type == /obj/screen) return
|
|
|
|
var/atom/movable/item = src.equipped()
|
|
|
|
if(!item) return
|
|
|
|
if(istype(item,/obj/item))
|
|
var/obj/item/IT = item
|
|
if(IT.twohanded)
|
|
if(IT.wielded)
|
|
if(hand)
|
|
var/obj/item/weapon/offhand/O = r_hand
|
|
del O
|
|
else
|
|
var/obj/item/weapon/offhand/O = l_hand
|
|
del O
|
|
|
|
IT.wielded = 0
|
|
IT.name = initial(IT.name)
|
|
|
|
|
|
u_equip(item)
|
|
if(src.client)
|
|
src.client.screen -= item
|
|
item.loc = src.loc
|
|
|
|
if (istype(item, /obj/item/weapon/grab))
|
|
item = item:throw() //throw the person instead of the grab
|
|
|
|
if(istype(item, /obj/item))
|
|
item:dropped(src) // let it know it's been dropped
|
|
|
|
//actually throw it!
|
|
if (item)
|
|
item.layer = initial(item.layer)
|
|
src.visible_message("\red [src] has thrown [item].")
|
|
|
|
if(istype(src.loc, /turf/space)) //they're in space, move em one space in the opposite direction
|
|
src.inertia_dir = get_dir(target, src)
|
|
step(src, inertia_dir)
|
|
item.throw_at(target, item.throw_range, item.throw_speed)
|
|
|
|
|
|
|
|
/proc/get_cardinal_step_away(atom/start, atom/finish) //returns the position of a step from start away from finish, in one of the cardinal directions
|
|
//returns only NORTH, SOUTH, EAST, or WEST
|
|
var/dx = finish.x - start.x
|
|
var/dy = finish.y - start.y
|
|
if(abs(dy) > abs (dx)) //slope is above 1:1 (move horizontally in a tie)
|
|
if(dy > 0)
|
|
return get_step(start, SOUTH)
|
|
else
|
|
return get_step(start, NORTH)
|
|
else
|
|
if(dx > 0)
|
|
return get_step(start, WEST)
|
|
else
|
|
return get_step(start, EAST)
|
|
|
|
/atom/movable/proc/hit_check()
|
|
if(src.throwing)
|
|
for(var/atom/A in get_turf(src))
|
|
if(A == src) continue
|
|
if(istype(A,/mob/living))
|
|
if(A:lying) continue
|
|
src.throw_impact(A)
|
|
src.throwing = 0
|
|
if(isobj(A))
|
|
if(A.density) // **TODO: Better behaviour for windows
|
|
// which are dense, but shouldn't always stop movement
|
|
src.throw_impact(A)
|
|
src.throwing = 0
|
|
|
|
/atom/proc/throw_impact(atom/hit_atom)
|
|
if(istype(hit_atom,/mob/living))
|
|
var/mob/living/M = hit_atom
|
|
M.visible_message("\red [hit_atom] has been hit by [src].")
|
|
if(src.vars.Find("throwforce"))
|
|
M.take_organ_damage(src:throwforce)
|
|
|
|
else if(isobj(hit_atom))
|
|
var/obj/O = hit_atom
|
|
if(!O.anchored)
|
|
step(O, src.dir)
|
|
O.hitby(src)
|
|
|
|
else if(isturf(hit_atom))
|
|
var/turf/T = hit_atom
|
|
if(T.density)
|
|
spawn(2)
|
|
step(src, turn(src.dir, 180))
|
|
if(istype(src,/mob/living))
|
|
var/mob/living/M = src
|
|
M.take_organ_damage(20)
|
|
|
|
/atom/movable/Bump(atom/O)
|
|
if(src.throwing)
|
|
src.throw_impact(O)
|
|
src.throwing = 0
|
|
..()
|
|
|
|
/atom/movable/proc/throw_at(atom/target, range, speed)
|
|
//use a modified version of Bresenham's algorithm to get from the atom's current position to that of the target
|
|
src.throwing = 1
|
|
|
|
var/dist_x = abs(target.x - src.x)
|
|
var/dist_y = abs(target.y - src.y)
|
|
|
|
var/dx
|
|
if (target.x > src.x)
|
|
dx = EAST
|
|
else
|
|
dx = WEST
|
|
|
|
var/dy
|
|
if (target.y > src.y)
|
|
dy = NORTH
|
|
else
|
|
dy = SOUTH
|
|
var/dist_travelled = 0
|
|
var/dist_since_sleep = 0
|
|
if(dist_x > dist_y)
|
|
var/error = dist_x/2 - dist_y
|
|
while (((((src.x < target.x && dx == EAST) || (src.x > target.x && dx == WEST)) && dist_travelled < range) || istype(src.loc, /turf/space)) && src.throwing && istype(src.loc, /turf))
|
|
// only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up
|
|
if(error < 0)
|
|
var/atom/step = get_step(src, dy)
|
|
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
|
|
break
|
|
src.Move(step)
|
|
hit_check()
|
|
error += dist_x
|
|
dist_travelled++
|
|
dist_since_sleep++
|
|
if(dist_since_sleep >= speed)
|
|
dist_since_sleep = 0
|
|
sleep(1)
|
|
else
|
|
var/atom/step = get_step(src, dx)
|
|
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
|
|
break
|
|
src.Move(step)
|
|
hit_check()
|
|
error -= dist_y
|
|
dist_travelled++
|
|
dist_since_sleep++
|
|
if(dist_since_sleep >= speed)
|
|
dist_since_sleep = 0
|
|
sleep(1)
|
|
else
|
|
var/error = dist_y/2 - dist_x
|
|
while (src &&((((src.y < target.y && dy == NORTH) || (src.y > target.y && dy == SOUTH)) && dist_travelled < range) || istype(src.loc, /turf/space)) && src.throwing && istype(src.loc, /turf))
|
|
// only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up
|
|
if(error < 0)
|
|
var/atom/step = get_step(src, dx)
|
|
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
|
|
break
|
|
src.Move(step)
|
|
hit_check()
|
|
error += dist_y
|
|
dist_travelled++
|
|
dist_since_sleep++
|
|
if(dist_since_sleep >= speed)
|
|
dist_since_sleep = 0
|
|
sleep(1)
|
|
else
|
|
var/atom/step = get_step(src, dy)
|
|
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
|
|
break
|
|
src.Move(step)
|
|
hit_check()
|
|
error -= dist_x
|
|
dist_travelled++
|
|
dist_since_sleep++
|
|
if(dist_since_sleep >= speed)
|
|
dist_since_sleep = 0
|
|
sleep(1)
|
|
|
|
//done throwing, either because it hit something or it finished moving
|
|
src.throwing = 0
|
|
if(isobj(src)) src:throw_impact(get_turf(src))
|
|
|
|
|