Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into upstream-merge-27503

This commit is contained in:
LetterJay
2017-05-24 08:11:07 -05:00
105 changed files with 2783 additions and 2423 deletions
File diff suppressed because it is too large Load Diff
+40 -18
View File
@@ -1142,6 +1142,10 @@
/obj/effect/turf_decal/bot{
dir = 2
},
/obj/structure/window/reinforced{
dir = 1;
layer = 2.9
},
/turf/open/floor/plasteel{
dir = 2
},
@@ -1338,6 +1342,13 @@
/obj/effect/turf_decal/bot{
dir = 2
},
/obj/structure/window/reinforced{
dir = 1;
layer = 2.9
},
/obj/structure/window/reinforced{
dir = 4
},
/turf/open/floor/plasteel{
dir = 2
},
@@ -1356,6 +1367,13 @@
/obj/effect/turf_decal/bot{
dir = 2
},
/obj/structure/window/reinforced{
dir = 1;
layer = 2.9
},
/obj/structure/window/reinforced{
dir = 8
},
/turf/open/floor/plasteel{
dir = 2
},
@@ -53772,6 +53790,10 @@
/obj/effect/turf_decal/bot{
dir = 2
},
/obj/structure/window/reinforced{
dir = 1;
layer = 2.9
},
/turf/open/floor/plasteel{
dir = 2
},
@@ -112232,11 +112254,11 @@ btp
cbv
ccq
bns
cjD
cjD
cjD
cjD
cnj
aof
aof
aof
aof
amw
aaa
aaa
aaa
@@ -112489,13 +112511,13 @@ ckS
bky
ccq
cds
cjD
aof
ckt
cly
cmw
cnj
cnj
cnj
amw
amw
amw
aaa
aaa
aaf
@@ -113003,13 +113025,13 @@ cbg
bTr
cct
cdu
cjG
aqx
cku
clz
cmx
cnj
cnj
cnj
amw
amw
amw
aaa
aaa
aaf
@@ -113260,11 +113282,11 @@ bky
bky
bky
bky
cjD
cjD
cjD
cjD
cnj
aof
aof
aof
aof
amw
aaa
aaa
aaa
+4 -4
View File
@@ -1,12 +1,12 @@
#define MC_TICK_CHECK ( ( world.tick_usage > GLOB.CURRENT_TICKLIMIT || src.state != SS_RUNNING ) ? pause() : 0 )
#define MC_TICK_CHECK ( ( world.tick_usage > Master.current_ticklimit || src.state != SS_RUNNING ) ? pause() : 0 )
#define MC_SPLIT_TICK_INIT(phase_count) var/original_tick_limit = GLOB.CURRENT_TICKLIMIT; var/split_tick_phases = ##phase_count
#define MC_SPLIT_TICK_INIT(phase_count) var/original_tick_limit = Master.current_ticklimit; var/split_tick_phases = ##phase_count
#define MC_SPLIT_TICK \
if(split_tick_phases > 1){\
GLOB.CURRENT_TICKLIMIT = ((original_tick_limit - world.tick_usage) / split_tick_phases) + world.tick_usage;\
Master.current_ticklimit = ((original_tick_limit - world.tick_usage) / split_tick_phases) + world.tick_usage;\
--split_tick_phases;\
} else {\
GLOB.CURRENT_TICKLIMIT = original_tick_limit;\
Master.current_ticklimit = original_tick_limit;\
}
// Used to smooth out costs to try and avoid oscillation.
+1 -1
View File
@@ -3,5 +3,5 @@
#define TICK_LIMIT_MC 70
#define TICK_LIMIT_MC_INIT_DEFAULT 98
#define TICK_CHECK ( world.tick_usage > GLOB.CURRENT_TICKLIMIT )
#define TICK_CHECK ( world.tick_usage > Master.current_ticklimit )
#define CHECK_TICK if TICK_CHECK stoplag()
+2 -3
View File
@@ -626,14 +626,13 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sortInstance, new())
var/val2 = fetchElement(L,cursor2)
while(1)
if(call(cmp)(val1,val2) < 0)
if(call(cmp)(val1,val2) <= 0)
if(++cursor1 >= end1)
break
val1 = fetchElement(L,cursor1)
else
moveElement(L,cursor2,cursor1)
++cursor2
if(++cursor2 >= end2)
break
++end1
@@ -653,4 +652,4 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sortInstance, new())
#undef MIN_GALLOP
#undef MIN_MERGE
#undef fetchElement
#undef fetchElement
+1 -1
View File
@@ -1215,7 +1215,7 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
. += round(i*DELTA_CALC)
sleep(i*world.tick_lag*DELTA_CALC)
i *= 2
while (world.tick_usage > min(TICK_LIMIT_TO_RUN, GLOB.CURRENT_TICKLIMIT))
while (world.tick_usage > min(TICK_LIMIT_TO_RUN, Master.current_ticklimit))
#undef DELTA_CALC
+1 -1
View File
@@ -14,7 +14,7 @@
selected_target[1] = null
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
if(selected_target[1] && over_object.IsAutoclickable())
if(selected_target[1] && over_object && over_object.IsAutoclickable())
selected_target[1] = over_object
selected_target[2] = params
+469 -467
View File
@@ -1,467 +1,469 @@
/*
Click code cleanup
~Sayu
*/
// 1 decisecond click delay (above and beyond mob/next_move)
//This is mainly modified by click code, to modify click delays elsewhere, use next_move and changeNext_move()
/mob/var/next_click = 0
// THESE DO NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
/mob/var/next_move_adjust = 0 //Amount to adjust action/click delays by, + or -
/mob/var/next_move_modifier = 1 //Value to multiply action/click delays by
//Delays the mob's next click/action by num deciseconds
// eg: 10-3 = 7 deciseconds of delay
// eg: 10*0.5 = 5 deciseconds of delay
// DOES NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
/mob/proc/changeNext_move(num)
next_move = world.time + ((num+next_move_adjust)*next_move_modifier)
/*
Before anything else, defer these calls to a per-mobtype handler. This allows us to
remove istype() spaghetti code, but requires the addition of other handler procs to simplify it.
Alternately, you could hardcode every mob's variation in a flat ClickOn() proc; however,
that's a lot of code duplication and is hard to maintain.
Note that this proc can be overridden, and is in the case of screen objects.
*/
/atom/Click(location,control,params)
if(initialized)
usr.ClickOn(src, params)
/atom/DblClick(location,control,params)
if(initialized)
usr.DblClickOn(src,params)
/atom/MouseWheel(delta_x,delta_y,location,control,params)
if(initialized)
usr.MouseWheelOn(src, delta_x, delta_y, params)
/*
Standard mob ClickOn()
Handles exceptions: Buildmode, middle click, modified clicks, mech actions
After that, mostly just check your state, check whether you're holding an item,
check whether you're adjacent to the target, then pass off the click to whoever
is recieving it.
The most common are:
* mob/UnarmedAttack(atom,adjacent) - used here only when adjacent, with no item in hand; in the case of humans, checks gloves
* atom/attackby(item,user) - used only when adjacent
* item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent
* mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed
*/
/mob/proc/ClickOn( atom/A, params )
if(world.time <= next_click)
return
next_click = world.time + 1
if(client && client.click_intercept)
if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["middle"])
ShiftMiddleClickOn(A)
return
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["middle"])
MiddleClickOn(A)
return
if(modifiers["shift"])
ShiftClickOn(A)
return
if(modifiers["alt"]) // alt and alt-gr (rightalt)
AltClickOn(A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
return
if(incapacitated(ignore_restraints = 1))
return
face_atom(A)
if(next_move > world.time) // in the year 2000...
return
if(A.IsObscured())
return
if(istype(loc,/obj/mecha))
var/obj/mecha/M = loc
return M.click_action(A,src,params)
if(restrained())
changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow
RestrainedClickOn(A)
return
if(in_throw_mode)
throw_item(A)
return
var/obj/item/W = get_active_held_item()
if(W == A)
W.attack_self(src)
update_inv_hands()
return
//These are always reachable.
//User itself, current loc, and user inventory
if(DirectAccess(A))
if(W)
melee_item_attack_chain(src,W,A,params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A)
return
//Can't reach anything else in lockers or other weirdness
if(!loc.AllowClick())
return
//Standard reach turf to turf or reaching inside storage
if(CanReach(A,W))
if(W)
melee_item_attack_chain(src,W,A,params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A,1)
else
if(W)
W.afterattack(A,src,0,params)
else
RangedAttack(A,params)
//Is the atom obscured by a PREVENT_CLICK_UNDER object above it
/atom/proc/IsObscured()
if(!isturf(loc)) //This only makes sense for things directly on turfs for now
return FALSE
var/turf/T = get_turf_pixel(src)
if(!T)
return FALSE
for(var/atom/movable/AM in T)
if(AM.flags & PREVENT_CLICK_UNDER && AM.density && AM.layer > layer)
return TRUE
return FALSE
/turf/IsObscured()
for(var/atom/movable/AM in src)
if(AM.flags & PREVENT_CLICK_UNDER && AM.density)
return TRUE
return FALSE
/atom/movable/proc/CanReach(atom/target,obj/item/tool,view_only = FALSE)
if(isturf(target) || isturf(target.loc) || DirectAccess(target)) //Directly accessible atoms
if(Adjacent(target) || (tool && CheckToolReach(src, target, tool.reach))) //Adjacent or reaching attacks
return TRUE
else
//Things inside storage insde another storage
//Eg Contents of a box in a backpack
var/atom/outer_storage = get_atom_on_turf(target)
if(outer_storage == target) //whatever that is we don't want infinite loop.
return FALSE
if(outer_storage && CanReach(outer_storage,tool) && outer_storage.CanReachStorage(target,src,view_only ? STORAGE_VIEW_DEPTH : INVENTORY_DEPTH))
return TRUE
return FALSE
//Can [target] in this container be reached by [user], can't be more than [depth] levels deep
/atom/proc/CanReachStorage(atom/target,user,depth)
return FALSE
/obj/item/weapon/storage/CanReachStorage(atom/target,user,depth)
while(target && depth > 0)
target = target.loc
depth--
if(target == src)
return TRUE
return FALSE
/atom/movable/proc/DirectAccess(atom/target)
if(target == src)
return TRUE
if(target == loc)
return TRUE
/mob/DirectAccess(atom/target)
if(..())
return TRUE
if(target in contents) //This could probably use moving down and restricting to inventory only
return TRUE
return FALSE
/mob/living/DirectAccess(atom/target)
if(..()) //Lightweight checks first
return TRUE
if(target in GetAllContents())
return TRUE
/atom/proc/AllowClick()
return FALSE
/turf/AllowClick()
return TRUE
/proc/CheckToolReach(atom/movable/here, atom/movable/there, reach)
if(!here || !there)
return
switch(reach)
if(0)
return FALSE
if(1)
return FALSE //here.Adjacent(there)
if(2 to INFINITY)
var/obj/dummy = new(get_turf(here))
dummy.pass_flags |= PASSTABLE
dummy.invisibility = INVISIBILITY_ABSTRACT
for(var/i in 1 to reach) //Limit it to that many tries
var/turf/T = get_step(dummy, get_dir(dummy, there))
if(dummy.CanReach(there))
qdel(dummy)
return TRUE
if(!dummy.Move(T)) //we're blocked!
qdel(dummy)
return
qdel(dummy)
// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click)
/mob/proc/DblClickOn(atom/A, params)
return
/*
Translates into attack_hand, etc.
Note: proximity_flag here is used to distinguish between normal usage (flag=1),
and usage when clicking on things telekinetically (flag=0). This proc will
not be called at ranged except with telekinesis.
proximity_flag is not currently passed to attack_hand, and is instead used
in human click code to allow glove touches only at melee range.
*/
/mob/proc/UnarmedAttack(atom/A, proximity_flag)
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
return
/*
Ranged unarmed attack:
This currently is just a default for all mobs, involving
laser eyes and telekinesis. You could easily add exceptions
for things like ranged glove touches, spitting alien acid/neurotoxin,
animals lunging, etc.
*/
/mob/proc/RangedAttack(atom/A, params)
/*
Restrained ClickOn
Used when you are handcuffed and click things.
Not currently used by anything but could easily be.
*/
/mob/proc/RestrainedClickOn(atom/A)
return
/*
Middle click
Only used for swapping hands
*/
/mob/proc/MiddleClickOn(atom/A)
return
/mob/living/carbon/MiddleClickOn(atom/A)
if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src))
next_click = world.time + 5
mind.changeling.chosen_sting.try_to_sting(src, A)
else
swap_hand()
/mob/living/simple_animal/drone/MiddleClickOn(atom/A)
swap_hand()
// In case of use break glass
/*
/atom/proc/MiddleClick(mob/M as mob)
return
*/
/*
Shift click
For most mobs, examine.
This is overridden in ai.dm
*/
/mob/proc/ShiftClickOn(atom/A)
A.ShiftClick(src)
return
/atom/proc/ShiftClick(mob/user)
if(user.client && user.client.eye == user || user.client.eye == user.loc)
user.examinate(src)
return
/*
Ctrl click
For most objects, pull
*/
/mob/proc/CtrlClickOn(atom/A)
A.CtrlClick(src)
return
/atom/proc/CtrlClick(mob/user)
var/mob/living/ML = user
if(istype(ML))
ML.pulled(src)
/mob/living/carbon/human/CtrlClick(mob/user)
if(ishuman(user) && Adjacent(user))
var/mob/living/carbon/human/H = user
H.dna.species.grab(H, src, H.martial_art)
H.next_click = world.time + CLICK_CD_MELEE
else
..()
/*
Alt click
Unused except for AI
*/
/mob/proc/AltClickOn(atom/A)
A.AltClick(src)
return
/mob/living/carbon/AltClickOn(atom/A)
if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src))
next_click = world.time + 5
mind.changeling.chosen_sting.try_to_sting(src, A)
else
..()
/atom/proc/AltClick(mob/user)
var/turf/T = get_turf(src)
if(T && user.TurfAdjacent(T))
if(user.listed_turf == T)
user.listed_turf = null
else
user.listed_turf = T
user.client.statpanel = T.name
return
/mob/proc/TurfAdjacent(turf/T)
return T.Adjacent(src)
/*
Control+Shift click
Unused except for AI
*/
/mob/proc/CtrlShiftClickOn(atom/A)
A.CtrlShiftClick(src)
return
/mob/proc/ShiftMiddleClickOn(atom/A)
src.pointed(A)
return
/atom/proc/CtrlShiftClick(mob/user)
return
/*
Misc helpers
Laser Eyes: as the name implies, handles this since nothing else does currently
face_atom: turns the mob towards what you clicked on
*/
/mob/proc/LaserEyes(atom/A)
return
/mob/living/LaserEyes(atom/A)
changeNext_move(CLICK_CD_RANGE)
var/turf/T = get_turf(src)
var/turf/U = get_turf(A)
var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam( loc )
LE.icon = 'icons/effects/genetics.dmi'
LE.icon_state = "eyelasers"
playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1)
LE.firer = src
LE.def_zone = get_organ_target()
LE.original = A
LE.current = T
LE.yo = U.y - T.y
LE.xo = U.x - T.x
LE.fire()
// Simple helper to face what you clicked on, in case it should be needed in more than one place
/mob/proc/face_atom(atom/A)
if( buckled || stat != CONSCIOUS || !A || !x || !y || !A.x || !A.y )
return
var/dx = A.x - x
var/dy = A.y - y
if(!dx && !dy) // Wall items are graphically shifted but on the floor
if(A.pixel_y > 16)
setDir(NORTH)
else if(A.pixel_y < -16)
setDir(SOUTH)
else if(A.pixel_x > 16)
setDir(EAST)
else if(A.pixel_x < -16)
setDir(WEST)
return
if(abs(dx) < abs(dy))
if(dy > 0)
setDir(NORTH)
else
setDir(SOUTH)
else
if(dx > 0)
setDir(EAST)
else
setDir(WEST)
/obj/screen/click_catcher
icon = 'icons/mob/screen_gen.dmi'
icon_state = "click_catcher"
plane = CLICKCATCHER_PLANE
mouse_opacity = 2
screen_loc = "CENTER"
/obj/screen/click_catcher/New()
..()
transform = matrix(200, 0, 0, 0, 200, 0)
/obj/screen/click_catcher/Click(location, control, params)
var/list/modifiers = params2list(params)
if(modifiers["middle"] && istype(usr, /mob/living/carbon))
var/mob/living/carbon/C = usr
C.swap_hand()
else
var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr))
if(T)
T.Click(location, control, params)
. = 1
/* MouseWheelOn */
/mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params)
return
/mob/dead/observer/MouseWheelOn(atom/A, delta_x, delta_y, params)
var/list/modifier = params2list(params)
if(modifier["shift"])
var/view = 0
if(delta_y > 0)
view = -1
else
view = 1
add_view_range(view)
/*
Click code cleanup
~Sayu
*/
// 1 decisecond click delay (above and beyond mob/next_move)
//This is mainly modified by click code, to modify click delays elsewhere, use next_move and changeNext_move()
/mob/var/next_click = 0
// THESE DO NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
/mob/var/next_move_adjust = 0 //Amount to adjust action/click delays by, + or -
/mob/var/next_move_modifier = 1 //Value to multiply action/click delays by
//Delays the mob's next click/action by num deciseconds
// eg: 10-3 = 7 deciseconds of delay
// eg: 10*0.5 = 5 deciseconds of delay
// DOES NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
/mob/proc/changeNext_move(num)
next_move = world.time + ((num+next_move_adjust)*next_move_modifier)
/*
Before anything else, defer these calls to a per-mobtype handler. This allows us to
remove istype() spaghetti code, but requires the addition of other handler procs to simplify it.
Alternately, you could hardcode every mob's variation in a flat ClickOn() proc; however,
that's a lot of code duplication and is hard to maintain.
Note that this proc can be overridden, and is in the case of screen objects.
*/
/atom/Click(location,control,params)
if(initialized)
usr.ClickOn(src, params)
/atom/DblClick(location,control,params)
if(initialized)
usr.DblClickOn(src,params)
/atom/MouseWheel(delta_x,delta_y,location,control,params)
if(initialized)
usr.MouseWheelOn(src, delta_x, delta_y, params)
/*
Standard mob ClickOn()
Handles exceptions: Buildmode, middle click, modified clicks, mech actions
After that, mostly just check your state, check whether you're holding an item,
check whether you're adjacent to the target, then pass off the click to whoever
is recieving it.
The most common are:
* mob/UnarmedAttack(atom,adjacent) - used here only when adjacent, with no item in hand; in the case of humans, checks gloves
* atom/attackby(item,user) - used only when adjacent
* item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent
* mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed
*/
/mob/proc/ClickOn( atom/A, params )
if(world.time <= next_click)
return
next_click = world.time + 1
if(client && client.click_intercept)
if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["middle"])
ShiftMiddleClickOn(A)
return
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["middle"])
MiddleClickOn(A)
return
if(modifiers["shift"])
ShiftClickOn(A)
return
if(modifiers["alt"]) // alt and alt-gr (rightalt)
AltClickOn(A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
return
if(incapacitated(ignore_restraints = 1))
return
face_atom(A)
if(next_move > world.time) // in the year 2000...
return
if(A.IsObscured())
return
if(istype(loc,/obj/mecha))
var/obj/mecha/M = loc
return M.click_action(A,src,params)
if(restrained())
changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow
RestrainedClickOn(A)
return
if(in_throw_mode)
throw_item(A)
return
var/obj/item/W = get_active_held_item()
if(W == A)
W.attack_self(src)
update_inv_hands()
return
//These are always reachable.
//User itself, current loc, and user inventory
if(DirectAccess(A))
if(W)
melee_item_attack_chain(src,W,A,params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A)
return
//Can't reach anything else in lockers or other weirdness
if(!loc.AllowClick())
return
//Standard reach turf to turf or reaching inside storage
if(CanReach(A,W))
if(W)
melee_item_attack_chain(src,W,A,params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A,1)
else
if(W)
W.afterattack(A,src,0,params)
else
RangedAttack(A,params)
//Is the atom obscured by a PREVENT_CLICK_UNDER object above it
/atom/proc/IsObscured()
if(!isturf(loc)) //This only makes sense for things directly on turfs for now
return FALSE
var/turf/T = get_turf_pixel(src)
if(!T)
return FALSE
for(var/atom/movable/AM in T)
if(AM.flags & PREVENT_CLICK_UNDER && AM.density && AM.layer > layer)
return TRUE
return FALSE
/turf/IsObscured()
for(var/atom/movable/AM in src)
if(AM.flags & PREVENT_CLICK_UNDER && AM.density)
return TRUE
return FALSE
/atom/movable/proc/CanReach(atom/target,obj/item/tool,view_only = FALSE)
if(isturf(target) || isturf(target.loc) || DirectAccess(target)) //Directly accessible atoms
if(Adjacent(target) || (tool && CheckToolReach(src, target, tool.reach))) //Adjacent or reaching attacks
return TRUE
else
//Things inside storage insde another storage
//Eg Contents of a box in a backpack
var/atom/outer_storage = get_atom_on_turf(target)
if(outer_storage == target) //whatever that is we don't want infinite loop.
return FALSE
if(outer_storage && CanReach(outer_storage,tool) && outer_storage.CanReachStorage(target,src,view_only ? STORAGE_VIEW_DEPTH : INVENTORY_DEPTH))
return TRUE
return FALSE
//Can [target] in this container be reached by [user], can't be more than [depth] levels deep
/atom/proc/CanReachStorage(atom/target,user,depth)
return FALSE
/obj/item/weapon/storage/CanReachStorage(atom/target,user,depth)
while(target && depth > 0)
target = target.loc
depth--
if(target == src)
return TRUE
return FALSE
/atom/movable/proc/DirectAccess(atom/target)
if(target == src)
return TRUE
if(target == loc)
return TRUE
/mob/DirectAccess(atom/target)
if(..())
return TRUE
if(target in contents) //This could probably use moving down and restricting to inventory only
return TRUE
return FALSE
/mob/living/DirectAccess(atom/target)
if(..()) //Lightweight checks first
return TRUE
if(target in GetAllContents())
return TRUE
/atom/proc/AllowClick()
return FALSE
/turf/AllowClick()
return TRUE
/proc/CheckToolReach(atom/movable/here, atom/movable/there, reach)
if(!here || !there)
return
switch(reach)
if(0)
return FALSE
if(1)
return FALSE //here.Adjacent(there)
if(2 to INFINITY)
var/obj/dummy = new(get_turf(here))
dummy.pass_flags |= PASSTABLE
dummy.invisibility = INVISIBILITY_ABSTRACT
for(var/i in 1 to reach) //Limit it to that many tries
var/turf/T = get_step(dummy, get_dir(dummy, there))
if(dummy.CanReach(there))
qdel(dummy)
return TRUE
if(!dummy.Move(T)) //we're blocked!
qdel(dummy)
return
qdel(dummy)
// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click)
/mob/proc/DblClickOn(atom/A, params)
return
/*
Translates into attack_hand, etc.
Note: proximity_flag here is used to distinguish between normal usage (flag=1),
and usage when clicking on things telekinetically (flag=0). This proc will
not be called at ranged except with telekinesis.
proximity_flag is not currently passed to attack_hand, and is instead used
in human click code to allow glove touches only at melee range.
*/
/mob/proc/UnarmedAttack(atom/A, proximity_flag)
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
return
/*
Ranged unarmed attack:
This currently is just a default for all mobs, involving
laser eyes and telekinesis. You could easily add exceptions
for things like ranged glove touches, spitting alien acid/neurotoxin,
animals lunging, etc.
*/
/mob/proc/RangedAttack(atom/A, params)
/*
Restrained ClickOn
Used when you are handcuffed and click things.
Not currently used by anything but could easily be.
*/
/mob/proc/RestrainedClickOn(atom/A)
return
/*
Middle click
Only used for swapping hands
*/
/mob/proc/MiddleClickOn(atom/A)
return
/mob/living/carbon/MiddleClickOn(atom/A)
if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src))
next_click = world.time + 5
mind.changeling.chosen_sting.try_to_sting(src, A)
else
swap_hand()
/mob/living/simple_animal/drone/MiddleClickOn(atom/A)
swap_hand()
// In case of use break glass
/*
/atom/proc/MiddleClick(mob/M as mob)
return
*/
/*
Shift click
For most mobs, examine.
This is overridden in ai.dm
*/
/mob/proc/ShiftClickOn(atom/A)
A.ShiftClick(src)
return
/atom/proc/ShiftClick(mob/user)
if(user.client && user.client.eye == user || user.client.eye == user.loc)
user.examinate(src)
return
/*
Ctrl click
For most objects, pull
*/
/mob/proc/CtrlClickOn(atom/A)
A.CtrlClick(src)
return
/atom/proc/CtrlClick(mob/user)
var/mob/living/ML = user
if(istype(ML))
ML.pulled(src)
/mob/living/carbon/human/CtrlClick(mob/user)
if(ishuman(user) && Adjacent(user))
if(world.time < user.next_move)
return FALSE
var/mob/living/carbon/human/H = user
H.dna.species.grab(H, src, H.mind.martial_art)
H.changeNext_move(CLICK_CD_MELEE)
else
..()
/*
Alt click
Unused except for AI
*/
/mob/proc/AltClickOn(atom/A)
A.AltClick(src)
return
/mob/living/carbon/AltClickOn(atom/A)
if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src))
next_click = world.time + 5
mind.changeling.chosen_sting.try_to_sting(src, A)
else
..()
/atom/proc/AltClick(mob/user)
var/turf/T = get_turf(src)
if(T && user.TurfAdjacent(T))
if(user.listed_turf == T)
user.listed_turf = null
else
user.listed_turf = T
user.client.statpanel = T.name
return
/mob/proc/TurfAdjacent(turf/T)
return T.Adjacent(src)
/*
Control+Shift click
Unused except for AI
*/
/mob/proc/CtrlShiftClickOn(atom/A)
A.CtrlShiftClick(src)
return
/mob/proc/ShiftMiddleClickOn(atom/A)
src.pointed(A)
return
/atom/proc/CtrlShiftClick(mob/user)
return
/*
Misc helpers
Laser Eyes: as the name implies, handles this since nothing else does currently
face_atom: turns the mob towards what you clicked on
*/
/mob/proc/LaserEyes(atom/A)
return
/mob/living/LaserEyes(atom/A)
changeNext_move(CLICK_CD_RANGE)
var/turf/T = get_turf(src)
var/turf/U = get_turf(A)
var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam( loc )
LE.icon = 'icons/effects/genetics.dmi'
LE.icon_state = "eyelasers"
playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1)
LE.firer = src
LE.def_zone = get_organ_target()
LE.original = A
LE.current = T
LE.yo = U.y - T.y
LE.xo = U.x - T.x
LE.fire()
// Simple helper to face what you clicked on, in case it should be needed in more than one place
/mob/proc/face_atom(atom/A)
if( buckled || stat != CONSCIOUS || !A || !x || !y || !A.x || !A.y )
return
var/dx = A.x - x
var/dy = A.y - y
if(!dx && !dy) // Wall items are graphically shifted but on the floor
if(A.pixel_y > 16)
setDir(NORTH)
else if(A.pixel_y < -16)
setDir(SOUTH)
else if(A.pixel_x > 16)
setDir(EAST)
else if(A.pixel_x < -16)
setDir(WEST)
return
if(abs(dx) < abs(dy))
if(dy > 0)
setDir(NORTH)
else
setDir(SOUTH)
else
if(dx > 0)
setDir(EAST)
else
setDir(WEST)
/obj/screen/click_catcher
icon = 'icons/mob/screen_gen.dmi'
icon_state = "click_catcher"
plane = CLICKCATCHER_PLANE
mouse_opacity = 2
screen_loc = "CENTER"
/obj/screen/click_catcher/New()
..()
transform = matrix(200, 0, 0, 0, 200, 0)
/obj/screen/click_catcher/Click(location, control, params)
var/list/modifiers = params2list(params)
if(modifiers["middle"] && istype(usr, /mob/living/carbon))
var/mob/living/carbon/C = usr
C.swap_hand()
else
var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr))
if(T)
T.Click(location, control, params)
. = 1
/* MouseWheelOn */
/mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params)
return
/mob/dead/observer/MouseWheelOn(atom/A, delta_x, delta_y, params)
var/list/modifier = params2list(params)
if(modifier["shift"])
var/view = 0
if(delta_y > 0)
view = -1
else
view = 1
add_view_range(view)
+23 -23
View File
@@ -14,15 +14,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
//Master -> SSPreInit -> GLOB -> world -> config -> SSInit -> Failsafe
//GOT IT MEMORIZED?
GLOBAL_VAR_INIT(MC_restart_clear, 0)
GLOBAL_VAR_INIT(MC_restart_timeout, 0)
GLOBAL_VAR_INIT(MC_restart_count, 0)
//current tick limit, assigned by the queue controller before running a subsystem.
//used by check_tick as well so that the procs subsystems call can obey that SS's tick limits
GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
/datum/controller/master
name = "Master"
@@ -59,6 +50,14 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
var/current_runlevel //for scheduling different subsystems for different stages of the round
var/static/restart_clear = 0
var/static/restart_timeout = 0
var/static/restart_count = 0
//current tick limit, assigned before running a subsystem.
//used by CHECK_TICK as well so that the procs subsystems call can obey that SS's tick limits
var/static/current_ticklimit = TICK_LIMIT_RUNNING
/datum/controller/master/New()
// Highlander-style: there can only be one! Kill off the old and replace it with the new.
subsystems = list()
@@ -90,14 +89,14 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
// -1 if we encountered a runtime trying to recreate it
/proc/Recreate_MC()
. = -1 //so if we runtime, things know we failed
if (world.time < GLOB.MC_restart_timeout)
if (world.time < Master.restart_timeout)
return 0
if (world.time < GLOB.MC_restart_clear)
GLOB.MC_restart_count *= 0.5
if (world.time < Master.restart_clear)
Master.restart_count *= 0.5
var/delay = 50 * ++GLOB.MC_restart_count
GLOB.MC_restart_timeout = world.time + delay
GLOB.MC_restart_clear = world.time + (delay * 2)
var/delay = 50 * ++Master.restart_count
Master.restart_timeout = world.time + delay
Master.restart_clear = world.time + (delay * 2)
Master.processing = 0 //stop ticking this one
try
new/datum/controller/master()
@@ -165,13 +164,13 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
var/start_timeofday = REALTIMEOFDAY
// Initialize subsystems.
GLOB.CURRENT_TICKLIMIT = config.tick_limit_mc_init
current_ticklimit = config.tick_limit_mc_init
for (var/datum/controller/subsystem/SS in subsystems)
if (SS.flags & SS_NO_INIT)
continue
SS.Initialize(REALTIMEOFDAY)
CHECK_TICK
GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
current_ticklimit = TICK_LIMIT_RUNNING
var/time = (REALTIMEOFDAY - start_timeofday) / 10
var/msg = "Initializations complete within [time] second[time == 1 ? "" : "s"]!"
@@ -206,6 +205,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
set waitfor = 0
if(delay)
sleep(delay)
testing("Master starting processing")
var/rtn = Loop()
if (rtn > 0 || processing < 0)
return //this was suppose to happen.
@@ -276,7 +276,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
while (1)
tickdrift = max(0, MC_AVERAGE_FAST(tickdrift, (((REALTIMEOFDAY - init_timeofday) - (world.time - init_time)) / world.tick_lag)))
if (processing <= 0)
GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
current_ticklimit = TICK_LIMIT_RUNNING
sleep(10)
continue
@@ -284,7 +284,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
// because sleeps are processed in the order received, so longer sleeps are more likely to run first
if (world.tick_usage > TICK_LIMIT_MC)
sleep_delta += 2
GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING * 0.5
current_ticklimit = TICK_LIMIT_RUNNING * 0.5
sleep(world.tick_lag * (processing + sleep_delta))
continue
@@ -322,7 +322,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
if (!error_level)
iteration++
error_level++
GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
current_ticklimit = TICK_LIMIT_RUNNING
sleep(10)
continue
@@ -334,7 +334,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
if (!error_level)
iteration++
error_level++
GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
current_ticklimit = TICK_LIMIT_RUNNING
sleep(10)
continue
error_level--
@@ -345,7 +345,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
iteration++
last_run = world.time
src.sleep_delta = MC_AVERAGE_FAST(src.sleep_delta, sleep_delta)
GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING - (TICK_LIMIT_RUNNING * 0.25) //reserve the tail 1/4 of the next tick for the mc.
current_ticklimit = TICK_LIMIT_RUNNING - (TICK_LIMIT_RUNNING * 0.25) //reserve the tail 1/4 of the next tick for the mc.
sleep(world.tick_lag * (processing + sleep_delta))
@@ -436,7 +436,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
tick_precentage = max(tick_precentage*0.5, tick_precentage-queue_node.tick_overrun)
GLOB.CURRENT_TICKLIMIT = round(world.tick_usage + tick_precentage)
current_ticklimit = round(world.tick_usage + tick_precentage)
if (!(queue_node_flags & SS_TICKER))
ran_non_ticker = TRUE
+1 -1
View File
@@ -150,7 +150,7 @@ SUBSYSTEM_DEF(atoms)
/datum/controller/subsystem/atoms/Shutdown()
var/initlog = InitLog()
if(initlog)
text2file("[GLOB.log_directory]/initialize.log", initlog)
text2file(initlog, "[GLOB.log_directory]/initialize.log")
#undef BAD_INIT_QDEL_BEFORE
#undef BAD_INIT_DIDNT_INIT
+2 -1
View File
@@ -1,7 +1,8 @@
SUBSYSTEM_DEF(blackbox)
name = "Blackbox"
wait = 6000
flags = SS_NO_TICK_CHECK
flags = SS_NO_TICK_CHECK | SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/msg_common = list()
var/list/msg_science = list()
-27
View File
@@ -1,27 +0,0 @@
SUBSYSTEM_DEF(fields)
name = "Fields"
wait = 2
priority = 40
flags = SS_KEEP_TIMING
var/list/datum/proximity_monitor/advanced/running = list()
var/list/datum/proximity_monitor/advanced/currentrun = list()
/datum/controller/subsystem/fields/fire(resumed = 0)
if(!resumed)
src.currentrun = running.Copy()
var/list/currentrun = src.currentrun
while(currentrun.len)
var/datum/proximity_monitor/advanced/F = currentrun[currentrun.len]
currentrun.len--
if(!F.requires_processing)
continue
F.process()
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/fields/proc/register_new_field(datum/proximity_monitor/advanced/F)
running += F
/datum/controller/subsystem/fields/proc/unregister_field(datum/proximity_monitor/advanced/F)
running -= F
+1 -1
View File
@@ -61,7 +61,7 @@ SUBSYSTEM_DEF(garbage)
for(var/path in sleptDestroy)
dellog += "Path : [path] \n"
dellog += "Sleeps : [sleptDestroy[path]] \n"
text2file("[GLOB.log_directory]/qdel.log", dellog.Join())
text2file(dellog.Join(), "[GLOB.log_directory]/qdel.log")
/datum/controller/subsystem/garbage/fire()
HandleToBeQueued()
@@ -0,0 +1,6 @@
PROCESSING_SUBSYSTEM_DEF(fields)
name = "Fields"
wait = 2
priority = 40
flags = SS_KEEP_TIMING | SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+6 -670
View File
@@ -79,681 +79,17 @@
/datum/martial_art/proc/teach(mob/living/carbon/human/H,make_temporary=0)
if(make_temporary)
temporary = 1
if(temporary && H.martial_art)
if(!H.martial_art.allow_temp_override)
if(temporary && H.mind.martial_art)
if(!H.mind.martial_art.allow_temp_override)
return
base = H.martial_art
base = H.mind.martial_art
if(help_verb)
H.verbs += help_verb
H.martial_art = src
H.mind.martial_art = src
/datum/martial_art/proc/remove(mob/living/carbon/human/H)
if(H.martial_art != src)
if(H.mind.martial_art != src)
return
H.martial_art = base
H.mind.martial_art = base
if(help_verb)
H.verbs -= help_verb
/datum/martial_art/boxing
name = "Boxing"
/datum/martial_art/boxing/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
to_chat(A, "<span class='warning'>Can't disarm while boxing!</span>")
return 1
/datum/martial_art/boxing/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
to_chat(A, "<span class='warning'>Can't grab while boxing!</span>")
return 1
/datum/martial_art/boxing/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
var/atk_verb = pick("left hook","right hook","straight punch")
var/damage = rand(5, 8) + A.dna.species.punchdamagelow
if(!damage)
playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
D.visible_message("<span class='warning'>[A] has attempted to [atk_verb] [D]!</span>", \
"<span class='userdanger'>[A] has attempted to [atk_verb] [D]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(A, D, "attempted to hit", atk_verb)
return 0
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
var/armor_block = D.run_armor_check(affecting, "melee")
playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1)
D.visible_message("<span class='danger'>[A] has [atk_verb]ed [D]!</span>", \
"<span class='userdanger'>[A] has [atk_verb]ed [D]!</span>", null, COMBAT_MESSAGE_RANGE)
D.apply_damage(damage, STAMINA, affecting, armor_block)
add_logs(A, D, "punched (boxing) ")
if(D.getStaminaLoss() > 50)
var/knockout_prob = D.getStaminaLoss() + rand(-15,15)
if((D.stat != DEAD) && prob(knockout_prob))
D.visible_message("<span class='danger'>[A] has knocked [D] out with a haymaker!</span>", \
"<span class='userdanger'>[A] has knocked [D] out with a haymaker!</span>")
D.apply_effect(10,WEAKEN,armor_block)
D.SetSleeping(5)
D.forcesay(GLOB.hit_appends)
add_logs(A, D, "knocked out (boxing) ")
else if(D.lying)
D.forcesay(GLOB.hit_appends)
return 1
/mob/living/carbon/human/proc/wrestling_help()
set name = "Recall Teachings"
set desc = "Remember how to wrestle."
set category = "Wrestling"
to_chat(usr, "<b><i>You flex your muscles and have a revelation...</i></b>")
to_chat(usr, "<span class='notice'>Clinch</span>: Grab. Passively gives you a chance to immediately aggressively grab someone. Not always successful.")
to_chat(usr, "<span class='notice'>Suplex</span>: Disarm someone you are grabbing. Suplexes your target to the floor. Greatly injures them and leaves both you and your target on the floor.")
to_chat(usr, "<span class='notice'>Advanced grab</span>: Grab. Passively causes stamina damage when grabbing someone.")
#define TORNADO_COMBO "HHD"
#define THROWBACK_COMBO "DHD"
#define PLASMA_COMBO "HDDDH"
/datum/martial_art/plasma_fist
name = "Plasma Fist"
help_verb = /mob/living/carbon/human/proc/plasma_fist_help
/datum/martial_art/plasma_fist/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,TORNADO_COMBO))
streak = ""
Tornado(A,D)
return 1
if(findtext(streak,THROWBACK_COMBO))
streak = ""
Throwback(A,D)
return 1
if(findtext(streak,PLASMA_COMBO))
streak = ""
Plasma(A,D)
return 1
return 0
/datum/martial_art/plasma_fist/proc/TornadoAnimate(mob/living/carbon/human/A)
set waitfor = FALSE
for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH))
if(!A)
break
A.setDir(i)
playsound(A.loc, 'sound/weapons/punch1.ogg', 15, 1, -1)
sleep(1)
/datum/martial_art/plasma_fist/proc/Tornado(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.say("TORNADO SWEEP!")
TornadoAnimate(A)
var/obj/effect/proc_holder/spell/aoe_turf/repulse/R = new(null)
var/list/turfs = list()
for(var/turf/T in range(1,A))
turfs.Add(T)
R.cast(turfs)
add_logs(A, D, "tornado sweeped(Plasma Fist)")
return
/datum/martial_art/plasma_fist/proc/Throwback(mob/living/carbon/human/A, mob/living/carbon/human/D)
D.visible_message("<span class='danger'>[A] has hit [D] with Plasma Punch!</span>", \
"<span class='userdanger'>[A] has hit [D] with Plasma Punch!</span>")
playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A)))
D.throw_at(throw_target, 200, 4,A)
A.say("HYAH!")
add_logs(A, D, "threw back (Plasma Fist)")
return
/datum/martial_art/plasma_fist/proc/Plasma(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
A.say("PLASMA FIST!")
D.visible_message("<span class='danger'>[A] has hit [D] with THE PLASMA FIST TECHNIQUE!</span>", \
"<span class='userdanger'>[A] has hit [D] with THE PLASMA FIST TECHNIQUE!</span>")
D.gib()
add_logs(A, D, "gibbed (Plasma Fist)")
return
/datum/martial_art/plasma_fist/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
if(check_streak(A,D))
return 1
basic_hit(A,D)
return 1
/datum/martial_art/plasma_fist/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("D",D)
if(check_streak(A,D))
return 1
basic_hit(A,D)
return 1
/datum/martial_art/plasma_fist/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("G",D)
if(check_streak(A,D))
return 1
basic_hit(A,D)
return 1
/mob/living/carbon/human/proc/plasma_fist_help()
set name = "Recall Teachings"
set desc = "Remember the martial techniques of the Plasma Fist."
set category = "Plasma Fist"
to_chat(usr, "<b><i>You clench your fists and have a flashback of knowledge...</i></b>")
to_chat(usr, "<span class='notice'>Tornado Sweep</span>: Harm Harm Disarm. Repulses target and everyone back.")
to_chat(usr, "<span class='notice'>Throwback</span>: Disarm Harm Disarm. Throws the target and an item at them.")
to_chat(usr, "<span class='notice'>The Plasma Fist</span>: Harm Disarm Disarm Disarm Harm. Knocks the brain out of the opponent and gibs their body.")
//Used by the gang of the same name. Uses combos. Basic attacks bypass armor and never miss
#define WRIST_WRENCH_COMBO "DD"
#define BACK_KICK_COMBO "HG"
#define STOMACH_KNEE_COMBO "GH"
#define HEAD_KICK_COMBO "DHH"
#define ELBOW_DROP_COMBO "HDHDH"
/datum/martial_art/the_sleeping_carp
name = "The Sleeping Carp"
deflection_chance = 100
no_guns = TRUE
allow_temp_override = FALSE
help_verb = /mob/living/carbon/human/proc/sleeping_carp_help
/datum/martial_art/the_sleeping_carp/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,WRIST_WRENCH_COMBO))
streak = ""
wristWrench(A,D)
return 1
if(findtext(streak,BACK_KICK_COMBO))
streak = ""
backKick(A,D)
return 1
if(findtext(streak,STOMACH_KNEE_COMBO))
streak = ""
kneeStomach(A,D)
return 1
if(findtext(streak,HEAD_KICK_COMBO))
streak = ""
headKick(A,D)
return 1
if(findtext(streak,ELBOW_DROP_COMBO))
streak = ""
elbowDrop(A,D)
return 1
return 0
/datum/martial_art/the_sleeping_carp/proc/wristWrench(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat && !D.stunned && !D.weakened)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
D.visible_message("<span class='warning'>[A] grabs [D]'s wrist and wrenches it sideways!</span>", \
"<span class='userdanger'>[A] grabs your wrist and violently wrenches it to the side!</span>")
playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
D.emote("scream")
D.drop_item()
D.apply_damage(5, BRUTE, pick("l_arm", "r_arm"))
D.Stun(3)
return 1
add_logs(A, D, "wrist wrenched (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/backKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(A.dir == D.dir && !D.stat && !D.weakened)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
D.visible_message("<span class='warning'>[A] kicks [D] in the back!</span>", \
"<span class='userdanger'>[A] kicks you in the back, making you stumble and fall!</span>")
step_to(D,get_step(D,D.dir),1)
D.Weaken(4)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
return 1
add_logs(A, D, "back-kicked (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/kneeStomach(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat && !D.weakened)
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
D.visible_message("<span class='warning'>[A] knees [D] in the stomach!</span>", \
"<span class='userdanger'>[A] winds you with a knee in the stomach!</span>")
D.audible_message("<b>[D]</b> gags!")
D.losebreath += 3
D.Stun(2)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
return 1
add_logs(A, D, "stomach kneed (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/headKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat && !D.weakened)
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
D.visible_message("<span class='warning'>[A] kicks [D] in the head!</span>", \
"<span class='userdanger'>[A] kicks you in the jaw!</span>")
D.apply_damage(20, BRUTE, "head")
D.drop_item()
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
D.Stun(4)
return 1
add_logs(A, D, "head kicked (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/elbowDrop(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(D.weakened || D.resting || D.stat)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
D.visible_message("<span class='warning'>[A] elbow drops [D]!</span>", \
"<span class='userdanger'>[A] piledrives you with their elbow!</span>")
if(D.stat)
D.death() //FINISH HIM!
D.apply_damage(50, BRUTE, "chest")
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 75, 1, -1)
return 1
add_logs(A, D, "elbow dropped (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("G",D)
if(check_streak(A,D))
return 1
if(A.grab_state >= GRAB_AGGRESSIVE)
D.grabbedby(A, 1)
else
A.start_pulling(D, 1)
if(A.pulling)
D.drop_all_held_items()
D.stop_pulling()
if(A.a_intent == INTENT_GRAB)
add_logs(A, D, "grabbed", addition="aggressively")
A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab
else
add_logs(A, D, "grabbed", addition="passively")
A.grab_state = GRAB_PASSIVE
return 1
/datum/martial_art/the_sleeping_carp/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
if(check_streak(A,D))
return 1
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
var/atk_verb = pick("punches", "kicks", "chops", "hits", "slams")
D.visible_message("<span class='danger'>[A] [atk_verb] [D]!</span>", \
"<span class='userdanger'>[A] [atk_verb] you!</span>")
D.apply_damage(rand(10,15), BRUTE)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, 1, -1)
if(prob(D.getBruteLoss()) && !D.lying)
D.visible_message("<span class='warning'>[D] stumbles and falls!</span>", "<span class='userdanger'>The blow sends you to the ground!</span>")
D.Weaken(4)
add_logs(A, D, "[atk_verb] (Sleeping Carp)")
return 1
/datum/martial_art/the_sleeping_carp/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("D",D)
if(check_streak(A,D))
return 1
return ..()
/mob/living/carbon/human/proc/sleeping_carp_help()
set name = "Recall Teachings"
set desc = "Remember the martial techniques of the Sleeping Carp clan."
set category = "Sleeping Carp"
to_chat(usr, "<b><i>You retreat inward and recall the teachings of the Sleeping Carp...</i></b>")
to_chat(usr, "<span class='notice'>Wrist Wrench</span>: Disarm Disarm. Forces opponent to drop item in hand.")
to_chat(usr, "<span class='notice'>Back Kick</span>: Harm Grab. Opponent must be facing away. Knocks down.")
to_chat(usr, "<span class='notice'>Stomach Knee</span>: Grab Harm. Knocks the wind out of opponent and stuns.")
to_chat(usr, "<span class='notice'>Head Kick</span>: Disarm Harm Harm. Decent damage, forces opponent to drop item in hand.")
to_chat(usr, "<span class='notice'>Elbow Drop</span>: Harm Disarm Harm Disarm Harm. Opponent must be on the ground. Deals huge damage, instantly kills anyone in critical condition.")
//CQC
#define SLAM_COMBO "GH"
#define KICK_COMBO "HH"
#define RESTRAIN_COMBO "GG"
#define PRESSURE_COMBO "DG"
#define CONSECUTIVE_COMBO "DDH"
/datum/martial_art/cqc
name = "CQC"
help_verb = /mob/living/carbon/human/proc/CQC_help
block_chance = 75
/datum/martial_art/cqc/proc/drop_restraining()
restraining = 0
/datum/martial_art/cqc/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,SLAM_COMBO))
streak = ""
Slam(A,D)
return 1
if(findtext(streak,KICK_COMBO))
streak = ""
Kick(A,D)
return 1
if(findtext(streak,RESTRAIN_COMBO))
streak = ""
Restrain(A,D)
return 1
if(findtext(streak,PRESSURE_COMBO))
streak = ""
Pressure(A,D)
return 1
if(findtext(streak,CONSECUTIVE_COMBO))
streak = ""
Consecutive(A,D)
return 0
/datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat || !D.weakened)
D.visible_message("<span class='warning'>[A] slams [D] into the ground!</span>", \
"<span class='userdanger'>[A] slams you into the ground!</span>")
playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1)
D.apply_damage(10, BRUTE)
D.Weaken(6)
add_logs(A, D, "cqc slammed")
return 1
/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat || !D.weakened)
D.visible_message("<span class='warning'>[A] kicks [D] back!</span>", \
"<span class='userdanger'>[A] kicks you back!</span>")
playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
var/atom/throw_target = get_edge_target_turf(D, A.dir)
D.throw_at(throw_target, 1, 14, A)
D.apply_damage(10, BRUTE)
add_logs(A, D, "cqc kicked")
if(D.weakened && !D.stat)
D.visible_message("<span class='warning'>[A] kicks [D]'s head, knocking them out!</span>", \
"<span class='userdanger'>[A] kicks your head, knocking you out!</span>")
playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1)
D.SetSleeping(15)
D.adjustBrainLoss(25)
return 1
/datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D)
D.visible_message("<span class='warning'>[A] forces their arm on [D]'s neck!</span>")
D.adjustStaminaLoss(60)
playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
return 1
/datum/martial_art/cqc/proc/Restrain(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(restraining)
return
if(!D.stat)
D.visible_message("<span class='warning'>[A] locks [D] into a restraining position!</span>", \
"<span class='userdanger'>[A] locks you into a restraining position!</span>")
D.adjustStaminaLoss(20)
D.Stun(5)
restraining = 1
addtimer(CALLBACK(src, .proc/drop_restraining), 50, TIMER_UNIQUE)
return 1
/datum/martial_art/cqc/proc/Consecutive(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat)
D.visible_message("<span class='warning'>[A] strikes [D]'s abdomen, neck and back consecutively</span>", \
"<span class='userdanger'>[A] strikes your abdomen, neck and back consecutively!</span>")
playsound(get_turf(D), 'sound/weapons/cqchit2.ogg', 50, 1, -1)
var/obj/item/I = D.get_active_held_item()
if(I && D.drop_item())
A.put_in_hands(I)
D.adjustStaminaLoss(50)
D.apply_damage(25, BRUTE)
return 1
/datum/martial_art/cqc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("G",D)
if(check_streak(A,D))
return 1
if(A.grab_state >= GRAB_AGGRESSIVE)
D.grabbedby(A, 1)
else
A.start_pulling(D, 1)
if(A.pulling)
D.stop_pulling()
add_logs(A, D, "grabbed", addition="aggressively")
A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab
return 1
/datum/martial_art/cqc/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
if(check_streak(A,D))
return 1
add_logs(A, D, "CQC'd")
A.do_attack_animation(D)
var/picked_hit_type = pick("CQC'd", "Big Bossed")
var/bonus_damage = 13
if(D.weakened || D.resting || D.lying)
bonus_damage += 5
picked_hit_type = "stomps on"
D.apply_damage(bonus_damage, BRUTE)
if(picked_hit_type == "kicks" || picked_hit_type == "stomps on")
playsound(get_turf(D), 'sound/weapons/cqchit2.ogg', 50, 1, -1)
else
playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
D.visible_message("<span class='danger'>[A] [picked_hit_type] [D]!</span>", \
"<span class='userdanger'>[A] [picked_hit_type] you!</span>")
add_logs(A, D, "[picked_hit_type] with CQC")
if(A.resting && !D.stat && !D.weakened)
D.visible_message("<span class='warning'>[A] leg sweeps [D]!", \
"<span class='userdanger'>[A] leg sweeps you!</span>")
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
D.apply_damage(10, BRUTE)
D.Weaken(3)
add_logs(A, D, "cqc sweeped")
return 1
/datum/martial_art/cqc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("D",D)
var/obj/item/I = null
if(check_streak(A,D))
return 1
if(prob(65))
if(!D.stat || !D.weakened || !restraining)
I = D.get_active_held_item()
D.visible_message("<span class='warning'>[A] strikes [D]'s jaw with their hand!</span>", \
"<span class='userdanger'>[A] strikes your jaw, disorienting you!</span>")
playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
if(I && D.drop_item())
A.put_in_hands(I)
D.Jitter(2)
D.apply_damage(5, BRUTE)
else
D.visible_message("<span class='danger'>[A] attempted to disarm [D]!</span>", \
"<span class='userdanger'>[A] attempted to disarm [D]!</span>")
playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
add_logs(A, D, "disarmed with CQC", "[I ? " grabbing \the [I]" : ""]")
if(restraining && A.pulling == D)
D.visible_message("<span class='danger'>[A] puts [D] into a chokehold!</span>", \
"<span class='userdanger'>[A] puts you into a chokehold!</span>")
D.SetSleeping(20)
restraining = 0
if(A.grab_state < GRAB_NECK)
A.grab_state = GRAB_NECK
else
restraining = 0
return 0
return 1
/mob/living/carbon/human/proc/CQC_help()
set name = "Remember The Basics"
set desc = "You try to remember some of the basics of CQC."
set category = "CQC"
to_chat(usr, "<b><i>You try to remember some of the basics of CQC.</i></b>")
to_chat(usr, "<span class='notice'>Slam</span>: Grab Harm. Slam opponent into the ground, weakens and knocks down.")
to_chat(usr, "<span class='notice'>CQC Kick</span>: Harm Disarm Harm. Knocks opponent away. Knocks out stunned or weakened opponents.")
to_chat(usr, "<span class='notice'>Restrain</span>: Grab Grab. Locks opponents into a restraining position, disarm to knock them out with a choke hold.")
to_chat(usr, "<span class='notice'>Pressure</span>: Disarm Grab. Decent stamina damage.")
to_chat(usr, "<span class='notice'>Consecutive CQC</span>: Disarm Disarm Harm. Mainly offensive move, huge damage and decent stamina damage.")
to_chat(usr, "<b><i>In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter attacks done to you.</i></b>")
//ITEMS
/obj/item/clothing/gloves/boxing
var/datum/martial_art/boxing/style = new
/obj/item/clothing/gloves/boxing/equipped(mob/user, slot)
if(!ishuman(user))
return
if(slot == slot_gloves)
var/mob/living/carbon/human/H = user
style.teach(H,1)
return
/obj/item/clothing/gloves/boxing/dropped(mob/user)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(H.get_item_by_slot(slot_gloves) == src)
style.remove(H)
return
/obj/item/weapon/storage/belt/champion/wrestling
name = "Wrestling Belt"
var/datum/martial_art/wrestling/style = new
/obj/item/weapon/storage/belt/champion/wrestling/equipped(mob/user, slot)
if(!ishuman(user))
return
if(slot == slot_belt)
var/mob/living/carbon/human/H = user
style.teach(H,1)
return
/obj/item/weapon/storage/belt/champion/wrestling/dropped(mob/user)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(H.get_item_by_slot(slot_belt) == src)
style.remove(H)
return
/obj/item/weapon/plasma_fist_scroll
name = "frayed scroll"
desc = "An aged and frayed scrap of paper written in shifting runes. There are hand-drawn illustrations of pugilism."
icon = 'icons/obj/wizard.dmi'
icon_state ="scroll2"
var/used = 0
/obj/item/weapon/plasma_fist_scroll/attack_self(mob/user)
if(!ishuman(user))
return
if(!used)
var/mob/living/carbon/human/H = user
var/datum/martial_art/plasma_fist/F = new/datum/martial_art/plasma_fist(null)
F.teach(H)
to_chat(H, "<span class='boldannounce'>You have learned the ancient martial art of Plasma Fist.</span>")
used = 1
desc = "It's completely blank."
name = "empty scroll"
icon_state = "blankscroll"
/obj/item/weapon/cqc_manual
name = "old manual"
desc = "A small, black manual. There are drawn instructions of tactical hand-to-hand combat."
icon = 'icons/obj/library.dmi'
icon_state ="cqcmanual"
/obj/item/weapon/cqc_manual/attack_self(mob/living/carbon/human/user)
if(!istype(user) || !user)
return
to_chat(user, "<span class='boldannounce'>You remember the basics of CQC.</span>")
var/datum/martial_art/cqc/D = new(null)
D.teach(user)
user.drop_item()
visible_message("<span class='warning'>[src] beeps ominously, and a moment later it bursts up in flames.</span>")
new /obj/effect/decal/cleanable/ash(get_turf(src))
qdel(src)
/obj/item/weapon/sleeping_carp_scroll
name = "mysterious scroll"
desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art."
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll2"
/obj/item/weapon/sleeping_carp_scroll/attack_self(mob/living/carbon/human/user)
if(!istype(user) || !user)
return
var/message = "<span class='sciradio'>You have learned the ancient martial art of the Sleeping Carp! Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles \
directed toward you. However, you are also unable to use any ranged weaponry. You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab.</span>"
to_chat(user, message)
var/datum/martial_art/the_sleeping_carp/theSleepingCarp = new(null)
theSleepingCarp.teach(user)
user.drop_item()
visible_message("<span class='warning'>[src] lights up in fire and quickly burns to ash.</span>")
new /obj/effect/decal/cleanable/ash(get_turf(src))
qdel(src)
/obj/item/weapon/twohanded/bostaff
name = "bo staff"
desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate."
force = 10
w_class = WEIGHT_CLASS_BULKY
slot_flags = SLOT_BACK
force_unwielded = 10
force_wielded = 24
throwforce = 20
throw_speed = 2
attack_verb = list("smashed", "slammed", "whacked", "thwacked")
icon = 'icons/obj/weapons.dmi'
icon_state = "bostaff0"
block_chance = 50
/obj/item/weapon/twohanded/bostaff/update_icon()
icon_state = "bostaff[wielded]"
return
/obj/item/weapon/twohanded/bostaff/attack(mob/target, mob/living/user)
add_fingerprint(user)
if((CLUMSY in user.disabilities) && prob(50))
to_chat(user, "<span class ='warning'>You club yourself over the head with [src].</span>")
user.Weaken(3)
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.apply_damage(2*force, BRUTE, "head")
else
user.take_bodypart_damage(2*force)
return
if(iscyborg(target))
return ..()
if(!isliving(target))
return ..()
var/mob/living/carbon/C = target
if(C.stat)
to_chat(user, "<span class='warning'>It would be dishonorable to attack a foe while they cannot retaliate.</span>")
return
if(user.a_intent == INTENT_DISARM)
if(!wielded)
return ..()
if(!ishuman(target))
return ..()
var/mob/living/carbon/human/H = target
var/list/fluffmessages = list("[user] clubs [H] with [src]!", \
"[user] smacks [H] with the butt of [src]!", \
"[user] broadsides [H] with [src]!", \
"[user] smashes [H]'s head with [src]!", \
"[user] beats [H] with front of [src]!", \
"[user] twirls and slams [H] with [src]!")
H.visible_message("<span class='warning'>[pick(fluffmessages)]</span>", \
"<span class='userdanger'>[pick(fluffmessages)]</span>")
playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, 1, -1)
H.adjustStaminaLoss(rand(13,20))
if(prob(10))
H.visible_message("<span class='warning'>[H] collapses!</span>", \
"<span class='userdanger'>Your legs give out!</span>")
H.Weaken(4)
if(H.staminaloss && !H.sleeping)
var/total_health = (H.health - H.staminaloss)
if(total_health <= HEALTH_THRESHOLD_CRIT && !H.stat)
H.visible_message("<span class='warning'>[user] delivers a heavy hit to [H]'s head, knocking them out cold!</span>", \
"<span class='userdanger'>[user] knocks you unconscious!</span>")
H.SetSleeping(30)
H.adjustBrainLoss(25)
else
return ..()
/obj/item/weapon/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance)
if(wielded)
return ..()
return 0
+67
View File
@@ -0,0 +1,67 @@
/datum/martial_art/boxing
name = "Boxing"
/datum/martial_art/boxing/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
to_chat(A, "<span class='warning'>Can't disarm while boxing!</span>")
return 1
/datum/martial_art/boxing/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
to_chat(A, "<span class='warning'>Can't grab while boxing!</span>")
return 1
/datum/martial_art/boxing/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
var/atk_verb = pick("left hook","right hook","straight punch")
var/damage = rand(5, 8) + A.dna.species.punchdamagelow
if(!damage)
playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
D.visible_message("<span class='warning'>[A] has attempted to [atk_verb] [D]!</span>", \
"<span class='userdanger'>[A] has attempted to [atk_verb] [D]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(A, D, "attempted to hit", atk_verb)
return 0
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
var/armor_block = D.run_armor_check(affecting, "melee")
playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1)
D.visible_message("<span class='danger'>[A] has [atk_verb]ed [D]!</span>", \
"<span class='userdanger'>[A] has [atk_verb]ed [D]!</span>", null, COMBAT_MESSAGE_RANGE)
D.apply_damage(damage, STAMINA, affecting, armor_block)
add_logs(A, D, "punched (boxing) ")
if(D.getStaminaLoss() > 50)
var/knockout_prob = D.getStaminaLoss() + rand(-15,15)
if((D.stat != DEAD) && prob(knockout_prob))
D.visible_message("<span class='danger'>[A] has knocked [D] out with a haymaker!</span>", \
"<span class='userdanger'>[A] has knocked [D] out with a haymaker!</span>")
D.apply_effect(10,WEAKEN,armor_block)
D.SetSleeping(5)
D.forcesay(GLOB.hit_appends)
add_logs(A, D, "knocked out (boxing) ")
else if(D.lying)
D.forcesay(GLOB.hit_appends)
return 1
/obj/item/clothing/gloves/boxing
var/datum/martial_art/boxing/style = new
/obj/item/clothing/gloves/boxing/equipped(mob/user, slot)
if(!ishuman(user))
return
if(slot == slot_gloves)
var/mob/living/carbon/human/H = user
style.teach(H,1)
return
/obj/item/clothing/gloves/boxing/dropped(mob/user)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(H.get_item_by_slot(slot_gloves) == src)
style.remove(H)
return
+199
View File
@@ -0,0 +1,199 @@
#define SLAM_COMBO "GH"
#define KICK_COMBO "HH"
#define RESTRAIN_COMBO "GG"
#define PRESSURE_COMBO "DG"
#define CONSECUTIVE_COMBO "DDH"
/datum/martial_art/cqc
name = "CQC"
help_verb = /mob/living/carbon/human/proc/CQC_help
block_chance = 75
/datum/martial_art/cqc/proc/drop_restraining()
restraining = 0
/datum/martial_art/cqc/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,SLAM_COMBO))
streak = ""
Slam(A,D)
return 1
if(findtext(streak,KICK_COMBO))
streak = ""
Kick(A,D)
return 1
if(findtext(streak,RESTRAIN_COMBO))
streak = ""
Restrain(A,D)
return 1
if(findtext(streak,PRESSURE_COMBO))
streak = ""
Pressure(A,D)
return 1
if(findtext(streak,CONSECUTIVE_COMBO))
streak = ""
Consecutive(A,D)
return 0
/datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat || !D.weakened)
D.visible_message("<span class='warning'>[A] slams [D] into the ground!</span>", \
"<span class='userdanger'>[A] slams you into the ground!</span>")
playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1)
D.apply_damage(10, BRUTE)
D.Weaken(6)
add_logs(A, D, "cqc slammed")
return 1
/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat || !D.weakened)
D.visible_message("<span class='warning'>[A] kicks [D] back!</span>", \
"<span class='userdanger'>[A] kicks you back!</span>")
playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
var/atom/throw_target = get_edge_target_turf(D, A.dir)
D.throw_at(throw_target, 1, 14, A)
D.apply_damage(10, BRUTE)
add_logs(A, D, "cqc kicked")
if(D.weakened && !D.stat)
D.visible_message("<span class='warning'>[A] kicks [D]'s head, knocking them out!</span>", \
"<span class='userdanger'>[A] kicks your head, knocking you out!</span>")
playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1)
D.SetSleeping(15)
D.adjustBrainLoss(25)
return 1
/datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D)
D.visible_message("<span class='warning'>[A] forces their arm on [D]'s neck!</span>")
D.adjustStaminaLoss(60)
playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
return 1
/datum/martial_art/cqc/proc/Restrain(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(restraining)
return
if(!D.stat)
D.visible_message("<span class='warning'>[A] locks [D] into a restraining position!</span>", \
"<span class='userdanger'>[A] locks you into a restraining position!</span>")
D.adjustStaminaLoss(20)
D.Stun(5)
restraining = 1
addtimer(CALLBACK(src, .proc/drop_restraining), 50, TIMER_UNIQUE)
return 1
/datum/martial_art/cqc/proc/Consecutive(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat)
D.visible_message("<span class='warning'>[A] strikes [D]'s abdomen, neck and back consecutively</span>", \
"<span class='userdanger'>[A] strikes your abdomen, neck and back consecutively!</span>")
playsound(get_turf(D), 'sound/weapons/cqchit2.ogg', 50, 1, -1)
var/obj/item/I = D.get_active_held_item()
if(I && D.drop_item())
A.put_in_hands(I)
D.adjustStaminaLoss(50)
D.apply_damage(25, BRUTE)
return 1
/datum/martial_art/cqc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("G",D)
if(check_streak(A,D))
return 1
if(A.grab_state >= GRAB_AGGRESSIVE)
D.grabbedby(A, 1)
else
A.start_pulling(D, 1)
if(A.pulling)
D.stop_pulling()
add_logs(A, D, "grabbed", addition="aggressively")
A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab
return 1
/datum/martial_art/cqc/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
if(check_streak(A,D))
return 1
add_logs(A, D, "CQC'd")
A.do_attack_animation(D)
var/picked_hit_type = pick("CQC'd", "Big Bossed")
var/bonus_damage = 13
if(D.weakened || D.resting || D.lying)
bonus_damage += 5
picked_hit_type = "stomps on"
D.apply_damage(bonus_damage, BRUTE)
if(picked_hit_type == "kicks" || picked_hit_type == "stomps on")
playsound(get_turf(D), 'sound/weapons/cqchit2.ogg', 50, 1, -1)
else
playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
D.visible_message("<span class='danger'>[A] [picked_hit_type] [D]!</span>", \
"<span class='userdanger'>[A] [picked_hit_type] you!</span>")
add_logs(A, D, "[picked_hit_type] with CQC")
if(A.resting && !D.stat && !D.weakened)
D.visible_message("<span class='warning'>[A] leg sweeps [D]!", \
"<span class='userdanger'>[A] leg sweeps you!</span>")
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
D.apply_damage(10, BRUTE)
D.Weaken(3)
add_logs(A, D, "cqc sweeped")
return 1
/datum/martial_art/cqc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("D",D)
var/obj/item/I = null
if(check_streak(A,D))
return 1
if(prob(65))
if(!D.stat || !D.weakened || !restraining)
I = D.get_active_held_item()
D.visible_message("<span class='warning'>[A] strikes [D]'s jaw with their hand!</span>", \
"<span class='userdanger'>[A] strikes your jaw, disorienting you!</span>")
playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
if(I && D.drop_item())
A.put_in_hands(I)
D.Jitter(2)
D.apply_damage(5, BRUTE)
else
D.visible_message("<span class='danger'>[A] attempted to disarm [D]!</span>", \
"<span class='userdanger'>[A] attempted to disarm [D]!</span>")
playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
add_logs(A, D, "disarmed with CQC", "[I ? " grabbing \the [I]" : ""]")
if(restraining && A.pulling == D)
D.visible_message("<span class='danger'>[A] puts [D] into a chokehold!</span>", \
"<span class='userdanger'>[A] puts you into a chokehold!</span>")
D.SetSleeping(20)
restraining = 0
if(A.grab_state < GRAB_NECK)
A.grab_state = GRAB_NECK
else
restraining = 0
return 0
return 1
/mob/living/carbon/human/proc/CQC_help()
set name = "Remember The Basics"
set desc = "You try to remember some of the basics of CQC."
set category = "CQC"
to_chat(usr, "<b><i>You try to remember some of the basics of CQC.</i></b>")
to_chat(usr, "<span class='notice'>Slam</span>: Grab Harm. Slam opponent into the ground, weakens and knocks down.")
to_chat(usr, "<span class='notice'>CQC Kick</span>: Harm Disarm Harm. Knocks opponent away. Knocks out stunned or weakened opponents.")
to_chat(usr, "<span class='notice'>Restrain</span>: Grab Grab. Locks opponents into a restraining position, disarm to knock them out with a choke hold.")
to_chat(usr, "<span class='notice'>Pressure</span>: Disarm Grab. Decent stamina damage.")
to_chat(usr, "<span class='notice'>Consecutive CQC</span>: Disarm Disarm Harm. Mainly offensive move, huge damage and decent stamina damage.")
to_chat(usr, "<b><i>In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter attacks done to you.</i></b>")
/obj/item/weapon/cqc_manual
name = "old manual"
desc = "A small, black manual. There are drawn instructions of tactical hand-to-hand combat."
icon = 'icons/obj/library.dmi'
icon_state ="cqcmanual"
/obj/item/weapon/cqc_manual/attack_self(mob/living/carbon/human/user)
if(!istype(user) || !user)
return
to_chat(user, "<span class='boldannounce'>You remember the basics of CQC.</span>")
var/datum/martial_art/cqc/D = new(null)
D.teach(user)
user.drop_item()
visible_message("<span class='warning'>[src] beeps ominously, and a moment later it bursts up in flames.</span>")
new /obj/effect/decal/cleanable/ash(get_turf(src))
qdel(src)
+9 -9
View File
@@ -13,12 +13,12 @@
to_chat(owner, "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>")
return
var/mob/living/carbon/human/H = owner
if (H.martial_art.streak == "neck_chop")
if (H.mind.martial_art.streak == "neck_chop")
owner.visible_message("<span class='danger'>[owner] assumes a neutral stance.</span>", "<b><i>Your next attack is cleared.</i></b>")
H.martial_art.streak = ""
H.mind.martial_art.streak = ""
else
owner.visible_message("<span class='danger'>[owner] assumes the Neck Chop stance!</span>", "<b><i>Your next attack will be a Neck Chop.</i></b>")
H.martial_art.streak = "neck_chop"
H.mind.martial_art.streak = "neck_chop"
/datum/action/leg_sweep
name = "Leg Sweep - Trips the victim, knocking them down for a brief moment."
@@ -29,12 +29,12 @@
to_chat(owner, "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>")
return
var/mob/living/carbon/human/H = owner
if (H.martial_art.streak == "leg_sweep")
if (H.mind.martial_art.streak == "leg_sweep")
owner.visible_message("<span class='danger'>[owner] assumes a neutral stance.</span>", "<b><i>Your next attack is cleared.</i></b>")
H.martial_art.streak = ""
H.mind.martial_art.streak = ""
else
owner.visible_message("<span class='danger'>[owner] assumes the Leg Sweep stance!</span>", "<b><i>Your next attack will be a Leg Sweep.</i></b>")
H.martial_art.streak = "leg_sweep"
H.mind.martial_art.streak = "leg_sweep"
/datum/action/lung_punch//referred to internally as 'quick choke'
name = "Lung Punch - Delivers a strong punch just above the victim's abdomen, constraining the lungs. The victim will be unable to breathe for a short time."
@@ -45,12 +45,12 @@
to_chat(owner, "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>")
return
var/mob/living/carbon/human/H = owner
if (H.martial_art.streak == "quick_choke")
if (H.mind.martial_art.streak == "quick_choke")
owner.visible_message("<span class='danger'>[owner] assumes a neutral stance.</span>", "<b><i>Your next attack is cleared.</i></b>")
H.martial_art.streak = ""
H.mind.martial_art.streak = ""
else
owner.visible_message("<span class='danger'>[owner] assumes the Lung Punch stance!</span>", "<b><i>Your next attack will be a Lung Punch.</i></b>")
H.martial_art.streak = "quick_choke"//internal name for lung punch
H.mind.martial_art.streak = "quick_choke"//internal name for lung punch
/datum/martial_art/krav_maga/teach(var/mob/living/carbon/human/H,var/make_temporary=0)
..()
+114
View File
@@ -0,0 +1,114 @@
#define TORNADO_COMBO "HHD"
#define THROWBACK_COMBO "DHD"
#define PLASMA_COMBO "HDDDH"
/datum/martial_art/plasma_fist
name = "Plasma Fist"
help_verb = /mob/living/carbon/human/proc/plasma_fist_help
/datum/martial_art/plasma_fist/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,TORNADO_COMBO))
streak = ""
Tornado(A,D)
return 1
if(findtext(streak,THROWBACK_COMBO))
streak = ""
Throwback(A,D)
return 1
if(findtext(streak,PLASMA_COMBO))
streak = ""
Plasma(A,D)
return 1
return 0
/datum/martial_art/plasma_fist/proc/TornadoAnimate(mob/living/carbon/human/A)
set waitfor = FALSE
for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH))
if(!A)
break
A.setDir(i)
playsound(A.loc, 'sound/weapons/punch1.ogg', 15, 1, -1)
sleep(1)
/datum/martial_art/plasma_fist/proc/Tornado(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.say("TORNADO SWEEP!")
TornadoAnimate(A)
var/obj/effect/proc_holder/spell/aoe_turf/repulse/R = new(null)
var/list/turfs = list()
for(var/turf/T in range(1,A))
turfs.Add(T)
R.cast(turfs)
add_logs(A, D, "tornado sweeped(Plasma Fist)")
return
/datum/martial_art/plasma_fist/proc/Throwback(mob/living/carbon/human/A, mob/living/carbon/human/D)
D.visible_message("<span class='danger'>[A] has hit [D] with Plasma Punch!</span>", \
"<span class='userdanger'>[A] has hit [D] with Plasma Punch!</span>")
playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A)))
D.throw_at(throw_target, 200, 4,A)
A.say("HYAH!")
add_logs(A, D, "threw back (Plasma Fist)")
return
/datum/martial_art/plasma_fist/proc/Plasma(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
A.say("PLASMA FIST!")
D.visible_message("<span class='danger'>[A] has hit [D] with THE PLASMA FIST TECHNIQUE!</span>", \
"<span class='userdanger'>[A] has hit [D] with THE PLASMA FIST TECHNIQUE!</span>")
D.gib()
add_logs(A, D, "gibbed (Plasma Fist)")
return
/datum/martial_art/plasma_fist/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
if(check_streak(A,D))
return 1
basic_hit(A,D)
return 1
/datum/martial_art/plasma_fist/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("D",D)
if(check_streak(A,D))
return 1
basic_hit(A,D)
return 1
/datum/martial_art/plasma_fist/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("G",D)
if(check_streak(A,D))
return 1
basic_hit(A,D)
return 1
/mob/living/carbon/human/proc/plasma_fist_help()
set name = "Recall Teachings"
set desc = "Remember the martial techniques of the Plasma Fist."
set category = "Plasma Fist"
to_chat(usr, "<b><i>You clench your fists and have a flashback of knowledge...</i></b>")
to_chat(usr, "<span class='notice'>Tornado Sweep</span>: Harm Harm Disarm. Repulses target and everyone back.")
to_chat(usr, "<span class='notice'>Throwback</span>: Disarm Harm Disarm. Throws the target and an item at them.")
to_chat(usr, "<span class='notice'>The Plasma Fist</span>: Harm Disarm Disarm Disarm Harm. Knocks the brain out of the opponent and gibs their body.")
/obj/item/weapon/plasma_fist_scroll
name = "frayed scroll"
desc = "An aged and frayed scrap of paper written in shifting runes. There are hand-drawn illustrations of pugilism."
icon = 'icons/obj/wizard.dmi'
icon_state ="scroll2"
var/used = 0
/obj/item/weapon/plasma_fist_scroll/attack_self(mob/user)
if(!ishuman(user))
return
if(!used)
var/mob/living/carbon/human/H = user
var/datum/martial_art/plasma_fist/F = new/datum/martial_art/plasma_fist(null)
F.teach(H)
to_chat(H, "<span class='boldannounce'>You have learned the ancient martial art of Plasma Fist.</span>")
used = 1
desc = "It's completely blank."
name = "empty scroll"
icon_state = "blankscroll"
+247
View File
@@ -0,0 +1,247 @@
#define WRIST_WRENCH_COMBO "DD"
#define BACK_KICK_COMBO "HG"
#define STOMACH_KNEE_COMBO "GH"
#define HEAD_KICK_COMBO "DHH"
#define ELBOW_DROP_COMBO "HDHDH"
/datum/martial_art/the_sleeping_carp
name = "The Sleeping Carp"
deflection_chance = 100
no_guns = TRUE
allow_temp_override = FALSE
help_verb = /mob/living/carbon/human/proc/sleeping_carp_help
/datum/martial_art/the_sleeping_carp/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,WRIST_WRENCH_COMBO))
streak = ""
wristWrench(A,D)
return 1
if(findtext(streak,BACK_KICK_COMBO))
streak = ""
backKick(A,D)
return 1
if(findtext(streak,STOMACH_KNEE_COMBO))
streak = ""
kneeStomach(A,D)
return 1
if(findtext(streak,HEAD_KICK_COMBO))
streak = ""
headKick(A,D)
return 1
if(findtext(streak,ELBOW_DROP_COMBO))
streak = ""
elbowDrop(A,D)
return 1
return 0
/datum/martial_art/the_sleeping_carp/proc/wristWrench(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat && !D.stunned && !D.weakened)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
D.visible_message("<span class='warning'>[A] grabs [D]'s wrist and wrenches it sideways!</span>", \
"<span class='userdanger'>[A] grabs your wrist and violently wrenches it to the side!</span>")
playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
D.emote("scream")
D.drop_item()
D.apply_damage(5, BRUTE, pick("l_arm", "r_arm"))
D.Stun(3)
return 1
add_logs(A, D, "wrist wrenched (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/backKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(A.dir == D.dir && !D.stat && !D.weakened)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
D.visible_message("<span class='warning'>[A] kicks [D] in the back!</span>", \
"<span class='userdanger'>[A] kicks you in the back, making you stumble and fall!</span>")
step_to(D,get_step(D,D.dir),1)
D.Weaken(4)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
return 1
add_logs(A, D, "back-kicked (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/kneeStomach(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat && !D.weakened)
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
D.visible_message("<span class='warning'>[A] knees [D] in the stomach!</span>", \
"<span class='userdanger'>[A] winds you with a knee in the stomach!</span>")
D.audible_message("<b>[D]</b> gags!")
D.losebreath += 3
D.Stun(2)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
return 1
add_logs(A, D, "stomach kneed (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/headKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat && !D.weakened)
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
D.visible_message("<span class='warning'>[A] kicks [D] in the head!</span>", \
"<span class='userdanger'>[A] kicks you in the jaw!</span>")
D.apply_damage(20, BRUTE, "head")
D.drop_item()
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
D.Stun(4)
return 1
add_logs(A, D, "head kicked (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/elbowDrop(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(D.weakened || D.resting || D.stat)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
D.visible_message("<span class='warning'>[A] elbow drops [D]!</span>", \
"<span class='userdanger'>[A] piledrives you with their elbow!</span>")
if(D.stat)
D.death() //FINISH HIM!
D.apply_damage(50, BRUTE, "chest")
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 75, 1, -1)
return 1
add_logs(A, D, "elbow dropped (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("G",D)
if(check_streak(A,D))
return 1
if(A.grab_state >= GRAB_AGGRESSIVE)
D.grabbedby(A, 1)
else
A.start_pulling(D, 1)
if(A.pulling)
D.drop_all_held_items()
D.stop_pulling()
if(A.a_intent == INTENT_GRAB)
add_logs(A, D, "grabbed", addition="aggressively")
A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab
else
add_logs(A, D, "grabbed", addition="passively")
A.grab_state = GRAB_PASSIVE
return 1
/datum/martial_art/the_sleeping_carp/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
if(check_streak(A,D))
return 1
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
var/atk_verb = pick("punches", "kicks", "chops", "hits", "slams")
D.visible_message("<span class='danger'>[A] [atk_verb] [D]!</span>", \
"<span class='userdanger'>[A] [atk_verb] you!</span>")
D.apply_damage(rand(10,15), BRUTE)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, 1, -1)
if(prob(D.getBruteLoss()) && !D.lying)
D.visible_message("<span class='warning'>[D] stumbles and falls!</span>", "<span class='userdanger'>The blow sends you to the ground!</span>")
D.Weaken(4)
add_logs(A, D, "[atk_verb] (Sleeping Carp)")
return 1
/datum/martial_art/the_sleeping_carp/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("D",D)
if(check_streak(A,D))
return 1
return ..()
/mob/living/carbon/human/proc/sleeping_carp_help()
set name = "Recall Teachings"
set desc = "Remember the martial techniques of the Sleeping Carp clan."
set category = "Sleeping Carp"
to_chat(usr, "<b><i>You retreat inward and recall the teachings of the Sleeping Carp...</i></b>")
to_chat(usr, "<span class='notice'>Wrist Wrench</span>: Disarm Disarm. Forces opponent to drop item in hand.")
to_chat(usr, "<span class='notice'>Back Kick</span>: Harm Grab. Opponent must be facing away. Knocks down.")
to_chat(usr, "<span class='notice'>Stomach Knee</span>: Grab Harm. Knocks the wind out of opponent and stuns.")
to_chat(usr, "<span class='notice'>Head Kick</span>: Disarm Harm Harm. Decent damage, forces opponent to drop item in hand.")
to_chat(usr, "<span class='notice'>Elbow Drop</span>: Harm Disarm Harm Disarm Harm. Opponent must be on the ground. Deals huge damage, instantly kills anyone in critical condition.")
/obj/item/weapon/sleeping_carp_scroll
name = "mysterious scroll"
desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art."
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll2"
/obj/item/weapon/sleeping_carp_scroll/attack_self(mob/living/carbon/human/user)
if(!istype(user) || !user)
return
var/message = "<span class='sciradio'>You have learned the ancient martial art of the Sleeping Carp! Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles \
directed toward you. However, you are also unable to use any ranged weaponry. You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab.</span>"
to_chat(user, message)
var/datum/martial_art/the_sleeping_carp/theSleepingCarp = new(null)
theSleepingCarp.teach(user)
user.drop_item()
visible_message("<span class='warning'>[src] lights up in fire and quickly burns to ash.</span>")
new /obj/effect/decal/cleanable/ash(get_turf(src))
qdel(src)
/obj/item/weapon/twohanded/bostaff
name = "bo staff"
desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate."
force = 10
w_class = WEIGHT_CLASS_BULKY
slot_flags = SLOT_BACK
force_unwielded = 10
force_wielded = 24
throwforce = 20
throw_speed = 2
attack_verb = list("smashed", "slammed", "whacked", "thwacked")
icon = 'icons/obj/weapons.dmi'
icon_state = "bostaff0"
block_chance = 50
/obj/item/weapon/twohanded/bostaff/update_icon()
icon_state = "bostaff[wielded]"
return
/obj/item/weapon/twohanded/bostaff/attack(mob/target, mob/living/user)
add_fingerprint(user)
if((CLUMSY in user.disabilities) && prob(50))
to_chat(user, "<span class ='warning'>You club yourself over the head with [src].</span>")
user.Weaken(3)
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.apply_damage(2*force, BRUTE, "head")
else
user.take_bodypart_damage(2*force)
return
if(iscyborg(target))
return ..()
if(!isliving(target))
return ..()
var/mob/living/carbon/C = target
if(C.stat)
to_chat(user, "<span class='warning'>It would be dishonorable to attack a foe while they cannot retaliate.</span>")
return
if(user.a_intent == INTENT_DISARM)
if(!wielded)
return ..()
if(!ishuman(target))
return ..()
var/mob/living/carbon/human/H = target
var/list/fluffmessages = list("[user] clubs [H] with [src]!", \
"[user] smacks [H] with the butt of [src]!", \
"[user] broadsides [H] with [src]!", \
"[user] smashes [H]'s head with [src]!", \
"[user] beats [H] with front of [src]!", \
"[user] twirls and slams [H] with [src]!")
H.visible_message("<span class='warning'>[pick(fluffmessages)]</span>", \
"<span class='userdanger'>[pick(fluffmessages)]</span>")
playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, 1, -1)
H.adjustStaminaLoss(rand(13,20))
if(prob(10))
H.visible_message("<span class='warning'>[H] collapses!</span>", \
"<span class='userdanger'>Your legs give out!</span>")
H.Weaken(4)
if(H.staminaloss && !H.sleeping)
var/total_health = (H.health - H.staminaloss)
if(total_health <= HEALTH_THRESHOLD_CRIT && !H.stat)
H.visible_message("<span class='warning'>[user] delivers a heavy hit to [H]'s head, knocking them out cold!</span>", \
"<span class='userdanger'>[user] knocks you unconscious!</span>")
H.SetSleeping(30)
H.adjustBrainLoss(25)
else
return ..()
/obj/item/weapon/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance)
if(wielded)
return ..()
return 0
+35 -5
View File
@@ -1,3 +1,13 @@
/mob/living/carbon/human/proc/wrestling_help()
set name = "Recall Teachings"
set desc = "Remember how to wrestle."
set category = "Wrestling"
to_chat(usr, "<b><i>You flex your muscles and have a revelation...</i></b>")
to_chat(usr, "<span class='notice'>Clinch</span>: Grab. Passively gives you a chance to immediately aggressively grab someone. Not always successful.")
to_chat(usr, "<span class='notice'>Suplex</span>: Disarm someone you are grabbing. Suplexes your target to the floor. Greatly injures them and leaves both you and your target on the floor.")
to_chat(usr, "<span class='notice'>Advanced grab</span>: Grab. Passively causes stamina damage when grabbing someone.")
/datum/martial_art/wrestling
name = "Wrestling"
var/datum/action/slam/slam = new/datum/action/slam()
@@ -40,7 +50,7 @@
return
owner.visible_message("<span class='danger'>[owner] prepares to BODY SLAM!</span>", "<b><i>Your next attack will be a BODY SLAM.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "slam"
H.mind.martial_art.streak = "slam"
/datum/action/throw_wrassle
name = "Throw (Cinch) - Spin a cinched opponent around and throw them."
@@ -52,7 +62,7 @@
return
owner.visible_message("<span class='danger'>[owner] prepares to THROW!</span>", "<b><i>Your next attack will be a THROW.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "throw"
H.mind.martial_art.streak = "throw"
/datum/action/kick
name = "Kick - A powerful kick, sends people flying away from you. Also useful for escaping from bad situations."
@@ -64,7 +74,7 @@
return
owner.visible_message("<span class='danger'>[owner] prepares to KICK!</span>", "<b><i>Your next attack will be a KICK.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "kick"
H.mind.martial_art.streak = "kick"
/datum/action/strike
name = "Strike - Hit a neaby opponent with a quick attack."
@@ -76,7 +86,7 @@
return
owner.visible_message("<span class='danger'>[owner] prepares to STRIKE!</span>", "<b><i>Your next attack will be a STRIKE.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "strike"
H.mind.martial_art.streak = "strike"
/datum/action/drop
name = "Drop - Smash down onto an opponent."
@@ -88,7 +98,7 @@
return
owner.visible_message("<span class='danger'>[owner] prepares to LEG DROP!</span>", "<b><i>Your next attack will be a LEG DROP.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "drop"
H.mind.martial_art.streak = "drop"
/datum/martial_art/wrestling/teach(var/mob/living/carbon/human/H,var/make_temporary=0)
..()
@@ -430,3 +440,23 @@
D.Stun(rand(3,5))
add_logs(A, D, "cinched")
return 1
/obj/item/weapon/storage/belt/champion/wrestling
name = "Wrestling Belt"
var/datum/martial_art/wrestling/style = new
/obj/item/weapon/storage/belt/champion/wrestling/equipped(mob/user, slot)
if(!ishuman(user))
return
if(slot == slot_belt)
var/mob/living/carbon/human/H = user
style.teach(H,1)
return
/obj/item/weapon/storage/belt/champion/wrestling/dropped(mob/user)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(H.get_item_by_slot(slot_belt) == src)
style.remove(H)
return
+2 -1
View File
@@ -50,7 +50,8 @@
var/datum/faction/faction //associated faction
var/datum/changeling/changeling //changeling holder
var/linglink
var/datum/martial_art/martial_art = null
var/static/default_martial_art = new/datum/martial_art
var/miming = 0 // Mime's vow of silence
var/list/antag_datums
var/antag_hud_icon_state = null //this mind's ANTAG_HUD should have this icon_state
+2 -2
View File
@@ -375,8 +375,8 @@
desc = "Used by veteran cultists to instantly transport items to their needful bretheren."
w_class = WEIGHT_CLASS_SMALL
brightness_on = 1
icon_state = "torch-on"
item_state = "torch-on"
icon_state = "torch"
item_state = "torch"
color = "#ff0000"
on_damage = 15
slot_flags = null
+1
View File
@@ -332,3 +332,4 @@ GLOBAL_LIST_INIT(gang_outfit_pool, list(/obj/item/clothing/suit/jacket/leather,/
SSticker.station_explosion_cinematic(1,"gang war", null)
SSticker.mode.explosion_in_progress = 0
SSticker.force_ending = TRUE
+23 -7
View File
@@ -28,6 +28,7 @@
var/static/list/boss_items = list(
/datum/gang_item/function/gang_ping,
/datum/gang_item/function/recall,
/datum/gang_item/clothing/under,
/datum/gang_item/clothing/suit,
/datum/gang_item/clothing/hat,
@@ -36,21 +37,29 @@
/datum/gang_item/clothing/mask,
/datum/gang_item/clothing/hands,
/datum/gang_item/clothing/belt,
/datum/gang_item/weapon/shuriken,
/datum/gang_item/weapon/switchblade,
/datum/gang_item/weapon/improvised,
/datum/gang_item/weapon/ammo/improvised_ammo,
/datum/gang_item/weapon/surplus,
/datum/gang_item/weapon/ammo/surplus_ammo,
/datum/gang_item/weapon/pistol,
/datum/gang_item/weapon/ammo/pistol_ammo,
/datum/gang_item/weapon/sniper,
/datum/gang_item/weapon/ammo/sniper_ammo,
/datum/gang_item/weapon/machinegun,
/datum/gang_item/weapon/uzi,
/datum/gang_item/weapon/ammo/uzi_ammo,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/spraycan,
/datum/gang_item/equipment/c4,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/emp,
/datum/gang_item/equipment/c4,
/datum/gang_item/equipment/frag,
/datum/gang_item/equipment/implant_breaker,
/datum/gang_item/equipment/stimpack,
/datum/gang_item/equipment/implant_breaker,
/datum/gang_item/equipment/wetwork_boots,
/datum/gang_item/equipment/pen,
/datum/gang_item/equipment/dominator
)
@@ -66,21 +75,29 @@
/datum/gang_item/clothing/mask,
/datum/gang_item/clothing/hands,
/datum/gang_item/clothing/belt,
/datum/gang_item/weapon/shuriken,
/datum/gang_item/weapon/shuriken,
/datum/gang_item/weapon/switchblade,
/datum/gang_item/weapon/improvised,
/datum/gang_item/weapon/ammo/improvised_ammo,
/datum/gang_item/weapon/surplus,
/datum/gang_item/weapon/ammo/surplus_ammo,
/datum/gang_item/weapon/pistol,
/datum/gang_item/weapon/ammo/pistol_ammo,
/datum/gang_item/weapon/sniper,
/datum/gang_item/weapon/ammo/sniper_ammo,
/datum/gang_item/weapon/machinegun,
/datum/gang_item/weapon/uzi,
/datum/gang_item/weapon/ammo/uzi_ammo,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/spraycan,
/datum/gang_item/equipment/c4,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/emp,
/datum/gang_item/equipment/c4,
/datum/gang_item/equipment/frag,
/datum/gang_item/equipment/implant_breaker,
/datum/gang_item/equipment/stimpack,
/datum/gang_item/equipment/implant_breaker,
/datum/gang_item/equipment/wetwork_boots,
)
/datum/gang/New(loc,gangname)
@@ -165,7 +182,6 @@
var/diff = domination_timer - world.time
return diff / 10
//////////////////////////////////////////// MESSAGING
@@ -283,4 +299,4 @@
ganghud = new()
/datum/gang/multiverse/income()
return
return
+48 -7
View File
@@ -199,10 +199,34 @@
cost = 5
item_path = /obj/item/weapon/switchblade
/datum/gang_item/weapon/surplus
name = "Surplus Rifle"
id = "surplus"
cost = 8
item_path = /obj/item/weapon/gun/ballistic/automatic/surplus
/datum/gang_item/weapon/ammo/surplus_ammo
name = "Surplus Rifle Ammo"
id = "surplus_ammo"
cost = 5
item_path = /obj/item/ammo_box/magazine/m10mm/rifle
/datum/gang_item/weapon/improvised
name = "Sawn-Off Improvised Shotgun"
id = "sawn"
cost = 6
item_path = /obj/item/weapon/gun/ballistic/revolver/doublebarrel/improvised/sawn
/datum/gang_item/weapon/ammo/improvised_ammo
name = "Box of Buckshot"
id = "buckshot"
cost = 5
item_path = /obj/item/weapon/storage/box/lethalshot
/datum/gang_item/weapon/pistol
name = "10mm Pistol"
id = "pistol"
cost = 25
cost = 30
item_path = /obj/item/weapon/gun/ballistic/automatic/pistol
/datum/gang_item/weapon/ammo/pistol_ammo
@@ -223,12 +247,19 @@
cost = 15
item_path = /obj/item/ammo_box/magazine/sniper_rounds
/datum/gang_item/weapon/machinegun
name = "Mounted Machine Gun"
id = "MG"
cost = 50
item_path = /obj/machinery/manned_turret
spawn_msg = "<span class='notice'>The mounted machine gun features enhanced responsiveness. Hold down on the trigger while firing to control where you're shooting.</span>"
/datum/gang_item/weapon/uzi
name = "Uzi SMG"
id = "uzi"
cost = 60
item_path = /obj/item/weapon/gun/ballistic/automatic/mini_uzi
id = "uzi"
/datum/gang_item/weapon/ammo/uzi_ammo
name = "Uzi Ammo"
@@ -236,8 +267,6 @@
cost = 40
item_path = /obj/item/ammo_box/magazine/uzim9mm
///////////////////
//EQUIPMENT
///////////////////
@@ -274,13 +303,13 @@
/datum/gang_item/equipment/frag
name = "Fragmentation Grenade"
id = "frag nade"
cost = 10
cost = 18
item_path = /obj/item/weapon/grenade/syndieminibomb/concussion/frag
/datum/gang_item/equipment/stimpack
name = "Black Market Stimulants"
id = "stimpack"
cost = 15
cost = 12
item_path = /obj/item/weapon/reagent_containers/syringe/stimulants
/datum/gang_item/equipment/implant_breaker
@@ -297,6 +326,18 @@
if(spawn_msg)
to_chat(user, spawn_msg)
/datum/gang_item/equipment/wetwork_boots
name = "Wetwork boots"
id = "wetwork"
cost = 20
item_path = /obj/item/clothing/shoes/combat/gang
/obj/item/clothing/shoes/combat/gang
name = "Wetwork boots"
desc = "A gang's best hitmen are prepared for anything."
permeability_coefficient = 0.01
flags = NOSLIP
/datum/gang_item/equipment/pen
name = "Recruitment Pen"
id = "pen"
@@ -390,4 +431,4 @@
return ..()
/datum/gang_item/equipment/dominator/spawn_item(mob/living/carbon/user, datum/gang/gang, obj/item/device/gangtool/gangtool)
new item_path(user.loc)
new item_path(user.loc)
+1 -1
View File
@@ -66,4 +66,4 @@
cooldown = 0
icon_state = "pen"
var/mob/M = get(src, /mob)
to_chat(M, "<span class='notice'>\icon[src] [src][(src.loc == M)?(""):(" in your [src.loc]")] vibrates softly. It is ready to be used again.</span>")
to_chat(M, "<span class='notice'>\icon[src] [src][(src.loc == M)?(""):(" in your [src.loc]")] vibrates softly. It is ready to be used again.</span>")
+1
View File
@@ -240,6 +240,7 @@
/obj/item/device/gangtool/spare/lt
promotable = 1
///////////// Internal tool used by gang regulars ///////////
/obj/item/device/gangtool/soldier
@@ -35,7 +35,12 @@
var/morphed = 0
var/atom/movable/form = null
var/morph_time = 0
var/static/list/blacklist_typecache = typecacheof(list(
/obj/screen,
/obj/singularity,
/mob/living/simple_animal/hostile/morph,
/obj/effect))
var/playstyle_string = "<b><font size=3 color='red'>You are a morph,</font> an abomination of science created primarily with changeling cells. \
You may take the form of anything nearby by shift-clicking it. This process will alert any nearby \
observers, and can only be performed once every five seconds. While morphed, you move faster, but do \
@@ -67,13 +72,7 @@
..()
/mob/living/simple_animal/hostile/morph/proc/allowed(atom/movable/A) // make it into property/proc ? not sure if worth it
if(istype(A,/obj/screen))
return 0
if(istype(A,/obj/singularity))
return 0
if(istype(A,/mob/living/simple_animal/hostile/morph))
return 0
return 1
return !is_type_in_typecache(A, blacklist_typecache)
/mob/living/simple_animal/hostile/morph/proc/eat(atom/movable/A)
if(A && A.loc != src)
@@ -100,6 +99,7 @@
visible_message("<span class='warning'>[src] suddenly twists and changes shape, becoming a copy of [target]!</span>", \
"<span class='notice'>You twist your body and assume the form of [target].</span>")
appearance = target.appearance
copy_overlays(target)
alpha = max(alpha, 150) //fucking chameleons
transform = initial(transform)
pixel_y = initial(pixel_y)
@@ -1,9 +1,9 @@
#define TURRET_STUN 0
#define TURRET_LETHAL 1
#define POPUP_ANIM_TIME 5
#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad
#define POPUP_ANIM_TIME 5
#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad
/obj/machinery/porta_turret
name = "turret"
icon = 'icons/obj/turrets.dmi'
@@ -87,9 +87,9 @@
if(has_cover)
cover = new /obj/machinery/porta_turret_cover(loc)
cover.parent_turret = src
underlays += image('icons/obj/turrets.dmi',icon_state = "basedark")
underlays += image('icons/obj/turrets.dmi',icon_state = "basedark")
if(!has_cover)
INVOKE_ASYNC(src, .proc/popUp)
INVOKE_ASYNC(src, .proc/popUp)
/obj/machinery/porta_turret/update_icon()
cut_overlays()
@@ -368,10 +368,10 @@
var/list/targets = list()
var/turretview = view(scan_range, base)
for(var/A in turretview)
var/atom/AA = A
if(AA.invisibility>SEE_INVISIBLE_LIVING)
continue
var/atom/AA = A
if(AA.invisibility>SEE_INVISIBLE_LIVING)
continue
if(check_anomalies)//if it's set to check for simple animals
if(istype(A, /mob/living/simple_animal))
var/mob/living/simple_animal/SA = A
@@ -426,7 +426,7 @@
raising = 1
if(cover)
flick("popup", cover)
sleep(POPUP_ANIM_TIME)
sleep(POPUP_ANIM_TIME)
raising = 0
if(cover)
cover.icon_state = "openTurretCover"
@@ -442,7 +442,7 @@
raising = 1
if(cover)
flick("popdown", cover)
sleep(POPDOWN_ANIM_TIME)
sleep(POPDOWN_ANIM_TIME)
raising = 0
if(cover)
cover.icon_state = "turretCover"
@@ -553,6 +553,7 @@
use_power = 0
has_cover = 0
scan_range = 9
req_access = list(GLOB.access_syndicate)
stun_projectile = /obj/item/projectile/bullet
lethal_projectile = /obj/item/projectile/bullet
lethal_projectile_sound = 'sound/weapons/Gunshot.ogg'
@@ -569,6 +570,8 @@
return 10 //Syndicate turrets shoot everything not in their faction
/obj/machinery/porta_turret/syndicate/pod
max_integrity = 40
integrity_failure = 20
obj_integrity = 40
stun_projectile = /obj/item/projectile/bullet/weakbullet3
lethal_projectile = /obj/item/projectile/bullet/weakbullet3
@@ -792,7 +795,7 @@
/obj/item/wallframe/turret_control
name = "turret control frame"
desc = "Used for building turret control panels"
icon_state = "apc"
icon_state = "apc"
result_path = /obj/machinery/turretid
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
@@ -921,3 +924,170 @@
on = 0
spawn(100)
on = 1
/////// MANNED TURRET ////////
/obj/machinery/manned_turret
name = "machine gun turret"
desc = "While the trigger is held down, this gun will redistribute recoil to allow its user to easily shift targets."
icon = 'icons/obj/turrets.dmi'
icon_state = "machinegun"
can_buckle = TRUE
density = TRUE
max_integrity = 100
obj_integrity = 100
buckle_lying = 0
layer = ABOVE_MOB_LAYER
var/view_range = 10
var/cooldown = 0
var/projectile_type = /obj/item/projectile/bullet/weakbullet3
var/rate_of_fire = 1
var/number_of_shots = 40
var/cooldown_duration = 90
var/atom/target
var/turf/target_turf
var/warned = FALSE
//BUCKLE HOOKS
/obj/machinery/manned_turret/unbuckle_mob(mob/living/buckled_mob,force = 0)
playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
for(var/obj/item/I in buckled_mob.held_items)
if(istype(I, /obj/item/gun_control))
qdel(I)
if(istype(buckled_mob))
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 0
if(buckled_mob.client)
buckled_mob.client.change_view(world.view)
anchored = FALSE
. = ..()
/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user)
if(user.incapacitated() || !istype(user))
return
M.forceMove(get_turf(src))
..()
for(var/V in M.held_items)
var/obj/item/I = V
if(istype(I))
if(M.dropItemToGround(I))
var/obj/item/gun_control/TC = new /obj/item/gun_control(src)
M.put_in_hands(TC)
else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
var/obj/item/gun_control/TC = new /obj/item/gun_control(src)
M.put_in_hands(TC)
M.pixel_y = 14
layer = ABOVE_MOB_LAYER
setDir(SOUTH)
playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
anchored = TRUE
if(user.client)
user.client.change_view(view_range)
/obj/item/gun_control
name = "turret controls"
icon = 'icons/obj/weapons.dmi'
icon_state = "offhand"
w_class = WEIGHT_CLASS_HUGE
flags = ABSTRACT | NODROP
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF | NOBLUDGEON
var/obj/machinery/manned_turret/turret
/obj/item/gun_control/New(obj/machinery/manned_turret/MT)
if(MT)
turret = MT
else
qdel(src)
/obj/item/gun_control/CanItemAutoclick()
return 1
/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user)
..()
var/obj/machinery/manned_turret/E = user.buckled
E.setDir(get_dir(E,targeted_atom))
user.setDir(E.dir)
switch(E.dir)
if(NORTH)
E.layer = BELOW_MOB_LAYER
user.pixel_x = 0
user.pixel_y = -14
if(NORTHEAST)
E.layer = BELOW_MOB_LAYER
user.pixel_x = -8
user.pixel_y = -4
if(EAST)
E.layer = ABOVE_MOB_LAYER
user.pixel_x = -14
user.pixel_y = 0
if(SOUTHEAST)
E.layer = BELOW_MOB_LAYER
user.pixel_x = -8
user.pixel_y = 4
if(SOUTH)
E.layer = ABOVE_MOB_LAYER
user.pixel_x = 0
user.pixel_y = 14
if(SOUTHWEST)
E.layer = BELOW_MOB_LAYER
user.pixel_x = 8
user.pixel_y = 4
if(WEST)
E.layer = ABOVE_MOB_LAYER
user.pixel_x = 14
user.pixel_y = 0
if(NORTHWEST)
E.layer = BELOW_MOB_LAYER
user.pixel_x = 8
user.pixel_y = -4
E.checkfire(targeted_atom, user)
/obj/machinery/manned_turret/proc/checkfire(atom/targeted_atom, mob/user)
target = targeted_atom
if(target == user || target == get_turf(src))
return
if(world.time < cooldown)
if(!warned && world.time > (cooldown - cooldown_duration + rate_of_fire*number_of_shots)) // To capture the window where one is done firing
warned = TRUE
playsound(src, 'sound/weapons/sear.ogg', 100, 1)
return
else
cooldown = world.time + cooldown_duration
warned = FALSE
INVOKE_ASYNC(src, /obj/machinery/manned_turret/.proc/volley)
/obj/machinery/manned_turret/proc/volley()
target_turf = get_turf(target)
for(var/i in 1 to number_of_shots)
addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper), i*rate_of_fire)
/obj/machinery/manned_turret/proc/fire_helper()
if(!src)
return
var/turf/targets_from = get_turf(src)
if(QDELETED(target))
target = target_turf
var/obj/item/projectile/P = new projectile_type(targets_from)
P.current = targets_from
P.starting = targets_from
P.firer = src
P.original = target
playsound(src, 'sound/weapons/Gunshot_smg.ogg', 75, 1)
P.yo = target.y - targets_from.y + rand(-1,1)
P.xo = target.x - targets_from.x + rand(-1,1)
P.fire()
/obj/machinery/manned_turret/ultimate // Admin-only proof of concept for autoclicker automatics
name = "Infinity Gun"
view_range = 12
projectile_type = /obj/item/projectile/bullet/weakbullet3
/obj/machinery/manned_turret/ultimate/checkfire(atom/targeted_atom, mob/user)
target = targeted_atom
if(target == user || target == get_turf(src))
return
target_turf = get_turf(target)
fire_helper(target_turf)
+26
View File
@@ -1152,6 +1152,32 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
premium = list(/obj/item/clothing/under/suit_jacket/checkered=1,/obj/item/clothing/head/mailman=1,/obj/item/clothing/under/rank/mailman=1,/obj/item/clothing/suit/jacket/leather=1,/obj/item/clothing/suit/jacket/leather/overcoat=1,/obj/item/clothing/under/pants/mustangjeans=1,/obj/item/clothing/neck/necklace/dope=3,/obj/item/clothing/suit/jacket/letterman_nanotrasen=1)
refill_canister = /obj/item/weapon/vending_refill/clothing
/obj/machinery/vending/toyliberationstation
name = "\improper Syndicate Donksoft Toy Vendor"
desc = "A ages 8 and up approved vendor that dispenses toys. If you were to find the right wires, you can unlock the adult mode setting!"
icon_state = "syndi"
req_access_txt = "1"
product_slogans = "Get your cool toys today!;Trigger a valid hunter today!;Quality toy weapons for cheap prices!;Give them to HoPs for all access!;Give them to HoS to get perma briged!"
product_ads = "Feel robust with your toys!;Express your inner child today!;Toy weapons don't kill people, but valid hunters do!;Who needs responsibilities when you have toy weapons?;Make your next murder FUN!"
vend_reply = "Come back for more!"
products = list(/obj/item/weapon/gun/ballistic/automatic/toy/unrestricted = 10,
/obj/item/weapon/gun/ballistic/automatic/toy/pistol/unrestricted = 10,
/obj/item/weapon/gun/ballistic/shotgun/toy/unrestricted = 10,
/obj/item/toy/sword = 10, /obj/item/ammo_box/foambox = 20,
/obj/item/toy/foamblade = 10,
/obj/item/toy/syndicateballoon = 10,
/obj/item/clothing/suit/syndicatefake = 5,
/obj/item/clothing/head/syndicatefake = 5) //OPS IN DORMS oh wait it's just a assistant
contraband = list(/obj/item/weapon/gun/ballistic/shotgun/toy/crossbow = 10, //Congrats, you unlocked the +18 setting!
/obj/item/weapon/gun/ballistic/automatic/c20r/toy/unrestricted = 10,
/obj/item/weapon/gun/ballistic/automatic/l6_saw/toy/unrestricted = 10,
/obj/item/ammo_box/foambox/riot = 20,
/obj/item/toy/katana = 10,
/obj/item/weapon/twohanded/dualsaber/toy = 5,
/obj/item/toy/cards/deck/syndicate = 10) //Gambling and it hurts, making it a +18 item
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
resistance_flags = FIRE_PROOF
#undef STANDARD_CHARGE
#undef CONTRABAND_CHARGE
#undef COIN_CHARGE
@@ -106,36 +106,19 @@
icon_state = "mecha_analyzer"
selectable = 0
equip_cooldown = 30
var/scanning = 0
var/scanning_time = 0
/obj/item/mecha_parts/mecha_equipment/mining_scanner/New()
..()
START_PROCESSING(SSobj, src)
/obj/item/mecha_parts/mecha_equipment/mining_scanner/attach(obj/mecha/M)
..()
M.occupant_sight_flags |= SEE_TURFS
if(M.occupant)
M.occupant.update_sight()
/obj/item/mecha_parts/mecha_equipment/mining_scanner/detach()
chassis.occupant_sight_flags &= ~SEE_TURFS
if(chassis.occupant)
chassis.occupant.update_sight()
return ..()
/obj/item/mecha_parts/mecha_equipment/mining_scanner/process()
if(!loc)
STOP_PROCESSING(SSobj, src)
qdel(src)
if(scanning)
return
if(istype(loc,/obj/mecha/working))
if(istype(loc,/obj/mecha/working) && scanning_time <= world.time)
var/obj/mecha/working/mecha = loc
if(!mecha.occupant)
return
var/list/L = list(mecha.occupant)
scanning = 1
mineral_scan_pulse(L,get_turf(loc))
spawn(equip_cooldown)
scanning = 0
scanning_time = world.time + equip_cooldown
mineral_scan_pulse(get_turf(src))
+1 -3
View File
@@ -93,6 +93,4 @@
/obj/effect/abstract/proximity_checker/Crossed(atom/movable/AM)
set waitfor = FALSE
var/atom/H = monitor.host
testing("HasProx: [H] -> [AM]")
H.HasProximity(AM)
monitor.host.HasProximity(AM)
@@ -196,13 +196,6 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
user.visible_message("[user] starts cutting hair off \the [src].", "<span class='notice'>You start cutting the hair off \the [src]...</span>", "<span class='italics'>You hear the sound of a knife rubbing against flesh.</span>")
if(do_after(user,50, target = src))
to_chat(user, "<span class='notice'>You cut the hair from this [src.singular_name].</span>")
//Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/sheet/hairlesshide/HS in user.loc)
if(HS.amount < 50)
HS.amount++
use(1)
break
//If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/sheet/hairlesshide/HS = new(user.loc)
HS.amount = 1
use(1)
@@ -230,3 +223,9 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
HS.amount = 1
wetness = initial(wetness)
src.use(1)
/obj/item/stack/sheet/wetleather/microwave_act(obj/machinery/microwave/MW)
..()
var/obj/item/stack/sheet/leather/L = new(loc)
L.amount = amount
qdel(src)
@@ -51,6 +51,7 @@
M.updateappearance(mutations_overlay_update=1)
log_attack(log_msg)
return TRUE
return FALSE
/obj/item/weapon/dnainjector/attack(mob/target, mob/user)
if(!user.IsAdvancedToolUser())
@@ -307,11 +308,11 @@
/obj/item/weapon/dnainjector/timed/inject(mob/living/carbon/M, mob/user)
prepare()
if(M.stat == DEAD) //prevents dead people from having their DNA changed
to_chat(user, "<span class='notice'>You can't modify [M]'s DNA while [M.p_theyre()] dead.</span>")
return FALSE
if(M.has_dna() && !(M.disabilities & NOCLONE))
if(M.stat == DEAD) //prevents dead people from having their DNA changed
to_chat(user, "<span class='notice'>You can't modify [M]'s DNA while [M.p_theyre()] dead.</span>")
return
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
var/endtime = world.time+duration
@@ -352,9 +353,9 @@
M.updateappearance(mutations_overlay_update=1)
M.dna.temporary_mutations[UI_CHANGED] = endtime
log_attack(log_msg)
return TRUE
else
to_chat(user, "<span class='notice'>It appears that [M] does not have compatible DNA.</span>")
return
return FALSE
/obj/item/weapon/dnainjector/timed/hulk
name = "\improper DNA injector (Hulk)"
@@ -19,7 +19,9 @@
var/mob/living/carbon/human/H = imp_in
if(!ishuman(H))
return
if(istype(H.martial_art, /datum/martial_art/krav_maga))
if(!H.mind)
return
if(istype(H.mind.martial_art, /datum/martial_art/krav_maga))
style.remove(H)
else
style.teach(H,1)
@@ -247,10 +247,10 @@
)
/obj/item/weapon/storage/belt/military
name = "military belt"
desc = "A syndicate belt designed to be used by boarding parties. Its style is modeled after the hardsuits they wear."
icon_state = "militarybelt"
item_state = "military"
name = "chest rig"
desc = "A set of tactical webbing worn by Syndicate boarding parties."
icon_state = "explorer1"
item_state = "explorer1"
max_w_class = WEIGHT_CLASS_SMALL
/obj/item/weapon/storage/belt/military/abductor
@@ -106,7 +106,7 @@
new /obj/item/device/flashlight/seclite(src)
new /obj/item/clothing/gloves/krav_maga/sec(src)
new /obj/item/weapon/door_remote/head_of_security(src)
new /obj/item/weapon/gun/ballistic/shotgun/automatic/dual_tube(src)
new /obj/item/weapon/gun/ballistic/shotgun/automatic/combat/compact(src)
/obj/structure/closet/secure_closet/security
name = "security officer's locker"
@@ -152,6 +152,8 @@
var/transfer_choice = alert("Transfer your soul to [src]? (Warning, your old body will die!)",,"Yes","No")
if(transfer_choice != "Yes")
return
if(QDELETED(src) || uses <= 0)
return
log_game("[user.ckey] golem-swapped into [src]")
user.visible_message("<span class='notice'>A faint light leaves [user], moving to [src] and animating it!</span>","<span class='notice'>You leave your old body behind, and transfer into [src]!</span>")
create(ckey = user.ckey, flavour = FALSE, name = user.real_name)
+3
View File
@@ -111,6 +111,9 @@
initial_gas_mix = "o2=14;n2=23;TEMP=300"
planetary_atmos = TRUE
baseturf = /turf/open/chasm/straight_down/lava_land_surface
light_range = 1.9 //slightly less range than lava
light_power = 0.65 //less bright, too
light_color = LIGHT_COLOR_LAVA //let's just say you're falling into lava, that makes sense right
/turf/open/chasm/straight_down/lava_land_surface/drop(atom/movable/AM)
//Make sure the item is still there after our sleep
+2
View File
@@ -73,6 +73,8 @@
for(i in 1 to mineralAmt)
new mineralType(src)
SSblackbox.add_details("ore_mined",mineralType)
for(var/obj/effect/temp_visual/mining_overlay/M in src)
qdel(M)
ChangeTurf(turf_type, defer_change)
addtimer(CALLBACK(src, .proc/AfterChange), 1, TIMER_UNIQUE)
playsound(src, 'sound/effects/break_stone.ogg', 50, 1) //beautiful destruction
@@ -19,7 +19,7 @@
/obj/machinery/meter/Initialize(mapload)
. = ..()
SSair.atmos_machinery += src
if (mapload && !target)
if (!target)
target = locate(/obj/machinery/atmospherics/pipe) in loc
/obj/machinery/meter/Destroy()
+2
View File
@@ -271,6 +271,8 @@ BLIND // can't see anything
/obj/item/clothing/head
name = "head"
icon = 'icons/obj/clothing/hats.dmi'
icon_state = "top_hat"
item_state = "that"
body_parts_covered = HEAD
slot_flags = SLOT_HEAD
var/blockTracking = 0 //For AI tracking
+29 -16
View File
@@ -7,25 +7,34 @@
actions_types = list(/datum/action/item_action/toggle_mode)
origin_tech = "materials=3;magnets=3;engineering=3;plasmatech=3"
var/mode = 0 //0 - regular mesons mode 1 - t-ray mode
mode = FALSE //FALSE - regular mesons mode TRUE - t-ray mode
var/range = 1
/obj/item/clothing/glasses/meson/engine/attack_self(mob/user)
/obj/item/clothing/glasses/meson/engine/toggle_mode(mob/user, voluntary)
var/turf/T = get_turf(src)
if(T && T.z == ZLEVEL_MINING && mode)
if(picked_excuse)
to_chat(user, "<span class='warning'>Due to [picked_excuse], the [name] cannot currently be swapped to \[Meson] mode.</span>")
return
mode = !mode
if(mode)
START_PROCESSING(SSobj, src)
vision_flags = 0
darkness_view = 2
invis_view = SEE_INVISIBLE_LIVING
lighting_alpha = null
to_chat(user, "<span class='notice'>You toggle the goggles' scanning mode to \[T-Ray].</span>")
if(voluntary)
to_chat(user, "<span class='notice'>You toggle the goggles' scanning mode to \[T-Ray].</span>")
else
to_chat(user, "<span class='warning'>The goggles abruptly toggle to \[T-Ray] mode!</span>")
else
STOP_PROCESSING(SSobj, src)
vision_flags = SEE_TURFS
darkness_view = 1
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
to_chat(loc, "<span class='notice'>You toggle the goggles' scanning mode to \[Meson].</span>")
if(voluntary)
to_chat(user, "<span class='notice'>You toggle the goggles' scanning mode to \[Meson].</span>")
else
to_chat(user, "<span class='warning'>The goggles abruptly toggle to \[Meson] mode!</span>")
if(ishuman(user))
var/mob/living/carbon/human/H = user
@@ -37,8 +46,14 @@
var/datum/action/A = X
A.UpdateButtonIcon()
/obj/item/clothing/glasses/meson/engine/attack_self(mob/user)
toggle_mode(user, TRUE)
/obj/item/clothing/glasses/meson/engine/process()
if(!mode)
var/turf/T = get_turf(src)
if(T && T.z == ZLEVEL_MINING)
toggle_mode(loc)
return
if(!ishuman(loc))
@@ -47,7 +62,6 @@
var/mob/living/carbon/human/user = loc
if(user.glasses != src)
return
scan()
/obj/item/clothing/glasses/meson/engine/proc/scan()
@@ -89,13 +103,17 @@
icon_state = "trayson-tray_off"
origin_tech = "materials=3;magnets=2;engineering=2"
mode = 1
var/on = 0
mode = TRUE
var/on = FALSE
vision_flags = 0
darkness_view = 2
invis_view = SEE_INVISIBLE_LIVING
range = 2
/obj/item/clothing/glasses/meson/engine/tray/Initialize()
. = ..()
picked_excuse = null
/obj/item/clothing/glasses/meson/engine/tray/process()
if(!on)
return
@@ -108,15 +126,10 @@
if(user.glasses == src)
user.update_inv_glasses()
/obj/item/clothing/glasses/meson/engine/tray/attack_self(mob/user)
/obj/item/clothing/glasses/meson/engine/tray/toggle_mode(mob/user, voluntary)
on = !on
if(on)
START_PROCESSING(SSobj, src)
to_chat(user, "<span class='notice'>You turn the goggles on.</span>")
else
STOP_PROCESSING(SSobj, src)
to_chat(user, "<span class='notice'>You turn the goggles off.</span>")
to_chat(user, "<span class='[voluntary ? "notice":"warning"]'>[voluntary ? "You turn the goggles":"The goggles turn"] [on ? "on":"off"][voluntary ? ".":"!"]</span>")
update_icon()
for(var/X in actions)
+49 -3
View File
@@ -31,14 +31,60 @@
/obj/item/clothing/glasses/meson
name = "Optical Meson Scanner"
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition."
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting conditions."
icon_state = "meson"
item_state = "meson"
origin_tech = "magnets=1;engineering=2"
darkness_view = 2
vision_flags = SEE_TURFS
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
glass_colour_type = /datum/client_colour/glass_colour/lightgreen
var/static/list/meson_mining_failure_excuses = list("seismic activity", "excessive lava", "ambient radiation", "electromagnetic storms", "bluespace disruption", \
"gravity", "dust", "dense rock", "ash", "badly understood science", "radiant heat")
var/picked_excuse
var/mode = FALSE //if FALSE, is in normal meson mode.
/obj/item/clothing/glasses/meson/Initialize()
. = ..()
picked_excuse = pick(meson_mining_failure_excuses)
START_PROCESSING(SSobj, src)
/obj/item/clothing/glasses/meson/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/clothing/glasses/meson/examine(mob/user)
..()
var/turf/T = get_turf(src)
if(T && T.z == ZLEVEL_MINING && mode && picked_excuse)
to_chat(user, "<span class='warning'>Due to [picked_excuse], these Meson Scanners will not be able to display terrain layouts in this area.</span>")
/obj/item/clothing/glasses/meson/proc/toggle_mode(mob/user)
if(vision_flags & SEE_TURFS)
mode = TRUE
vision_flags &= ~SEE_TURFS
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(picked_excuse)
to_chat(H, "<span class='warning'>Due to [picked_excuse], your Meson Scanners will not be able to display terrain layouts in this area.</span>")
if(H.glasses == src)
H.update_sight()
else if(!(vision_flags & SEE_TURFS))
mode = FALSE
vision_flags |= SEE_TURFS
if(ishuman(user))
var/mob/living/carbon/human/H = user
to_chat(H, "<span class='notice'>Your Meson Scanners have reactivated.</span>")
if(H.glasses == src)
H.update_sight()
/obj/item/clothing/glasses/meson/process()
var/turf/T = get_turf(src)
if(T && T.z == ZLEVEL_MINING)
if(!mode)
toggle_mode(loc)
else if(mode)
toggle_mode(loc)
/obj/item/clothing/glasses/meson/night
name = "Night Vision Optical Meson Scanner"
@@ -47,7 +93,7 @@
item_state = "nvgmeson"
origin_tech = "magnets=4;engineering=5;plasmatech=4"
darkness_view = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/meson/gar
+6 -6
View File
@@ -14,14 +14,14 @@
/obj/item/clothing/suit/armor/vest
name = "armor vest"
desc = "A slim armored vest that protects against most types of damage."
desc = "A slim Type I armored vest that provides decent protection against most types of damage."
icon_state = "armoralt"
item_state = "armoralt"
blood_overlay_type = "armor"
dog_fashion = /datum/dog_fashion/back
/obj/item/clothing/suit/armor/vest/alt
desc = "An armored vest that protects against most types of damage."
desc = "A Type I armored vest that provides decent protection against most types of damage."
icon_state = "armor"
item_state = "armor"
@@ -31,7 +31,7 @@
/obj/item/clothing/suit/armor/hos
name = "armored greatcoat"
desc = "A greatcoat enchanced with a special alloy for some protection and style for those with a commanding presence."
desc = "A greatcoat enhanced with a special alloy for some extra protection and style for those with a commanding presence."
icon_state = "hos"
item_state = "greatcoat"
body_parts_covered = CHEST|GROIN|ARMS|LEGS
@@ -77,7 +77,7 @@
/obj/item/clothing/suit/armor/vest/capcarapace
name = "captain's carapace"
desc = "An armored vest reinforced with ceramic plates and pauldrons to provide additional protection whilst still offering maximum mobility and flexibility. Issued only to the station's finest, although it does chafe your nipples."
desc = "An fireproof armored chestpiece reinforced with ceramic plates and plasteel pauldrons to provide additional protection whilst still offering maximum mobility and flexibility. Issued only to the station's finest, although it does chafe your nipples."
icon_state = "capcarapace"
item_state = "armor"
body_parts_covered = CHEST|GROIN
@@ -93,7 +93,7 @@
/obj/item/clothing/suit/armor/riot
name = "riot suit"
desc = "A suit of armor with heavy padding to protect against melee attacks."
desc = "A suit of semi-flexible polycarbonate body armor with heavy padding to protect against melee attacks."
icon_state = "riot"
item_state = "swat_suit"
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
@@ -115,7 +115,7 @@
/obj/item/clothing/suit/armor/bulletproof
name = "bulletproof armor"
desc = "A bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent."
desc = "A Type III heavy bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent."
icon_state = "bulletproof"
item_state = "armor"
blood_overlay_type = "armor"
-5
View File
@@ -28,7 +28,6 @@
var/square_depth_up = 0
var/square_depth_down = 0
//Processing
var/requires_processing = FALSE
var/process_inner_turfs = FALSE //Don't do this unless it's absolutely necessary
var/process_edge_turfs = FALSE //Don't do this either unless it's absolutely necessary, you can just track what things are inside manually or on the initial setup.
var/setup_edge_turfs = FALSE //Setup edge turfs/all field turfs. Set either or both to ON when you need it, it's defaulting to off unless you do to save CPU.
@@ -40,11 +39,7 @@
var/list/turf/field_turfs_new = list()
var/list/turf/edge_turfs_new = list()
/datum/proximity_monitor/advanced/New()
SSfields.register_new_field(src)
/datum/proximity_monitor/advanced/Destroy()
SSfields.unregister_field(src)
full_cleanup()
return ..()
+5 -1
View File
@@ -3,7 +3,6 @@
//Only use square radius for this!
/datum/proximity_monitor/advanced/peaceborg_dampener
name = "\improper Hyperkinetic Dampener Field"
requires_processing = TRUE
setup_edge_turfs = TRUE
setup_field_turfs = TRUE
field_shape = FIELD_SHAPE_RADIUS_SQUARE
@@ -22,10 +21,15 @@
use_host_turf = TRUE
/datum/proximity_monitor/advanced/peaceborg_dampener/New()
START_PROCESSING(SSfields, src)
tracked = list()
staging = list()
..()
/datum/proximity_monitor/advanced/peaceborg_dampener/Destroy()
STOP_PROCESSING(SSfields, src)
return ..()
/datum/proximity_monitor/advanced/peaceborg_dampener/process()
if(!istype(projector))
qdel(src)
+1 -1
View File
@@ -125,7 +125,7 @@
/datum/language_holder/synthetic
languages = list(/datum/language/common)
shadow_languages = list(/datum/language/machine, /datum/language/draconic)
shadow_languages = list(/datum/language/common, /datum/language/machine, /datum/language/draconic)
/datum/language_holder/universal/New()
..()
+2 -2
View File
@@ -270,7 +270,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
if(5)
dat += "<H3>Upload a New Title</H3>"
if(!scanner)
findscanner(9)
scanner = findscanner(9)
if(!scanner)
dat += "<FONT color=red>No scanner found within wireless network range.</FONT><BR>"
else if(!scanner.cache)
@@ -314,7 +314,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
popup.open()
/obj/machinery/computer/libraryconsole/bookmanagement/proc/findscanner(viewrange)
for(var/obj/machinery/libraryscanner/S in range(viewrange))
for(var/obj/machinery/libraryscanner/S in range(viewrange, get_turf(src)))
return S
return null
+78 -99
View File
@@ -169,7 +169,7 @@
icon = 'icons/obj/mining.dmi'
icon_state = "resonator"
item_state = "resonator"
desc = "A handheld device that creates small fields of energy that resonate until they detonate, crushing rock. It can also be activated without a target to create a field at the user's location, to act as a delayed time trap. It's more effective in a vacuum."
desc = "A handheld device that creates small fields of energy that resonate until they detonate, crushing rock. It's more effective in a vacuum."
w_class = WEIGHT_CLASS_NORMAL
force = 15
throwforce = 10
@@ -188,18 +188,6 @@
fieldlimit = 6
quick_burst_mod = 1
/obj/item/weapon/resonator/proc/CreateResonance(target, creator)
var/turf/T = get_turf(target)
var/obj/effect/resonance/R = locate(/obj/effect/resonance) in T
if(R)
R.resonance_damage *= quick_burst_mod
R.burst()
return
if(fields.len < fieldlimit)
playsound(src,'sound/weapons/resonator_fire.ogg',50,1)
var/obj/effect/resonance/RE = new(T, creator, burst_time, src)
fields += RE
/obj/item/weapon/resonator/attack_self(mob/user)
if(burst_time == 50)
burst_time = 30
@@ -208,57 +196,76 @@
burst_time = 50
to_chat(user, "<span class='info'>You set the resonator's fields to detonate after 5 seconds.</span>")
/obj/item/weapon/resonator/afterattack(atom/target, mob/user, proximity_flag)
if(proximity_flag)
if(!check_allowed_items(target, 1))
return
/obj/item/weapon/resonator/proc/CreateResonance(target, mob/user)
var/turf/T = get_turf(target)
var/obj/effect/temp_visual/resonance/R = locate(/obj/effect/temp_visual/resonance) in T
if(R)
R.damage_multiplier = quick_burst_mod
R.burst()
return
if(LAZYLEN(fields) < fieldlimit)
new /obj/effect/temp_visual/resonance(T, user, src, burst_time)
user.changeNext_move(CLICK_CD_MELEE)
CreateResonance(target, user)
/obj/effect/resonance
/obj/item/weapon/resonator/pre_attackby(atom/target, mob/user, params)
if(check_allowed_items(target, 1))
CreateResonance(target, user)
return TRUE
/obj/effect/temp_visual/resonance
name = "resonance field"
desc = "A resonating field that significantly damages anything inside of it when the field eventually ruptures. More damaging in low pressure environments."
icon = 'icons/effects/effects.dmi'
icon_state = "shield1"
layer = ABOVE_ALL_MOB_LAYER
anchored = TRUE
mouse_opacity = 0
duration = 50
var/resonance_damage = 20
var/damage_multiplier = 1
var/creator
var/obj/item/weapon/resonator/res
/obj/effect/resonance/New(loc, set_creator, timetoburst, set_resonator)
..()
/obj/effect/temp_visual/resonance/Initialize(mapload, set_creator, set_resonator, set_duration)
duration = set_duration
. = ..()
creator = set_creator
res = set_resonator
check_pressure()
addtimer(CALLBACK(src, .proc/burst), timetoburst)
if(res)
res.fields += src
playsound(src,'sound/weapons/resonator_fire.ogg',50,1)
transform = matrix()*0.75
animate(src, transform = matrix()*1.5, time = duration)
deltimer(timerid)
timerid = addtimer(CALLBACK(src, .proc/burst), duration, TIMER_STOPPABLE)
/obj/effect/resonance/Destroy()
/obj/effect/temp_visual/resonance/Destroy()
if(res)
res.fields -= src
res = null
creator = null
. = ..()
/obj/effect/resonance/proc/check_pressure()
var/turf/proj_turf = get_turf(src)
/obj/effect/temp_visual/resonance/proc/check_pressure(turf/proj_turf)
if(!proj_turf)
proj_turf = get_turf(src)
if(!istype(proj_turf))
return
var/datum/gas_mixture/environment = proj_turf.return_air()
var/pressure = environment.return_pressure()
resonance_damage = initial(resonance_damage)
if(pressure < 50)
name = "strong [initial(name)]"
resonance_damage = 60
resonance_damage *= 3
else
name = initial(name)
resonance_damage = initial(resonance_damage)
resonance_damage *= damage_multiplier
/obj/effect/resonance/proc/burst()
check_pressure()
/obj/effect/temp_visual/resonance/proc/burst()
var/turf/T = get_turf(src)
playsound(src,'sound/weapons/resonator_blast.ogg',50,1)
new /obj/effect/temp_visual/resonance_crush(T)
if(ismineralturf(T))
var/turf/closed/mineral/M = T
M.gets_drilled(creator)
check_pressure(T)
playsound(T,'sound/weapons/resonator_blast.ogg',50,1)
for(var/mob/living/L in T)
if(creator)
add_logs(creator, L, "used a resonator field on", "resonator")
@@ -266,6 +273,16 @@
L.apply_damage(resonance_damage, BRUTE)
qdel(src)
/obj/effect/temp_visual/resonance_crush
icon_state = "shield1"
layer = ABOVE_ALL_MOB_LAYER
duration = 4
/obj/effect/temp_visual/resonance_crush/Initialize()
. = ..()
transform = matrix()*1.5
animate(src, transform = matrix()*0.1, alpha = 50, time = 4)
/**********************Facehugger toy**********************/
/obj/item/clothing/mask/facehugger/toy
@@ -345,28 +362,23 @@
/**********************Mining Scanners**********************/
/obj/item/device/mining_scanner
desc = "A scanner that checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results."
desc = "A scanner that checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations."
name = "manual mining scanner"
icon_state = "mining1"
item_state = "analyzer"
w_class = WEIGHT_CLASS_SMALL
flags = CONDUCT
slot_flags = SLOT_BELT
var/cooldown = 0
var/cooldown = 35
var/current_cooldown = 0
origin_tech = "engineering=1;magnets=1"
/obj/item/device/mining_scanner/attack_self(mob/user)
if(!user.client)
return
if(!cooldown)
cooldown = TRUE
addtimer(CALLBACK(src, .proc/clear_cooldown), 40)
var/list/mobs = list()
mobs |= user
mineral_scan_pulse(mobs, get_turf(user))
/obj/item/device/mining_scanner/proc/clear_cooldown()
cooldown = FALSE
if(current_cooldown <= world.time)
current_cooldown = world.time + cooldown
mineral_scan_pulse(get_turf(user))
//Debug item to identify all ore spread quickly
@@ -379,7 +391,7 @@
qdel(src)
/obj/item/device/t_scanner/adv_mining_scanner
desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear meson scanners for optimal results. This one has an extended range."
desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. This one has an extended range."
name = "advanced automatic mining scanner"
icon_state = "mining0"
item_state = "analyzer"
@@ -387,77 +399,47 @@
flags = CONDUCT
slot_flags = SLOT_BELT
var/cooldown = 35
var/on_cooldown = 0
var/current_cooldown = 0
var/range = 7
var/meson = TRUE
origin_tech = "engineering=3;magnets=3"
/obj/item/device/t_scanner/adv_mining_scanner/material
meson = FALSE
desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results. This one has an extended range."
/obj/item/device/t_scanner/adv_mining_scanner/lesser
name = "automatic mining scanner"
desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear meson scanners for optimal results."
desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations."
range = 4
cooldown = 50
/obj/item/device/t_scanner/adv_mining_scanner/lesser/material
desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results."
meson = FALSE
/obj/item/device/t_scanner/adv_mining_scanner/scan()
if(!on_cooldown)
on_cooldown = 1
spawn(cooldown)
on_cooldown = 0
if(current_cooldown <= world.time)
current_cooldown = world.time + cooldown
var/turf/t = get_turf(src)
var/list/mobs = recursive_mob_check(t, 1,0,0)
if(!mobs.len)
return
if(meson)
mineral_scan_pulse(mobs, t, range)
else
mineral_scan_pulse_material(mobs, t, range)
mineral_scan_pulse(t, range)
//For use with mesons
/proc/mineral_scan_pulse(list/mobs, turf/T, range = world.view)
/proc/mineral_scan_pulse(turf/T, range = world.view)
var/list/minerals = list()
for(var/turf/closed/mineral/M in range(range, T))
if(M.scan_state)
minerals += M
if(minerals.len)
for(var/mob/user in mobs)
if(user.client)
var/client/C = user.client
for(var/turf/closed/mineral/M in minerals)
var/turf/F = get_turf(M)
var/image/I = image('icons/turf/smoothrocks.dmi', loc = F, icon_state = M.scan_state, layer = FLASH_LAYER)
I.plane = FULLSCREEN_PLANE
C.images += I
spawn(30)
if(C)
C.images -= I
//For use with material scanners
/proc/mineral_scan_pulse_material(list/mobs, turf/T, range = world.view)
var/list/minerals = list()
for(var/turf/closed/mineral/M in range(range, T))
if(M.scan_state)
minerals += M
if(minerals.len)
if(LAZYLEN(minerals))
for(var/turf/closed/mineral/M in minerals)
var/obj/effect/temp_visual/mining_overlay/oldC = locate(/obj/effect/temp_visual/mining_overlay) in M
if(oldC)
qdel(oldC)
var/obj/effect/temp_visual/mining_overlay/C = new /obj/effect/temp_visual/mining_overlay(M)
C.icon_state = M.scan_state
/obj/effect/temp_visual/mining_overlay
plane = FULLSCREEN_PLANE
layer = FLASH_LAYER
icon = 'icons/turf/smoothrocks.dmi'
anchored = 1
mouse_opacity = 0
duration = 30
pixel_x = -4
pixel_y = -4
icon = 'icons/effects/ore_visuals.dmi'
appearance_flags = 0 //to avoid having TILE_BOUND in the flags, so that the 480x480 icon states let you see it no matter where you are
duration = 35
pixel_x = -224
pixel_y = -224
/obj/effect/temp_visual/mining_overlay/Initialize()
. = ..()
animate(src, alpha = 0, time = duration, easing = EASE_IN)
/**********************Xeno Warning Sign**********************/
@@ -529,7 +511,6 @@
return ..()
/obj/item/projectile/destabilizer/on_hit(atom/target, blocked = 0)
if(isliving(target))
var/mob/living/L = target
var/datum/status_effect/crusher_mark/CM = L.apply_status_effect(STATUS_EFFECT_CRUSHERMARK)
@@ -539,7 +520,6 @@
var/turf/closed/mineral/M = target_turf
new /obj/effect/temp_visual/kinetic_blast(M)
M.gets_drilled(firer)
..()
/obj/item/weapon/twohanded/required/mining_hammer/afterattack(atom/target, mob/user, proximity_flag)
@@ -570,7 +550,6 @@
else
L.apply_damage(50, BRUTE, blocked = def_check)
/obj/item/weapon/twohanded/required/mining_hammer/proc/Recharge()
if(!charged)
charged = TRUE
@@ -821,7 +821,9 @@
timer = world.time + cooldown_time
if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one!
chaser_timer = world.time + chaser_cooldown
new /obj/effect/temp_visual/hierophant/chaser(get_turf(user), user, target, chaser_speed, friendly_fire_check)
var/obj/effect/temp_visual/hierophant/chaser/C = new(get_turf(user), user, target, chaser_speed, friendly_fire_check)
C.damage = 30
C.monster_damage_boost = FALSE
add_logs(user, target, "fired a chaser at", src)
else
INVOKE_ASYNC(src, .proc/cardinal_blasts, T, user) //otherwise, just do cardinal blast
+1 -1
View File
@@ -19,7 +19,7 @@
new /datum/data/mining_equipment("Stabilizing Serum", /obj/item/weapon/hivelordstabilizer, 400),
new /datum/data/mining_equipment("Fulton Beacon", /obj/item/fulton_core, 400),
new /datum/data/mining_equipment("Shelter Capsule", /obj/item/weapon/survivalcapsule, 400),
new /datum/data/mining_equipment("GAR scanners", /obj/item/clothing/glasses/meson/gar, 500),
new /datum/data/mining_equipment("GAR Meson Scanners", /obj/item/clothing/glasses/meson/gar, 500),
new /datum/data/mining_equipment("Explorer's Webbing", /obj/item/weapon/storage/belt/mining, 500),
new /datum/data/mining_equipment("Survival Medipen", /obj/item/weapon/reagent_containers/hypospray/medipen/survival, 500),
new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/weapon/storage/firstaid/brute, 600),
-20
View File
@@ -44,7 +44,6 @@
var/light_on = 0
var/datum/action/innate/minedrone/toggle_light/toggle_light_action
var/datum/action/innate/minedrone/toggle_meson_vision/toggle_meson_vision_action
var/datum/action/innate/minedrone/toggle_mode/toggle_mode_action
var/datum/action/innate/minedrone/dump_ore/dump_ore_action
@@ -52,8 +51,6 @@
..()
toggle_light_action = new()
toggle_light_action.Grant(src)
toggle_meson_vision_action = new()
toggle_meson_vision_action.Grant(src)
toggle_mode_action = new()
toggle_mode_action.Grant(src)
dump_ore_action = new()
@@ -189,23 +186,6 @@
user.light_on = !user.light_on
to_chat(user, "<span class='notice'>You toggle your light [user.light_on ? "on" : "off"].</span>")
/datum/action/innate/minedrone/toggle_meson_vision
name = "Toggle Meson Vision"
button_icon_state = "meson"
/datum/action/innate/minedrone/toggle_meson_vision/Activate()
var/mob/living/simple_animal/hostile/mining_drone/user = owner
if(user.sight & SEE_TURFS)
user.sight &= ~SEE_TURFS
user.lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
else
user.sight |= SEE_TURFS
user.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
user.sync_lighting_plane_alpha()
to_chat(user, "<span class='notice'>You toggle your meson vision [(user.sight & SEE_TURFS) ? "on" : "off"].</span>")
/datum/action/innate/minedrone/toggle_mode
name = "Toggle Mode"
button_icon_state = "mech_cycle_equip_off"
@@ -36,7 +36,8 @@
//initialise organs
create_internal_organs()
martial_art = default_martial_art
if(mind)
mind.martial_art = mind.default_martial_art
handcrafting = new()
@@ -40,12 +40,13 @@
if(spec_return)
return spec_return
if(martial_art && martial_art.deflection_chance) //Some martial arts users can deflect projectiles!
if(prob(martial_art.deflection_chance))
if(!lying && dna && !dna.check_mutation(HULK)) //But only if they're not lying down, and hulks can't do it
visible_message("<span class='danger'>[src] deflects the projectile; [p_they()] can't be hit with ranged weapons!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1)
return 0
if(mind)
if(mind.martial_art && mind.martial_art.deflection_chance) //Some martial arts users can deflect projectiles!
if(prob(mind.martial_art.deflection_chance))
if(!lying && dna && !dna.check_mutation(HULK)) //But only if they're not lying down, and hulks can't do it
visible_message("<span class='danger'>[src] deflects the projectile; [p_they()] can't be hit with ranged weapons!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1)
return 0
if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
@@ -103,10 +104,11 @@
return 0
/mob/living/carbon/human/proc/check_block()
if(martial_art && martial_art.block_chance \
&& prob(martial_art.block_chance) && in_throw_mode \
&& !stat && !weakened && !stunned)
return TRUE
if(mind)
if(mind.martial_art && mind.martial_art.block_chance \
&& prob(mind.martial_art.block_chance) && in_throw_mode \
&& !stat && !weakened && !stunned)
return TRUE
return FALSE
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
@@ -39,9 +39,6 @@
var/bleed_rate = 0 //how much are we bleeding
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
var/datum/martial_art/martial_art = null
var/static/default_martial_art = new/datum/martial_art
var/name_override //For temporary visible name changes
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
@@ -144,9 +144,9 @@
if(NOGUNS in src.dna.species.species_traits)
to_chat(src, "<span class='warning'>Your fingers don't fit in the trigger guard!</span>")
return 0
if(martial_art && martial_art.no_guns) //great dishonor to famiry
to_chat(src, "<span class='warning'>Use of ranged weaponry would bring dishonor to the clan.</span>")
return 0
if(mind)
if(mind.martial_art && mind.martial_art.no_guns) //great dishonor to famiry
to_chat(src, "<span class='warning'>Use of ranged weaponry would bring dishonor to the clan.</span>")
return 0
return .
@@ -0,0 +1,9 @@
/mob/living/carbon/human/Login()
..()
if(src.martial_art == default_martial_art && mind.stored_martial_art) //If the mind has a martial art stored and the body has the default one.
src.mind.stored_martial_art.teach(src) //Running teach so that it deals with help verbs.
else if(src.martial_art != default_martial_art && src.martial_art != mind.stored_martial_art) //If the body has a martial art which is not the default one and is not stored in the mind.
if(src.martial_art_owner != mind)
src.martial_art.remove(src)
else
src.mind.stored_martial_art = src.martial_art
@@ -1304,7 +1304,7 @@
/datum/species/proc/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
return
/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art)
/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
if(!istype(M))
return
CHECK_DNA_AND_SPECIES(M)
@@ -1312,6 +1312,8 @@
if(!istype(M)) //sanity check for drones.
return
if(M.mind)
attacker_style = M.mind.martial_art
if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(0, M.name, attack_type = UNARMED_ATTACK))
add_logs(M, H, "attempted to touch")
H.visible_message("<span class='warning'>[M] attempted to touch [H]!</span>")
@@ -406,7 +406,7 @@
else
reactive_teleport(H)
/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art)
/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
..()
if(world.time > last_teleport + teleport_cooldown && M != H && M.a_intent != INTENT_HELP)
reactive_teleport(H)
@@ -490,7 +490,7 @@
var/golem_name = "[uppertext(clown_name)]"
return golem_name
/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art)
/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
..()
if(world.time > last_banana + banana_cooldown && M != H && M.a_intent != INTENT_HELP)
new/obj/item/weapon/grown/bananapeel/specialpeel(get_turf(H))
@@ -526,7 +526,6 @@
name = "Miner"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/borg/sight/meson,
/obj/item/weapon/storage/bag/ore/cyborg,
/obj/item/weapon/pickaxe/drill/cyborg,
/obj/item/weapon/shovel,
@@ -123,8 +123,9 @@ Difficulty: Very Hard
/mob/living/simple_animal/hostile/megafauna/colossus/proc/enrage(mob/living/L)
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.martial_art && prob(H.martial_art.deflection_chance))
. = TRUE
if(H.mind)
if(H.mind.martial_art && prob(H.mind.martial_art.deflection_chance))
. = TRUE
/mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots()
dir_shots(GLOB.diagonals)
@@ -525,7 +525,9 @@ Difficulty: Hard
targetturf = get_turf(target)
/obj/effect/temp_visual/hierophant/chaser/proc/make_blast()
new /obj/effect/temp_visual/hierophant/blast(loc, caster, friendly_fire_check)
var/obj/effect/temp_visual/hierophant/blast/B = new(loc, caster, friendly_fire_check)
B.damage = damage
B.monster_damage_boost = monster_damage_boost
/obj/effect/temp_visual/hierophant/telegraph
icon = 'icons/effects/96x96.dmi'
+5 -1
View File
@@ -295,8 +295,12 @@
return A
else
var/atom/movable/AM = A
if(AM == buckled) //Kind of unnecessary but let's just be sure
if(AM == buckled)
continue
if(ismob(AM))
var/mob/M = AM
if(M.buckled)
continue
if(!AM.CanPass(src) || AM.density)
if(AM.anchored)
return AM
+2 -2
View File
@@ -44,8 +44,8 @@
..()
/obj/item/weapon/paper/New()
..()
/obj/item/weapon/paper/Initialize()
. = ..()
pixel_y = rand(-8, 8)
pixel_x = rand(-9, 9)
update_icon()
+1 -1
View File
@@ -110,7 +110,7 @@
papers.Add(P)
total_paper++
update_icon()
else if(istype(I, /obj/item/weapon/pen))
else if(istype(I, /obj/item/weapon/pen) && !bin_pen)
var/obj/item/weapon/pen/P = I
if(!user.transferItemToLoc(P, src))
return
@@ -13,6 +13,21 @@
max_ammo = 8
multiple_sprites = 2
/obj/item/ammo_box/magazine/m10mm/rifle
name = "rifle magazine (10mm)"
desc = "A well-worn magazine fitted for the surplus rifle."
icon_state = "75-8"
origin_tech = "combat=2"
ammo_type = /obj/item/ammo_casing/c10mm
caliber = "10mm"
max_ammo = 10
/obj/item/ammo_box/magazine/m10mm/rifle/update_icon()
if(ammo_count())
icon_state = "75-8"
else
icon_state = "75-0"
/obj/item/ammo_box/magazine/m10mm/fire
name = "pistol magazine (10mm incendiary)"
desc = "A gun magazine. Loaded with rounds which ignite the target."
@@ -52,16 +67,31 @@
/obj/item/ammo_box/magazine/wt550m9/wtap
name = "wt550 magazine (Armour Piercing 4.6x30mm)"
icon_state = "46x30mmtA-20"
ammo_type = /obj/item/ammo_casing/c46x30mmap
/obj/item/ammo_box/magazine/wt550m9/wtap/update_icon()
..()
icon_state = "46x30mmtA-[round(ammo_count(),4)]"
/obj/item/ammo_box/magazine/wt550m9/wttx
name = "wt550 magazine (Toxin Tipped 4.6x30mm)"
icon_state = "46x30mmtT-20"
ammo_type = /obj/item/ammo_casing/c46x30mmtox
/obj/item/ammo_box/magazine/wt550m9/wttx/update_icon()
..()
icon_state = "46x30mmtT-[round(ammo_count(),4)]"
/obj/item/ammo_box/magazine/wt550m9/wtic
name = "wt550 magazine (Incindiary 4.6x30mm)"
icon_state = "46x30mmtI-20"
ammo_type = /obj/item/ammo_casing/c46x30mminc
/obj/item/ammo_box/magazine/wt550m9/wtic/update_icon()
..()
icon_state = "46x30mmtI-[round(ammo_count(),4)]"
/obj/item/ammo_box/magazine/uzim9mm
name = "uzi magazine (9mm)"
icon_state = "uzi9mm-32"
@@ -109,6 +109,11 @@
ammo_type = /obj/item/ammo_casing/shotgun/buckshot
max_ammo = 6
/obj/item/ammo_box/magazine/internal/shot/com/compact
name = "compact combat shotgun internal magazine"
ammo_type = /obj/item/ammo_casing/shotgun/buckshot
max_ammo = 4
/obj/item/ammo_box/magazine/internal/shot/dual
name = "double-barrel shotgun internal magazine"
max_ammo = 2
@@ -375,8 +375,29 @@
pin = /obj/item/device/firing_pin/implant/pindicate
origin_tech = "combat=7;syndicate=6"
// Old Semi-Auto Rifle //
/obj/item/weapon/gun/ballistic/automatic/surplus
name = "Surplus Rifle"
desc = "One of countless obsolete ballistic rifles that still sees use as a cheap deterrent. Uses 10mm ammo and its bulky frame prevents one-hand firing."
origin_tech = "combat=3;materials=2"
icon_state = "surplus"
item_state = "moistnugget"
weapon_weight = WEAPON_HEAVY
mag_type = /obj/item/ammo_box/magazine/m10mm/rifle
fire_delay = 30
burst_size = 1
can_unsuppress = 1
can_suppress = 1
w_class = WEIGHT_CLASS_HUGE
slot_flags = SLOT_BACK
actions_types = list()
/obj/item/weapon/gun/ballistic/automatic/surplus/update_icon()
if(magazine)
icon_state = "surplus"
else
icon_state = "surplus-e"
// Laser rifle (rechargeable magazine) //
@@ -344,6 +344,15 @@
slung = 0
update_icon()
/obj/item/weapon/gun/ballistic/revolver/doublebarrel/improvised/sawn
name = "sawn-off improvised shotgun"
desc = "A single-shot shotgun, better not miss"
icon_state = "ishotgun"
item_state = "gun"
w_class = WEIGHT_CLASS_NORMAL
sawn_state = SAWN_OFF
slot_flags = SLOT_BELT
/obj/item/weapon/gun/ballistic/revolver/reverse //Fires directly at its user... unless the user is a clown, of course.
clumsy_check = 0
@@ -192,6 +192,14 @@
mag_type = /obj/item/ammo_box/magazine/internal/shot/com
w_class = WEIGHT_CLASS_HUGE
/obj/item/weapon/gun/ballistic/shotgun/automatic/combat/compact
name = "compact combat shotgun"
desc = "A compact version of the semi automatic combat shotgun. For close encounters."
icon_state = "cshotgunc"
origin_tech = "combat=4;materials=2"
mag_type = /obj/item/ammo_box/magazine/internal/shot/com/compact
w_class = WEIGHT_CLASS_BULKY
//Dual Feed Shotgun
/obj/item/weapon/gun/ballistic/shotgun/automatic/dual_tube
@@ -1,10 +0,0 @@
diff a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm (rejected hunks)
@@ -203,7 +203,7 @@
range = 4
dismemberment = 20
impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser
- var/mine_range = 4 //mines this many additional tiles
+ var/mine_range = 3 //mines this many additional tiles
/obj/item/projectile/plasma/Initialize()
. = ..()
+2 -2
View File
@@ -453,14 +453,14 @@
/datum/reagents/proc/check_ignoreslow(mob/M)
if(istype(M, /mob))
if(M.reagents.has_reagent("morphine")||M.reagents.has_reagent("ephedrine"))
if(M.reagents.has_reagent("morphine"))
return 1
else
M.status_flags &= ~IGNORESLOWDOWN
/datum/reagents/proc/check_gofast(mob/M)
if(istype(M, /mob))
if(M.reagents.has_reagent("unholywater")||M.reagents.has_reagent("nuka_cola")||M.reagents.has_reagent("stimulants"))
if(M.reagents.has_reagent("unholywater")||M.reagents.has_reagent("nuka_cola")||M.reagents.has_reagent("stimulants")||M.reagents.has_reagent("ephedrine"))
return 1
else
M.status_flags &= ~GOTTAGOFAST
@@ -1,285 +1,183 @@
/obj/machinery/computer/pandemic
name = "PanD.E.M.I.C 2200"
desc = "Used to work with viruses."
density = 1
anchored = 1
density = TRUE
anchored = TRUE
icon = 'icons/obj/chemical.dmi'
icon_state = "mixer0"
circuit = /obj/item/weapon/circuitboard/computer/pandemic
use_power = 1
use_power = TRUE
idle_power_usage = 20
resistance_flags = ACID_PROOF
var/temp_html = ""
var/wait = null
var/obj/item/weapon/reagent_containers/beaker = null
var/wait
var/obj/item/weapon/reagent_containers/beaker
/obj/machinery/computer/pandemic/Initialize()
. = ..()
update_icon()
/obj/machinery/computer/pandemic/proc/GetVirusByIndex(index)
if(beaker && beaker.reagents)
if(beaker.reagents.reagent_list.len)
var/datum/reagent/blood/BL = locate() in beaker.reagents.reagent_list
if(BL)
if(BL.data && BL.data["viruses"])
var/list/viruses = BL.data["viruses"]
return viruses[index]
return null
/obj/machinery/computer/pandemic/Destroy()
QDEL_NULL(beaker)
return ..()
/obj/machinery/computer/pandemic/proc/GetResistancesByIndex(index)
if(beaker && beaker.reagents)
if(beaker.reagents.reagent_list.len)
var/datum/reagent/blood/BL = locate() in beaker.reagents.reagent_list
if(BL)
if(BL.data && BL.data["resistances"])
var/list/resistances = BL.data["resistances"]
return resistances[index]
return null
/obj/machinery/computer/pandemic/proc/get_by_index(thing, index)
if(!beaker || !beaker.reagents)
return
var/datum/reagent/blood/B = locate() in beaker.reagents.reagent_list
if(B && B.data[thing])
return B.data[thing][index]
/obj/machinery/computer/pandemic/proc/GetVirusTypeByIndex(index)
var/datum/disease/D = GetVirusByIndex(index)
/obj/machinery/computer/pandemic/proc/get_virus_id_by_index(index)
var/datum/disease/D = get_by_index("viruses", index)
if(D)
return D.GetDiseaseID()
return null
/obj/machinery/computer/pandemic/proc/replicator_cooldown(waittime)
wait = 1
/obj/machinery/computer/pandemic/proc/get_viruses_data(datum/reagent/blood/B)
. = list()
if(!islist(B.data["viruses"]))
return
var/list/V = B.data["viruses"]
var/index = 1
for(var/virus in V)
var/datum/disease/D = virus
if(!istype(D) || D.visibility_flags & HIDDEN_PANDEMIC)
continue
var/list/this = list()
this["name"] = D.name
if(istype(D, /datum/disease/advance))
var/datum/disease/advance/A = SSdisease.archive_diseases[D.GetDiseaseID()]
if(A.name == "Unknown")
this["can_rename"] = TRUE
this["name"] = A.name
this["is_adv"] = TRUE
this["resistance"] = A.totalResistance()
this["stealth"] = A.totalStealth()
this["stage_speed"] = A.totalStageSpeed()
this["transmission"] = A.totalTransmittable()
this["symptoms"] = list()
for(var/symptom in A.symptoms)
var/datum/symptom/S = symptom
var/list/this_symptom = list()
this_symptom["name"] = S.name
this["symptoms"] += list(this_symptom)
this["index"] = index++
this["agent"] = D.agent
this["description"] = D.desc || "none"
this["spread"] = D.spread_text || "none"
this["cure"] = D.cure_text || "none"
. += list(this)
/obj/machinery/computer/pandemic/proc/get_resistance_data(datum/reagent/blood/B)
. = list()
if(!islist(B.data["resistances"]))
return
var/list/resistances = B.data["resistances"]
for(var/id in resistances)
var/list/this = list()
var/datum/disease/D = SSdisease.archive_diseases[id]
if(D)
this["id"] = id
this["name"] = D.name
. += list(this)
/obj/machinery/computer/pandemic/proc/reset_replicator_cooldown()
wait = FALSE
update_icon()
spawn(waittime)
wait = null
update_icon()
playsound(src.loc, 'sound/machines/ping.ogg', 30, 1)
playsound(loc, 'sound/machines/ping.ogg', 30, 1)
/obj/machinery/computer/pandemic/update_icon()
if(stat & BROKEN)
icon_state = (beaker ? "mixer1_b" : "mixer0_b")
return
icon_state = "mixer[(beaker)?"1":"0"][(powered()) ? "" : "_nopower"]"
icon_state = "mixer[(beaker) ? "1" : "0"][powered() ? "" : "_nopower"]"
if(wait)
cut_overlays()
else
add_overlay("waitlight")
/obj/machinery/computer/pandemic/Topic(href, href_list)
/obj/machinery/computer/pandemic/proc/eject_beaker()
beaker.forceMove(get_turf(src))
beaker = null
update_icon()
/obj/machinery/computer/pandemic/ui_interact(mob/user, ui_key = "main", datum/tgui/ui, force_open = FALSE, datum/tgui/master_ui, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "pandemic", name, 575, 500, master_ui, state)
ui.open()
/obj/machinery/computer/pandemic/ui_data(mob/user)
var/list/data = list()
data["is_ready"] = !wait
if(beaker)
data["has_beaker"] = TRUE
if(!beaker.reagents.total_volume || !beaker.reagents.reagent_list)
data["beaker_empty"] = TRUE
var/datum/reagent/blood/B = locate() in beaker.reagents.reagent_list
if(B)
data["has_blood"] = TRUE
data["blood"] = list()
data["blood"]["dna"] = B.data["blood_DNA"] || "none"
data["blood"]["type"] = B.data["blood_type"] || "none"
data["viruses"] = get_viruses_data(B)
data["resistances"] = get_resistance_data(B)
return data
/obj/machinery/computer/pandemic/ui_act(action, params)
if(..())
return
usr.set_machine(src)
if(!beaker) return
if (href_list["create_vaccine"])
if(!src.wait)
var/obj/item/weapon/reagent_containers/glass/bottle/B = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc)
if(B)
B.pixel_x = rand(-3, 3)
B.pixel_y = rand(-3, 3)
var/path = GetResistancesByIndex(text2num(href_list["create_vaccine"]))
var/vaccine_type = path
var/vaccine_name = "Unknown"
if(!ispath(vaccine_type))
if(SSdisease.archive_diseases[path])
var/datum/disease/D = SSdisease.archive_diseases[path]
if(D)
vaccine_name = D.name
vaccine_type = path
else if(vaccine_type)
var/datum/disease/D = new vaccine_type(0, null)
if(D)
vaccine_name = D.name
if(vaccine_type)
B.name = "[vaccine_name] vaccine bottle"
B.reagents.add_reagent("vaccine", 15, list(vaccine_type))
replicator_cooldown(200)
else
temp_html = "The replicator is not ready yet."
updateUsrDialog()
return
else if (href_list["create_virus_culture"])
if(!wait)
var/type = GetVirusTypeByIndex(text2num(href_list["create_virus_culture"]))//the path is received as string - converting
var/datum/disease/D = null
if(!ispath(type))
D = GetVirusByIndex(text2num(href_list["create_virus_culture"]))
var/datum/disease/advance/A = SSdisease.archive_diseases[D.GetDiseaseID()]
if(A)
D = new A.type(0, A)
else if(type)
if(type in SSdisease.diseases) // Make sure this is a disease
D = new type(0, null)
if(!D)
return
var/name = stripped_input(usr,"Name:","Name the culture",D.name,MAX_NAME_LEN)
if(name == null || wait)
return
var/obj/item/weapon/reagent_containers/glass/bottle/B = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc)
B.icon_state = "bottle3"
B.pixel_x = rand(-3, 3)
B.pixel_y = rand(-3, 3)
replicator_cooldown(50)
var/list/data = list("viruses"=list(D))
B.name = "[name] culture bottle"
B.desc = "A small bottle. Contains [D.agent] culture in synthblood medium."
B.reagents.add_reagent("blood",20,data)
updateUsrDialog()
else
temp_html = "The replicator is not ready yet."
updateUsrDialog()
return
else if (href_list["empty_beaker"])
beaker.reagents.clear_reagents()
updateUsrDialog()
return
else if (href_list["eject"])
beaker.forceMove(get_turf(loc))
beaker = null
icon_state = "mixer0"
updateUsrDialog()
return
else if (href_list["emptyeject_beaker"])
beaker.reagents.clear_reagents()
beaker.forceMove(get_turf(loc))
beaker = null
icon_state = "mixer0"
updateUsrDialog()
return
else if(href_list["clear"])
temp_html = ""
updateUsrDialog()
return
else if(href_list["name_disease"])
var/new_name = stripped_input(usr, "Name the Disease", "New Name", "", MAX_NAME_LEN)
if(!new_name)
return
if(..())
return
var/id = GetVirusTypeByIndex(text2num(href_list["name_disease"]))
if(SSdisease.archive_diseases[id])
switch(action)
if("eject_beaker")
eject_beaker()
. = TRUE
if("empty_beaker")
beaker.reagents.clear_reagents()
. = TRUE
if("empty_eject_beaker")
beaker.reagents.clear_reagents()
eject_beaker()
. = TRUE
if("rename_disease")
var/id = get_virus_id_by_index(text2num(params["index"]))
var/datum/disease/advance/A = SSdisease.archive_diseases[id]
A.AssignName(new_name)
for(var/datum/disease/advance/AD in SSdisease.processing)
AD.Refresh()
updateUsrDialog()
else
usr << browse(null, "window=pandemic")
updateUsrDialog()
return
add_fingerprint(usr)
return
/obj/machinery/computer/pandemic/attack_hand(mob/user)
if(..())
return
user.set_machine(src)
var/dat = ""
if(temp_html)
dat = "[src.temp_html]<BR><BR><A href='?src=\ref[src];clear=1'>Main Menu</A>"
else if(!beaker)
dat += "Please insert beaker.<BR>"
dat += "<A href='?src=\ref[user];mach_close=pandemic'>Close</A>"
else
var/datum/reagents/R = beaker.reagents
var/datum/reagent/blood/Blood = null
for(var/datum/reagent/blood/B in R.reagent_list)
if(B)
Blood = B
break
if(!R.total_volume||!R.reagent_list.len)
dat += "The beaker is empty<BR>"
else if(!Blood)
dat += "No blood sample found in beaker."
else if(!Blood.data)
dat += "No blood data found in beaker."
else
dat += "<h3>Blood sample data:</h3>"
dat += "<b>Blood DNA:</b> [(Blood.data["blood_DNA"]||"none")]<BR>"
dat += "<b>Blood Type:</b> [(Blood.data["blood_type"]||"none")]<BR>"
if(Blood.data["viruses"])
var/list/vir = Blood.data["viruses"]
if(vir.len)
var/i = 0
for(var/datum/disease/D in Blood.data["viruses"])
i++
if(!(D.visibility_flags & HIDDEN_PANDEMIC))
if(istype(D, /datum/disease/advance))
var/datum/disease/advance/A = D
D = SSdisease.archive_diseases[A.GetDiseaseID()]
if(D && D.name == "Unknown")
dat += "<b><a href='?src=\ref[src];name_disease=[i]'>Name Disease</a></b><BR>"
if(!D)
CRASH("We weren't able to get the advance disease from the archive.")
dat += "<b>Disease Agent:</b> [D?"[D.agent] - <A href='?src=\ref[src];create_virus_culture=[i]'>Create virus culture bottle</A>":"none"]<BR>"
dat += "<b>Common name:</b> [(D.name||"none")]<BR>"
dat += "<b>Description: </b> [(D.desc||"none")]<BR>"
dat += "<b>Spread:</b> [(D.spread_text||"none")]<BR>"
dat += "<b>Possible cure:</b> [(D.cure_text||"none")]<BR><BR>"
if(istype(D, /datum/disease/advance))
var/datum/disease/advance/A = D
dat += "<b>Stealth:</b> [(A.totalStealth())]<BR>"
dat += "<b>Resistance:</b> [(A.totalResistance())]<BR>"
dat += "<b>Stage Speed:</b> [(A.totalStageSpeed())]<BR>"
dat += "<b>Transmission:</b> [(A.totalTransmittable())]<BR><BR>"
dat += "<b>Symptoms:</b> "
var/english_symptoms = list()
for(var/datum/symptom/S in A.symptoms)
english_symptoms += S.name
dat += english_list(english_symptoms)
else
dat += "No detectable virus in the sample."
else
dat += "No detectable virus in the sample."
dat += "<BR><b>Contains antibodies to:</b> "
if(Blood.data["resistances"])
var/list/res = Blood.data["resistances"]
if(res.len)
dat += "<ul>"
var/i = 0
for(var/type in Blood.data["resistances"])
i++
var/disease_name = "Unknown"
if(!ispath(type))
var/datum/disease/advance/A = SSdisease.archive_diseases[type]
if(A)
disease_name = A.name
else
var/datum/disease/D = new type(0, null)
disease_name = D.name
dat += "<li>[disease_name] - <A href='?src=\ref[src];create_vaccine=[i]'>Create vaccine bottle</A></li>"
dat += "</ul><BR>"
else
dat += "nothing<BR>"
else
dat += "nothing<BR>"
dat += "<BR><A href='?src=\ref[src];eject=1'>Eject beaker</A>[((R.total_volume&&R.reagent_list.len) ? "-- <A href='?src=\ref[src];empty_beaker=1'>Empty beaker</A>":"")]"
dat += "[((R.total_volume&&R.reagent_list.len) ? "-- <A href='?src=\ref[src];emptyeject_beaker=1'>Empty and Eject beaker</A>":"")]<BR>"
dat += "<A href='?src=\ref[user];mach_close=pandemic'>Close</A>"
user << browse("<TITLE>[src.name]</TITLE><BR>[dat]", "window=pandemic;size=575x400")
onclose(user, "pandemic")
return
if(A)
var/new_name = stripped_input(usr, "Name the disease", "New name", "", MAX_NAME_LEN)
if(!new_name || ..())
return
A.AssignName(new_name)
for(var/datum/disease/advance/AD in SSdisease.processing)
AD.Refresh()
. = TRUE
if("create_culture_bottle")
var/id = get_virus_id_by_index(text2num(params["index"]))
var/datum/disease/advance/A = new(FALSE, SSdisease.archive_diseases[id])
var/list/data = list("viruses" = list(A))
var/obj/item/weapon/reagent_containers/glass/bottle/B = new(get_turf(src))
B.name = "[A.name] culture bottle"
B.desc = "A small bottle. Contains [A.agent] culture in synthblood medium."
B.reagents.add_reagent("blood", 20, data)
wait = TRUE
update_icon()
addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 50)
. = TRUE
if("create_vaccine_bottle")
var/index = params["index"]
var/datum/disease/D = SSdisease.archive_diseases[index]
var/obj/item/weapon/reagent_containers/glass/bottle/B = new(get_turf(src))
B.name = "[D.name] vaccine bottle"
B.reagents.add_reagent("vaccine", 15, list(index))
wait = TRUE
update_icon()
addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 200)
. = TRUE
/obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/reagent_containers) && (I.container_type & OPENCONTAINER))
. = 1 //no afterattack
. = TRUE //no afterattack
if(stat & (NOPOWER|BROKEN))
return
if(beaker)
@@ -288,15 +186,15 @@
if(!user.drop_item())
return
beaker = I
beaker.loc = src
beaker = I
beaker.forceMove(src)
to_chat(user, "<span class='notice'>You add the beaker to the machine.</span>")
updateUsrDialog()
icon_state = "mixer1"
update_icon()
else
return ..()
/obj/machinery/computer/pandemic/on_deconstruction()
if(beaker)
beaker.loc = get_turf(src)
..()
beaker.forceMove(get_turf(src))
beaker = null
. = ..()
@@ -160,6 +160,12 @@
var/obj/item/toy/carpplushie/dehy_carp/dehy = O
dehy.Swell() // Makes a carp
else if(istype(O, /obj/item/stack/sheet/hairlesshide))
var/obj/item/stack/sheet/hairlesshide/HH = O
var/obj/item/stack/sheet/wetleather/WL = new(get_turf(HH))
WL.amount = HH.amount
qdel(HH)
/*
* Water reaction to a mob
*/
@@ -367,11 +373,15 @@
if(ishuman(M))
var/mob/living/carbon/human/N = M
if(N.dna.species.id == "human") // If they're human, turn em to the "orange" race, and give em spiky black hair
N.hair_style = "Spiky"
N.facial_hair_style = "Shaved"
N.facial_hair_color = "000"
N.hair_color = "000"
if(!(HAIR in N.dna.species.species_traits)) //No hair? No problem!
N.dna.species.species_traits += HAIR
if(N.dna.species.use_skintones)
N.skin_tone = "orange"
N.hair_style = "Spiky"
N.hair_color = "000"
if(MUTCOLORS in N.dna.species.species_traits) //Aliens with custom colors simply get turned orange
else if(MUTCOLORS in N.dna.species.species_traits) //Aliens with custom colors simply get turned orange
N.dna.features["mcolor"] = "f80"
N.regenerate_icons()
if(prob(7))
@@ -380,7 +390,7 @@
else
M.visible_message("<b>[M]</b> flexes [M.p_their()] arms.")
if(prob(10))
M.say(pick("Check these sweet biceps bro!", "Deal with it.", "CHUG! CHUG! CHUG! CHUG!", "Winning!", "NERDS!", "My name is John and I hate every single one of you."))
M.say(pick("Shit was SO cash.", "You are everything bad in the world.", "What sports do you play, other than 'jack off to naked drawn Japanese people?'", "Dont be a stranger. Just hit me with your best shot.", "My name is John and I hate every single one of you."))
..()
return
@@ -1126,7 +1136,7 @@
/datum/reagent/nitrous_oxide/reaction_mob(mob/M, method=TOUCH, reac_volume)
if(method == VAPOR)
M.drowsyness += max(round(reac_volume, 1), 2)
/datum/reagent/nitrous_oxide/on_mob_life(mob/living/M)
M.drowsyness += 2
if(ishuman(M))
+4 -3
View File
@@ -104,11 +104,12 @@
if(!operating)
return
use_power(100)
affecting = loc.contents - src // moved items will be all in loc
sleep(1)
addtimer(CALLBACK(src, .proc/convey, affecting), 1)
/obj/machinery/conveyor/proc/convey(list/affecting)
for(var/atom/movable/A in affecting)
if(A.loc == loc)
if((A.loc == loc) && A.has_gravity())
A.ConveyorMove(movedir)
// attack with item, place item on conveyor
+7 -3
View File
@@ -83,14 +83,18 @@
//sometimes we want to ignore that we don't have the required amount of legs.
/mob/proc/get_leg_ignore()
return 0
return FALSE
/mob/living/carbon/alien/larva/get_leg_ignore()
return 1
return TRUE
/mob/living/carbon/human/get_leg_ignore()
if(movement_type & FLYING)
return 1
return TRUE
var/obj/item/weapon/tank/jetpack/J = get_jetpack()
if(J && J.on && !has_gravity())
return TRUE
return FALSE
/mob/living/proc/get_missing_limbs()
return list()
+2 -2
View File
@@ -914,8 +914,8 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
cost = 3
/datum/uplink_item/device_tools/military_belt
name = "Military Belt"
desc = "A robust seven-slot red belt that is capable of holding all manner of tatical equipment."
name = "Chest Rig"
desc = "A robust seven-slot set of webbing that is capable of holding all manner of tatical equipment."
item = /obj/item/weapon/storage/belt/military
cost = 1
exclude_modes = list(/datum/game_mode/nuclear)
@@ -0,0 +1,4 @@
author: "Lzimann"
delete-after: True
changes:
- rscadd: "Pandemic is now tgui!"
@@ -0,0 +1,5 @@
author: "Joan"
delete-after: True
changes:
- tweak: "Resonator fields now visually show how long they have until they burst."
- bugfix: "Hitting a legion skull with a resonator will now produce a field."
@@ -0,0 +1,4 @@
author: "Steelpoint"
delete-after: True
changes:
- rscadd: "The Warden's Cycler Shotgun has been replaced with a Compact Combat Shotgun. A unique weapon, it can fit in armour slots but at the sacrifice of a smaller ammo capacity of four shells."
@@ -0,0 +1,4 @@
author: "CitadelStationBot"
delete-after: True
changes:
- bugfix: "Spessmen seems to have stopped suffering from the mental condition that makes them believe they can't move fast if they have only one leg, even if they're in space and using a jetpack!"
@@ -0,0 +1,4 @@
author: "That Really Good Soda Flavor"
delete-after: True
changes:
- bugfix: "Martial arts are no longer lost when mind-swapping, cloning, moving your brain, et cetera."
@@ -0,0 +1,7 @@
author: "coiax"
delete-after: True
changes:
- rscadd: "Galactic Common has been added to silicon's internal language
database, meaning even if a cyborg is created from someone who
previously did not know Galactic Common, they will be able to speak it
as a silicon."
@@ -0,0 +1,4 @@
author: "ma44"
delete-after: True
changes:
- rscadd: "Reports of syndicate base on lavaland has been outfitted with a state of the art donksoft toy weapon dispenser."
@@ -0,0 +1,4 @@
author: "Joan"
delete-after: True
changes:
- tweak: "Chasms will glow dimly, like lava."
@@ -0,0 +1,4 @@
author: "Steelpoint"
delete-after: True
changes:
- rscadd: "Auto Rifle alt ammo mags (AP, Incendiary, Uranium Tipped) now have a coloured stripe to denote them."
@@ -0,0 +1,6 @@
author: "Joan"
delete-after: True
changes:
- rscdel: "Nanotrasen has taken a lower bid for their meson suppliers, and meson scanners will no longer display terrain layouts while on the planet."
- tweak: "However, they have discovered that, with some tweaks, mineral scanners will no longer actually require you to be wearing mesons."
- tweak: "The cheaper mesons will not completely remove reliance on light."
@@ -0,0 +1,4 @@
author: "That Really Good Soda Flavor"
delete-after: True
changes:
- bugfix: "Fixed a bug where paper bins could swallow up pens into the void."
+10
View File
@@ -0,0 +1,10 @@
author: "Robustin"
delete-after: True
changes:
- rscadd: "Gang influence is now decentralized, each gangster has their own influence that they can increase by spraying (and protecting) their tags and new influence-enhancing bling."
- rscadd: "Gang uniforms are now created based on your gang's color and can be purchased by any gang member. They will increase the wearer's influence and provide protection, but will make it fairly obvious which gang you belong to."
- rscadd: "Gangs have access to a new surplus rifle; it is a semi-automatic rifle that is very bulky and has a very low rate of fire. Gang members can buy this gun for just 8 influence."
- rscadd: "Gangs have access to the new machine gun turret; it unleashes a volley of bullets with an extended view range. It does not run out of ammo, but a significant delay between volleys and its stationary nature leaves the gunner vulnerable to flanking and return fire. Holding down the trigger will allow you to aim the gun while firing. It will cost gangs 50 influence."
- rscadd: "The sawn-off improvised shotgun is now available to gangs for 6 influence. With buckshot shells being easy to produce or purchase, this gun gives the most \"bang for your buck\" but its single-shell capacity will leave you vulnerable during a pitched gunfight."
- rscadd: "The Wetwork boots give gangs access to a lightly armored noslip variant."
- tweak: "The armored gang outfits are now slightly more resistant to ballistic and bomb damage"
@@ -0,0 +1,4 @@
author: "Tacolizard"
delete-after: True
changes:
- tweak: "Station based armour is slightly more descriptive of what it does."
@@ -0,0 +1,4 @@
author: "That Really Good Soda Flavor"
delete-after: True
changes:
- tweak: "Changed spray tan overdoses to be more realistic."
@@ -0,0 +1,5 @@
author: "QualityVan"
delete-after: True
changes:
- rscadd: "Hairless hides now become wet when exposed to water"
- rscadd: "You can microwave wet leather to dry it"
@@ -0,0 +1,4 @@
author: "Steelpoint"
delete-after: True
changes:
- rscadd: "Boxstation armoury weapon racks now have glass panes to help prevent the weapons easily flying out of a breached hull."
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Some files were not shown because too many files have changed in this diff Show More