Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into turfs

# Conflicts:
#	code/game/objects/items.dm
#	code/modules/power/cable.dm
#	icons/mob/inhands/items_lefthand.dmi
#	icons/mob/inhands/items_righthand.dmi
#	icons/obj/lighting.dmi
#	paradise.dme
This commit is contained in:
Mark van Alphen
2019-04-30 19:26:17 +02:00
153 changed files with 1935 additions and 1105 deletions
+21
View File
@@ -100,6 +100,10 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
var/trip_walksafe = TRUE
var/trip_tiles = 0
//Tooltip vars
var/in_inventory = FALSE //is this item equipped into an inventory slot or hand of a mob?
var/tip_timer = 0
/obj/item/New()
..()
for(var/path in actions_types)
@@ -340,11 +344,13 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
A.Remove(user)
if(flags & DROPDEL)
qdel(src)
in_inventory = FALSE
SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user)
// called just as an item is picked up (loc is not yet changed)
/obj/item/proc/pickup(mob/user)
SEND_SIGNAL(src, COMSIG_ITEM_PICKUP, user)
in_inventory = TRUE
return TRUE
// called when this item is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
@@ -374,6 +380,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
var/datum/action/A = X
if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
in_inventory = TRUE
/obj/item/proc/item_action_slot_check(slot, mob/user)
return 1
@@ -532,6 +539,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
if(callback) //call the original callback
. = callback.Invoke()
throw_speed = initial(throw_speed) //explosions change this.
in_inventory = FALSE
/obj/item/proc/pwr_drain()
return 0 // Process Kill
@@ -585,3 +593,16 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
return
var/mob/owner = loc
owner.regenerate_icons()
/obj/item/proc/openTip(location, control, params, user)
openToolTip(user, src, params, title = name, content = "[desc]", theme = "")
/obj/item/MouseEntered(location, control, params)
if(in_inventory)
var/timedelay = 5
var/user = usr
tip_timer = addtimer(CALLBACK(src, .proc/openTip, location, control, params, user), timedelay, TIMER_STOPPABLE)
/obj/item/MouseExited()
deltimer(tip_timer) //delete any in-progress timer if the mouse is moved off the item before it finishes
closeToolTip(usr)
@@ -307,6 +307,9 @@
brightness_on = 7
icon_state = "torch"
item_state = "torch"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
light_color = LIGHT_COLOR_ORANGE
on_damage = 10
/obj/item/flashlight/slime
+100 -86
View File
@@ -1,3 +1,7 @@
#define DISCONNECTED 0
#define CLAMPED_OFF 1
#define OPERATING 2
// Powersink - used to drain station power
/obj/item/powersink
@@ -13,28 +17,55 @@
throw_range = 2
materials = list(MAT_METAL=750)
origin_tech = "powerstorage=5;syndicate=5"
var/drain_rate = 1600000 // amount of power to drain per tick
var/apc_drain_rate = 50 // Max. amount drained from single APC. In Watts.
var/dissipation_rate = 20000 // Passive dissipation of drained power. In Watts.
var/power_drained = 0 // Amount of power drained.
var/max_power = 1e10 // Detonation point.
var/mode = 0 // 0 = off, 1=clamped (off), 2=operating
var/drained_this_tick = 0 // This is unfortunately necessary to ensure we process powersinks BEFORE other machinery such as APCs.
var/admins_warned = 0 // stop spam, only warn the admins once that we are about to go boom
var/drain_rate = 2000000 // amount of power to drain per tick
var/power_drained = 0 // has drained this much power
var/max_power = 6e8 // maximum power that can be drained before exploding
var/mode = 0 // 0 = off, 1=clamped (off), 2=operating
var/admins_warned = FALSE // stop spam, only warn the admins once that we are about to boom
var/datum/powernet/PN // Our powernet
var/obj/structure/cable/attached // the attached cable
/obj/item/powersink/Destroy()
STOP_PROCESSING(SSobj, src)
GLOB.processing_power_items.Remove(src)
PN = null
attached = null
return ..()
/obj/item/powersink/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/screwdriver))
if(mode == 0)
/obj/item/powersink/update_icon()
icon_state = "powersink[mode == OPERATING]"
/obj/item/powersink/proc/set_mode(value)
if(value == mode)
return
switch(value)
if(DISCONNECTED)
attached = null
if(mode == OPERATING)
STOP_PROCESSING(SSobj, src)
anchored = FALSE
density = FALSE
if(CLAMPED_OFF)
if(!attached)
return
if(mode == OPERATING)
STOP_PROCESSING(SSobj, src)
anchored = TRUE
density = TRUE
if(OPERATING)
if(!attached)
return
START_PROCESSING(SSobj, src)
anchored = TRUE
density = TRUE
mode = value
update_icon()
set_light(0)
/obj/item/powersink/attackby(obj/item/I, mob/user)
if(isscrewdriver(I))
if(mode == DISCONNECTED)
var/turf/T = loc
if(isturf(T) && !T.intact)
attached = locate() in T
@@ -42,98 +73,81 @@
to_chat(user, "No exposed cable here to attach to.")
return
else
anchored = 1
mode = 1
src.visible_message("<span class='notice'>[user] attaches [src] to the cable!</span>")
set_mode(CLAMPED_OFF)
visible_message("<span class='notice'>[user] attaches [src] to the cable!</span>")
message_admins("Power sink activated by [key_name_admin(user)] at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
log_game("Power sink activated by [key_name(user)] at ([x],[y],[z])")
return
else
to_chat(user, "Device must be placed over an exposed cable to attach to it.")
return
else
if(mode == 2)
STOP_PROCESSING(SSobj, src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite
GLOB.processing_power_items.Remove(src)
anchored = 0
mode = 0
set_mode(DISCONNECTED)
src.visible_message("<span class='notice'>[user] detaches [src] from the cable!</span>")
set_light(0)
icon_state = "powersink0"
return
else
..()
return ..()
/obj/item/powersink/attack_ai()
return
/obj/item/powersink/attack_hand(var/mob/user)
switch(mode)
if(0)
if(DISCONNECTED)
..()
if(1)
src.visible_message("<span class='notice'>[user] activates [src]!</span>")
mode = 2
icon_state = "powersink1"
START_PROCESSING(SSobj, src)
GLOB.processing_power_items.Add(src)
if(2) //This switch option wasn't originally included. It exists now. --NeoFite
src.visible_message("<span class='notice'>[user] deactivates [src]!</span>")
mode = 1
set_light(0)
icon_state = "powersink0"
STOP_PROCESSING(SSobj, src)
GLOB.processing_power_items.Remove(src)
/obj/item/powersink/pwr_drain()
if(!attached)
return 0
if(drained_this_tick)
return 1
drained_this_tick = 1
var/drained = 0
if(!PN)
return 1
set_light(12)
PN.trigger_warning()
// found a powernet, so drain up to max power from it
drained = PN.draw_power(drain_rate)
// if tried to drain more than available on powernet
// now look for APCs and drain their cells
if(drained < drain_rate)
for(var/obj/machinery/power/terminal/T in PN.nodes)
// Enough power drained this tick, no need to torture more APCs
if(drained >= drain_rate)
break
if(istype(T.master, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = T.master
if(A.operating && A.cell)
A.cell.charge = max(0, A.cell.charge - apc_drain_rate)
drained += apc_drain_rate
if(A.charging == 2) // If the cell was full
A.charging = 1 // It's no longer full
power_drained += drained
return 1
if(CLAMPED_OFF)
user.visible_message( \
"[user] activates \the [src]!", \
"<span class='notice'>You activate \the [src].</span>",
"<span class='italics'>You hear a click.</span>")
message_admins("Power sink activated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_VERBOSEJMP(src)]")
log_game("Power sink activated by [key_name(user)] at [AREACOORD(src)]")
set_mode(OPERATING)
if(OPERATING)
user.visible_message( \
"[user] deactivates \the [src]!", \
"<span class='notice'>You deactivate \the [src].</span>",
"<span class='italics'>You hear a click.</span>")
set_mode(CLAMPED_OFF)
/obj/item/powersink/process()
drained_this_tick = 0
power_drained -= min(dissipation_rate, power_drained)
if(!attached)
set_mode(DISCONNECTED)
return
var/datum/powernet/PN = attached.powernet
if(PN)
set_light(5)
// found a powernet, so drain up to max power from it
var/drained = min (drain_rate, attached.newavail())
attached.add_delayedload(drained)
power_drained += drained
// if tried to drain more than available on powernet
// now look for APCs and drain their cells
if(drained < drain_rate)
for(var/obj/machinery/power/terminal/T in PN.nodes)
if(istype(T.master, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = T.master
if(A.operating && A.cell)
A.cell.charge = max(0, A.cell.charge - 50)
power_drained += 50
if(A.charging == 2) // If the cell was full
A.charging = 1 // It's no longer full
if(drained >= drain_rate)
break
if(power_drained > max_power * 0.98)
if(!admins_warned)
admins_warned = 1
if (!admins_warned)
admins_warned = TRUE
message_admins("Power sink at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>) is 95% full. Explosion imminent.")
playsound(src, 'sound/effects/screech.ogg', 100, 1, 1)
if(power_drained >= max_power)
STOP_PROCESSING(SSobj, src)
explosion(src.loc, 4,8,16,32)
qdel(src)
return
if(attached && attached.powernet)
PN = attached.powernet
else
PN = null
#undef DISCONNECTED
#undef CLAMPED_OFF
#undef OPERATING
+3 -3
View File
@@ -54,7 +54,7 @@
to_chat(user, "There are [amount] [singular_name]\s in the stack.")
else
to_chat(user, "There are [amount] [name]\s in the stack.")
to_chat(user,"<span class='notice'>Ctrl-Shift-click to take a custom amount.</span>")
to_chat(user,"<span class='notice'>Alt-click to take a custom amount.</span>")
/obj/item/stack/proc/add(newamount)
amount += newamount
@@ -263,7 +263,7 @@
else
..()
/obj/item/stack/CtrlShiftClick(mob/living/user)
/obj/item/stack/AltClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
@@ -276,7 +276,7 @@
//get amount from user
var/min = 0
var/max = get_amount()
var/stackmaterial = round(input(user, "How many sheets do you wish to take out of this stack? (Maximum: [max])") as num)
var/stackmaterial = round(input(user, "How many sheets do you wish to take out of this stack? (Maximum: [max])") as null|num)
if(stackmaterial == null || stackmaterial <= min || stackmaterial > get_amount())
return
change_stack(user,stackmaterial)
@@ -98,6 +98,8 @@
//alt titles are handled a bit weirdly in order to unobtrusively integrate into existing ID system
var/assignment = null //can be alt title or the actual job
var/rank = null //actual job
var/owner_uid
var/owner_ckey
var/dorm = 0 // determines if this ID has claimed a dorm already
var/sex
@@ -195,6 +197,19 @@
jobnamedata += " (" + assignment + ")"
return jobnamedata
/obj/item/card/id/proc/getPlayer()
if(owner_uid)
var/mob/living/carbon/human/H = locateUID(owner_uid)
if(istype(H) && H.ckey == owner_ckey)
return H
owner_uid = null
if(owner_ckey)
for(var/mob/M in GLOB.player_list)
if(M.ckey && M.ckey == owner_ckey)
owner_uid = M.UID()
return M
owner_ckey = null
/obj/item/card/id/proc/is_untrackable()
return untrackable
+3 -4
View File
@@ -112,10 +112,9 @@
/obj/item/dice/attack_self(mob/user as mob)
diceroll(user)
/obj/item/dice/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
if(!..())
return
diceroll(thrower)
/obj/item/dice/throw_impact(atom/target)
diceroll(thrownby)
. = ..()
/obj/item/dice/proc/diceroll(mob/user)
result = rand(1, sides)
@@ -152,8 +152,14 @@
breakouttime = 35//easy to apply, easy to break out of
gender = NEUTER
origin_tech = "engineering=3;combat=1"
hitsound = 'sound/effects/snap.ogg'
var/weaken = 0
/obj/item/restraints/legcuffs/bola/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
playsound(loc,'sound/weapons/bolathrow.ogg', 50, TRUE)
if(!..())
return
/obj/item/restraints/legcuffs/bola/throw_impact(atom/hit_atom)
if(..() || !iscarbon(hit_atom))//if it gets caught or the target can't be cuffed,
return//abort
@@ -166,6 +172,7 @@
feedback_add_details("handcuffs","B")
to_chat(C, "<span class='userdanger'>[src] ensnares you!</span>")
C.Weaken(weaken)
playsound(loc, hitsound, 50, TRUE)
/obj/item/restraints/legcuffs/bola/tactical //traitor variant
name = "reinforced bola"
@@ -28,6 +28,22 @@
else
has_extinguisher = new/obj/item/extinguisher
/obj/structure/extinguisher_cabinet/examine(mob/user)
..()
to_chat(user, "<span class='notice'>Alt-click to [opened ? "close":"open"] it.</span>")
/obj/structure/extinguisher_cabinet/AltClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user))
return
if(!iscarbon(usr))
return
playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
opened = !opened
update_icon()
/obj/structure/extinguisher_cabinet/Destroy()
QDEL_NULL(has_extinguisher)
return ..()
@@ -37,11 +53,16 @@
return
if(istype(O, /obj/item/extinguisher))
if(!has_extinguisher && opened)
if(!user.drop_item())
return
user.drop_item(O)
contents += O
has_extinguisher = O
update_icon()
to_chat(user, "<span class='notice'>You place [O] in [src].</span>")
return TRUE
else
playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
opened = !opened
else if(istype(O, /obj/item/weldingtool))
if(has_extinguisher)
@@ -65,6 +86,7 @@
new material_drop(T)
qdel(src)
else
playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
opened = !opened
update_icon()
@@ -81,21 +103,27 @@
to_chat(user, "<span class='notice'>You try to move your [temp.name], but cannot!")
return
if(has_extinguisher)
if(icon_state == "extinguisher_closed")
playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
user.put_in_hands(has_extinguisher)
to_chat(user, "<span class='notice'>You take [has_extinguisher] from [src].</span>")
has_extinguisher = null
opened = 1
else
playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
opened = !opened
update_icon()
/obj/structure/extinguisher_cabinet/attack_tk(mob/user)
if(has_extinguisher)
if(icon_state == "extinguisher_closed")
playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
has_extinguisher.loc = loc
to_chat(user, "<span class='notice'>You telekinetically remove [has_extinguisher] from [src].</span>")
has_extinguisher = null
opened = 1
else
playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
opened = !opened
update_icon()
+2 -2
View File
@@ -273,8 +273,8 @@
var/obj/structure/cable/C = T.get_cable_node()
if(C)
playsound(loc, 'sound/magic/lightningshock.ogg', 100, 1, extrarange = 5)
tesla_zap(src, 3, C.powernet.avail * 0.01) //Zap for 1/100 of the amount of power. At a million watts in the grid, it will be as powerful as a tesla revolver shot.
C.powernet.load += C.powernet.avail * 0.0375 // you can gain up to 3.5 via the 4x upgrades power is halved by the pole so thats 2x then 1X then .5X for 3.5x the 3 bounces shock.
tesla_zap(src, 3, C.newavail() * 0.01) //Zap for 1/100 of the amount of power. At a million watts in the grid, it will be as powerful as a tesla revolver shot.
C.add_delayedload(C.newavail() * 0.0375) // you can gain up to 3.5 via the 4x upgrades power is halved by the pole so thats 2x then 1X then .5X for 3.5x the 3 bounces shock.
return ..()
/obj/structure/grille/broken // Pre-broken grilles for map placement