diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index fcc2d0c91b9..72937092c4f 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -51,6 +51,7 @@ var/global/list/facial_hair_styles_list = list() //stores /datum/sprite_accessor
var/global/list/facial_hair_styles_male_list = list()
var/global/list/facial_hair_styles_female_list = list()
var/global/list/skin_styles_female_list = list() //unused
+var/global/list/body_marking_styles_list = list() //stores /datum/sprite_accessory/marking indexed by name
//Underwear
var/datum/category_collection/underwear/global_underwear = new()
@@ -141,6 +142,12 @@ var/global/list/string_slot_flags = list(
facial_hair_styles_male_list += H.name
facial_hair_styles_female_list += H.name
+ //Body markings - Initialise all /datum/sprite_accessory/marking into an list indexed by marking name
+ paths = typesof(/datum/sprite_accessory/marking) - /datum/sprite_accessory/marking
+ for(var/path in paths)
+ var/datum/sprite_accessory/marking/M = new path()
+ body_marking_styles_list[M.name] = M
+
//Surgery Steps - Initialize all /datum/surgery_step into a list
paths = typesof(/datum/surgery_step)-/datum/surgery_step
for(var/T in paths)
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index e30de18f4e2..e80dcb72270 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -84,6 +84,7 @@ var/global/list/datum/dna/gene/dna_genes[0]
// New stuff
var/species = "Human"
+ var/list/body_markings = list()
// Make a copy of this strand.
// USE THIS WHEN COPYING STUFF OR YOU'LL GET CORRUPTION!
@@ -93,6 +94,7 @@ var/global/list/datum/dna/gene/dna_genes[0]
new_dna.b_type=b_type
new_dna.real_name=real_name
new_dna.species=species
+ new_dna.body_markings=body_markings.Copy()
for(var/b=1;b<=DNA_SE_LENGTH;b++)
new_dna.SE[b]=SE[b]
if(b<=DNA_UI_LENGTH)
@@ -152,6 +154,11 @@ var/global/list/datum/dna/gene/dna_genes[0]
SetUIValueRange(DNA_UI_HAIR_STYLE, hair, hair_styles_list.len, 1)
SetUIValueRange(DNA_UI_BEARD_STYLE, beard, facial_hair_styles_list.len,1)
+ body_markings.Cut()
+ for(var/obj/item/organ/external/E in character.organs)
+ if(E.markings.len)
+ body_markings[E.organ_tag] = E.markings.Copy()
+
UpdateUI()
// Set a DNA UI block's raw value.
diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm
index 98acc1d335d..2287d3477c9 100644
--- a/code/game/dna/dna2_helpers.dm
+++ b/code/game/dna/dna2_helpers.dm
@@ -156,6 +156,13 @@
else
H.gender = MALE
+ //Body markings
+ for(var/tag in dna.body_markings)
+ var/obj/item/organ/external/E = H.organs_by_name[tag]
+ if(E)
+ var/list/marklist = dna.body_markings[tag]
+ E.markings = marklist.Copy()
+
//Hair
var/hair = dna.GetUIValueRange(DNA_UI_HAIR_STYLE,hair_styles_list.len)
if((0 < hair) && (hair <= hair_styles_list.len))
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 43497523708..6dd278dc63b 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -8,7 +8,7 @@ obj/machinery/recharger
idle_power_usage = 4
active_power_usage = 40000 //40 kW
var/obj/item/charging = null
- var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/device/laptop, /obj/item/weapon/cell, /obj/item/device/flashlight, /obj/item/device/electronic_assembly)
+ var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/device/laptop, /obj/item/weapon/cell, /obj/item/device/flashlight, /obj/item/device/electronic_assembly, /obj/item/weapon/weldingtool/electric)
var/icon_state_charged = "recharger2"
var/icon_state_charging = "recharger1"
var/icon_state_idle = "recharger0" //also when unpowered
@@ -33,19 +33,19 @@ obj/machinery/recharger
if(allowed)
if(charging)
- user << "\A [charging] is already charging here."
+ to_chat(user, "\A [charging] is already charging here.")
return
// Checks to make sure he's not in space doing it, and that the area got proper power.
if(!powered())
- user << "The [name] blinks red as you try to insert the item!"
+ to_chat(user, "The [name] blinks red as you try to insert the item!")
return
if(istype(G, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/E = G
if(!E.power_supply)
- user << "Your gun has no power cell."
+ to_chat(user, "Your gun has no power cell.")
return
if(E.self_recharge)
- user << "Your gun has no recharge port."
+ to_chat(user, "Your gun has no recharge port.")
return
if(istype(G, /obj/item/weapon/gun/energy/staff))
return
@@ -65,16 +65,22 @@ obj/machinery/recharger
if(!assembly.battery)
to_chat(user, "The assembly doesn't have a power cell.")
return
+ if(istype(G, /obj/item/weapon/weldingtool/electric))
+ var/obj/item/weapon/weldingtool/electric/welder = G
+ if(!welder.power_supply)
+ to_chat(user, "Your welder has no power cell.")
+ return
+
user.drop_item()
G.loc = src
charging = G
update_icon()
else if(portable && istype(G, /obj/item/weapon/wrench))
if(charging)
- user << "Remove [charging] first!"
+ to_chat(user, "Remove [charging] first!")
return
anchored = !anchored
- user << "You [anchored ? "attached" : "detached"] the recharger."
+ to_chat(user, "You [anchored ? "attached" : "detached"] the recharger.")
playsound(loc, 'sound/items/Ratchet.ogg', 75, 1)
else if(default_deconstruction_screwdriver(user, G))
return
@@ -208,8 +214,8 @@ obj/machinery/recharger
name = "wall recharger"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "wrecharger0"
- active_power_usage = 25000 //25 kW , It's more specialized than the standalone recharger (guns and batons only) so make it more powerful
- allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/weapon/cell/device)
+ active_power_usage = 25000 //25 kW , It's more specialized than the standalone recharger (guns, batons, and flashlights only) so make it more powerful
+ allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/device/flashlight, /obj/item/weapon/cell/device)
icon_state_charged = "wrecharger2"
icon_state_charging = "wrecharger1"
icon_state_idle = "wrecharger0"
diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm
index a4b0a02c5ab..73efffe121b 100644
--- a/code/game/objects/items/devices/defib.dm
+++ b/code/game/objects/items/devices/defib.dm
@@ -8,6 +8,8 @@
var/state //0 off, 1 open, 2 working, 3 dead
var/uses = 2 //Calculates initial uses based on starting cell size
+ var/use_on_synthetic = 0 //If 1, this is only useful on FBPs, if 0, this is only useful on fleshies
+ var/pad_name = "defib pads" //Just the name given for some cosmetic things
var/chance = 75 //Percent chance of working
var/charge_cost //Set in New() based on uses
var/obj/item/weapon/cell/cell //The size is mostly irrelevant, see 'uses'
@@ -32,13 +34,31 @@
if(istype(onto) && Adjacent(usr) && !usr.restrained() && !usr.stat)
var/mob/living/carbon/human/user = usr
//<--Feel free to code clothing checks right here
- user.visible_message("[user] begins applying defib pads to [onto].",
- "You begin applying defib pads to [onto].")
+ if(can_defib(onto))
+ user.visible_message("[user] begins applying [pad_name] to [onto].",
+ "You begin applying [pad_name] to [onto].")
if(do_after(user, 100, onto))
patient = onto
statechange(1,patient)
- user.visible_message("[user] applies defib pads to [onto].",
- "You finish applying defib pads to [onto].")
+ user.visible_message("[user] applies [pad_name] to [onto].",
+ "You finish applying [pad_name] to [onto].")
+
+
+//can_defib() check is where all of the qualifying conditions should go
+//Could probably toss in checks here for damage, organs, etc, but for now I'll leave it as just this
+/obj/item/device/defib_kit/proc/can_defib(var/mob/living/carbon/human/target)
+ var/mob/living/carbon/human/user = usr
+ if(use_on_synthetic && !target.isSynthetic())
+ to_chat(user, "[src] isn't designed for organics!")
+ return 0
+ else if(!use_on_synthetic && target.isSynthetic())
+ to_chat(user, "[src] isn't designed for synthetics!")
+ return 0
+ else if(!target.isSynthetic() && ((world.time - target.timeofdeath) > (10 MINUTES)))//Can only revive organics within a few minutes
+ to_chat(user, "There is no spark of life in [target.name], they've been dead too long to revive this way.")
+ return 0
+ return 1
+
/obj/item/device/defib_kit/attackby(var/obj/item/A as obj, mob/living/user as mob)
..()
@@ -94,7 +114,7 @@
//Patient moved too far
if(patient && !(get_dist(src,patient) <= 1)) //You separated the kit and pads too far
- audible_message("There's a clatter as the defib pads are yanked off of [patient].")
+ audible_message("There is a clatter as the [pad_name] are yanked off of [patient].")
statechange(0)
patient = null
return
@@ -111,7 +131,7 @@
patient.visible_message("[patient] convulses!")
playsound(src.loc, 'sound/effects/sparks2.ogg', 75, 1)
//Actual rezzing code
- if(prob(chance) && ((world.time - patient.timeofdeath) < (10 MINUTES))) //Can only revive within a few minutes
+ if(prob(chance))
if(!patient.client && patient.mind) //Don't force the dead person to come back if they don't want to.
for(var/mob/observer/dead/ghost in player_list)
if(ghost.mind == patient.mind)
@@ -155,3 +175,10 @@
break
return
+
+/obj/item/device/defib_kit/jumper_kit
+ name = "jumper cable kit"
+ desc = "This Morpheus-branded FBP defib kit is a semi-automated model. Apply cables, step back, wait."
+ icon_state = "jumper_kit"
+ use_on_synthetic = 1
+ pad_name = "jumper cables"
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 27ee923a1b4..ecd023320b2 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -181,6 +181,38 @@
else
return ..()
+/obj/item/device/flashlight/MouseDrop(obj/over_object as obj)
+ if(!canremove)
+ return
+
+ if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist
+
+ if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
+ return
+
+ if (!( istype(over_object, /obj/screen) ))
+ return ..()
+
+ //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away.
+ //there's got to be a better way of doing this.
+ if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
+ return
+
+ if (( usr.restrained() ) || ( usr.stat ))
+ return
+
+ if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src))
+ return
+
+ switch(over_object.name)
+ if("r_hand")
+ usr.u_equip(src)
+ usr.put_in_r_hand(src)
+ if("l_hand")
+ usr.u_equip(src)
+ usr.put_in_l_hand(src)
+ src.add_fingerprint(usr)
+
/obj/item/device/flashlight/attackby(obj/item/weapon/W, mob/user as mob)
if(power_use)
if(istype(W, /obj/item/weapon/cell))
diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm
index 6d041847857..76c4f9e7688 100644
--- a/code/game/objects/items/weapons/cigs_lighters.dm
+++ b/code/game/objects/items/weapons/cigs_lighters.dm
@@ -87,6 +87,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
var/icon_on
var/type_butt = null
var/chem_volume = 0
+ var/max_smoketime = 0 //Related to sprites
var/smoketime = 0
var/is_pipe = 0 //Prevents a runtime with pipes
var/matchmes = "USER lights NAME with FLAME"
@@ -100,8 +101,12 @@ CIGARETTE PACKETS ARE IN FANCY.DM
..()
flags |= NOREACT // so it doesn't react until you light it
create_reagents(chem_volume) // making the cigarrete a chemical holder with a maximum volume of 15
+ if(smoketime && !max_smoketime)
+ max_smoketime = smoketime
/obj/item/clothing/mask/smokable/proc/smoke(amount)
+ if(smoketime > max_smoketime)
+ smoketime = max_smoketime
smoketime -= amount
if(reagents && reagents.total_volume) // check if it has any reagents at all
if(ishuman(loc))
@@ -120,11 +125,29 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(location)
location.hotspot_expose(700, 5)
+/obj/item/clothing/mask/smokable/update_icon()
+ if(lit)
+ icon_state = "[initial(icon_state)]_on"
+ item_state = "[initial(item_state)]_on"
+ else if(smoketime < max_smoketime)
+ if(is_pipe)
+ icon_state = initial(icon_state)
+ item_state = initial(item_state)
+ else
+ icon_state = "[initial(icon_state)]_burnt"
+ item_state = "[initial(item_state)]_burnt"
+ if(ismob(loc))
+ var/mob/living/M = loc
+ M.update_inv_wear_mask(0)
+ M.update_inv_l_hand(0)
+ M.update_inv_r_hand(1)
+ ..()
+
/obj/item/clothing/mask/smokable/examine(mob/user)
..()
if(is_pipe)
return
- var/smoke_percent = round((smoketime / initial(smoketime)) * 100)
+ var/smoke_percent = round((smoketime / max_smoketime) * 100)
switch(smoke_percent)
if(90 to INFINITY)
user << "[src] is still fresh."
@@ -156,15 +179,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM
return
flags &= ~NOREACT // allowing reagents to react after being lit
reagents.handle_reactions()
- icon_state = icon_on
- item_state = icon_on
- if(ismob(loc))
- var/mob/living/M = loc
- M.update_inv_wear_mask(0)
- M.update_inv_l_hand(0)
- M.update_inv_r_hand(1)
var/turf/T = get_turf(src)
T.visible_message(flavor_text)
+ update_icon()
set_light(2, 0.25, "#E38F46")
processing_objects.Add(src)
@@ -205,14 +222,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/smokable/proc/quench()
lit = 0
processing_objects.Remove(src)
- icon_state = initial(icon_state)
- item_state = initial(item_state)
-
- if(ismob(loc))
- var/mob/living/M = loc
- M.update_inv_wear_mask(0)
- M.update_inv_l_hand(0)
- M.update_inv_r_hand(1)
+ update_icon()
/obj/item/clothing/mask/smokable/attack(mob/living/carbon/human/H, mob/user, def_zone)
if(lit && H == user && istype(H))
@@ -259,15 +269,15 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/smokable/cigarette
name = "cigarette"
desc = "A roll of tobacco and nicotine."
- icon_state = "cigoff"
+ icon_state = "cig"
+ item_state = "cig"
throw_speed = 0.5
- item_state = "cigoff"
w_class = ITEMSIZE_TINY
slot_flags = SLOT_EARS | SLOT_MASK
attack_verb = list("burnt", "singed")
- icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi
type_butt = /obj/item/weapon/cigbutt
chem_volume = 15
+ max_smoketime = 300
smoketime = 300
matchmes = "USER lights their NAME with their FLAME."
lightermes = "USER manages to light their NAME with FLAME."
@@ -315,11 +325,11 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/smokable/cigarette/cigar
name = "premium cigar"
desc = "A brown roll of tobacco and... well, you're not quite sure. This thing's huge!"
- icon_state = "cigar2off"
- icon_on = "cigar2on"
+ icon_state = "cigar2"
type_butt = /obj/item/weapon/cigbutt/cigarbutt
throw_speed = 0.5
- item_state = "cigaroff"
+ item_state = "cigar"
+ max_smoketime = 1500
smoketime = 1500
chem_volume = 20
matchmes = "USER lights their NAME with their FLAME."
@@ -331,14 +341,13 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/smokable/cigarette/cigar/cohiba
name = "\improper Cohiba Robusto cigar"
desc = "There's little more you could want from a cigar."
- icon_state = "cigar2off"
- icon_on = "cigar2on"
+ icon_state = "cigar2"
/obj/item/clothing/mask/smokable/cigarette/cigar/havana
name = "premium Havanian cigar"
desc = "A cigar fit for only the best of the best."
- icon_state = "cigar2off"
- icon_on = "cigar2on"
+ icon_state = "cigar2"
+ max_smoketime = 7200
smoketime = 7200
chem_volume = 30
@@ -375,9 +384,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/smokable/pipe
name = "smoking pipe"
desc = "A pipe, for smoking. Made of fine, stained cherry wood."
- icon_state = "pipeoff"
- item_state = "pipeoff"
- icon_on = "pipeon" //Note - these are in masks.dmi
+ icon_state = "pipe"
+ item_state = "pipe"
smoketime = 0
chem_volume = 50
matchmes = "USER lights their NAME with their FLAME."
@@ -429,6 +437,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if (smoketime)
user << "[src] is already packed."
return
+ max_smoketime = 1000
smoketime = 1000
if(G.reagents)
G.reagents.trans_to_obj(src, G.reagents.total_volume)
@@ -455,9 +464,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/smokable/pipe/cobpipe
name = "corn cob pipe"
desc = "A nicotine delivery system popularized by folksy backwoodsmen, kept popular in the modern age and beyond by space hipsters."
- icon_state = "cobpipeoff"
- item_state = "cobpipeoff"
- icon_on = "cobpipeon" //Note - these are in masks.dmi
+ icon_state = "cobpipe"
+ item_state = "cobpipe"
chem_volume = 35
/////////
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index a5b03264d64..2f4b2f3a8ce 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -28,6 +28,38 @@
update_icon()
return
+/obj/item/weapon/melee/baton/MouseDrop(obj/over_object as obj)
+ if(!canremove)
+ return
+
+ if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist
+
+ if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
+ return
+
+ if (!( istype(over_object, /obj/screen) ))
+ return ..()
+
+ //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away.
+ //there's got to be a better way of doing this.
+ if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
+ return
+
+ if (( usr.restrained() ) || ( usr.stat ))
+ return
+
+ if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src))
+ return
+
+ switch(over_object.name)
+ if("r_hand")
+ usr.u_equip(src)
+ usr.put_in_r_hand(src)
+ if("l_hand")
+ usr.u_equip(src)
+ usr.put_in_l_hand(src)
+ src.add_fingerprint(usr)
+
/obj/item/weapon/melee/baton/loaded/New() //this one starts with a cell pre-installed.
..()
bcell = new/obj/item/weapon/cell/device/weapon(src)
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index 8e039ee2dac..7c5ac1ee551 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -297,6 +297,38 @@
M.update_inv_l_hand()
M.update_inv_r_hand()
+/obj/item/weapon/weldingtool/MouseDrop(obj/over_object as obj)
+ if(!canremove)
+ return
+
+ if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist
+
+ if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
+ return
+
+ if (!( istype(over_object, /obj/screen) ))
+ return ..()
+
+ //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away.
+ //there's got to be a better way of doing this.
+ if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
+ return
+
+ if (( usr.restrained() ) || ( usr.stat ))
+ return
+
+ if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src))
+ return
+
+ switch(over_object.name)
+ if("r_hand")
+ usr.u_equip(src)
+ usr.put_in_r_hand(src)
+ if("l_hand")
+ usr.u_equip(src)
+ usr.put_in_l_hand(src)
+ src.add_fingerprint(usr)
+
//Sets the welding state of the welding tool. If you see W.welding = 1 anywhere, please change it to W.setWelding(1)
//so that the welding tool updates accordingly
/obj/item/weapon/weldingtool/proc/setWelding(var/set_welding, var/mob/M)
diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm
index 050ec316382..23b42457508 100644
--- a/code/modules/client/preference_setup/general/01_basic.dm
+++ b/code/modules/client/preference_setup/general/01_basic.dm
@@ -130,7 +130,11 @@ datum/preferences/proc/set_biological_gender(var/gender)
return ..()
/datum/category_item/player_setup_item/general/basic/proc/get_genders()
- var/datum/species/S = all_species[pref.species]
+ var/datum/species/S
+ if(pref.species)
+ S = all_species[pref.species]
+ else
+ S = all_species["Human"]
var/list/possible_genders = S.genders
if(!pref.organ_data || pref.organ_data[BP_TORSO] != "cyborg")
return possible_genders
diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm
index 079713c7eae..3e239badc7a 100644
--- a/code/modules/client/preference_setup/general/03_body.dm
+++ b/code/modules/client/preference_setup/general/03_body.dm
@@ -28,6 +28,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["disabilities"] >> pref.disabilities
S["organ_data"] >> pref.organ_data
S["rlimb_data"] >> pref.rlimb_data
+ S["body_markings"] >> pref.body_markings
pref.preview_icon = null
/datum/category_item/player_setup_item/general/body/save_character(var/savefile/S)
@@ -51,6 +52,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["disabilities"] << pref.disabilities
S["organ_data"] << pref.organ_data
S["rlimb_data"] << pref.rlimb_data
+ S["body_markings"] << pref.body_markings
/datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S)
if(!pref.species || !(pref.species in playable_species))
@@ -75,6 +77,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.disabilities = sanitize_integer(pref.disabilities, 0, 65535, initial(pref.disabilities))
if(!pref.organ_data) pref.organ_data = list()
if(!pref.rlimb_data) pref.rlimb_data = list()
+ if(!pref.body_markings) pref.body_markings = list()
+ else pref.body_markings &= body_marking_styles_list
// Moved from /datum/preferences/proc/copy_to()
/datum/category_item/player_setup_item/general/body/copy_to_mob(var/mob/living/carbon/human/character)
@@ -123,6 +127,20 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
I.robotize()
else if(status == "digital")
I.digitize()
+
+ for(var/N in character.organs_by_name)
+ var/obj/item/organ/external/O = character.organs_by_name[N]
+ O.markings.Cut()
+
+ for(var/M in pref.body_markings)
+ var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[M]
+ var/mark_color = "[pref.body_markings[M]]"
+
+ for(var/BP in mark_datum.body_parts)
+ var/obj/item/organ/external/O = character.organs_by_name[BP]
+ if(O)
+ O.markings[M] = list("color" = mark_color, "datum" = mark_datum)
+
return
/datum/category_item/player_setup_item/general/body/content(var/mob/user)
@@ -251,6 +269,13 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(has_flag(mob_species, HAS_SKIN_COLOR))
. += "
Body Color
"
. += "Change Color __
"
+
+ . += "
Body Markings +
"
+ for(var/M in pref.body_markings)
+ . += "[M] - Color"
+ . += "
"
+ . += "__
"
+
. = jointext(.,null)
/datum/category_item/player_setup_item/general/body/proc/has_flag(var/datum/species/mob_species, var/flag)
@@ -289,7 +314,6 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(!(pref.biological_gender in mob_species.genders))
pref.set_biological_gender(mob_species.genders[1])
-
//grab one of the valid hair styles for the newly chosen species
var/list/valid_hairstyles = list()
for(var/hairstyle in hair_styles_list)
@@ -334,6 +358,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.s_tone = 0
reset_limbs() // Safety for species with incompatible manufacturers; easier than trying to do it case by case.
+ pref.body_markings.Cut() // Basically same as above.
var/min_age = get_min_age()
var/max_age = get_max_age()
@@ -421,6 +446,32 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.f_style = new_f_style
return TOPIC_REFRESH_UPDATE_PREVIEW
+ else if(href_list["marking_style"])
+ var/list/usable_markings = pref.body_markings.Copy() ^ body_marking_styles_list.Copy()
+ for(var/M in usable_markings)
+ var/datum/sprite_accessory/S = usable_markings[M]
+ if(!S.species_allowed.len)
+ continue
+ else if(!(pref.species in S.species_allowed))
+ usable_markings -= M
+
+ var/new_marking = input(user, "Choose a body marking:", "Character Preference") as null|anything in usable_markings
+ if(new_marking && CanUseTopic(user))
+ pref.body_markings[new_marking] = "#000000" //New markings start black
+ return TOPIC_REFRESH_UPDATE_PREVIEW
+
+ else if(href_list["marking_remove"])
+ var/M = href_list["marking_remove"]
+ pref.body_markings -= M
+ return TOPIC_REFRESH_UPDATE_PREVIEW
+
+ else if(href_list["marking_color"])
+ var/M = href_list["marking_color"]
+ var/mark_color = input(user, "Choose the [M] color: ", "Character Preference", pref.body_markings[M]) as color|null
+ if(mark_color && CanUseTopic(user))
+ pref.body_markings[M] = "[mark_color]"
+ return TOPIC_REFRESH_UPDATE_PREVIEW
+
else if(href_list["reset_limbs"])
reset_limbs()
return TOPIC_REFRESH_UPDATE_PREVIEW
diff --git a/code/modules/client/preference_setup/loadout/loadout_suit.dm b/code/modules/client/preference_setup/loadout/loadout_suit.dm
index de8e06419e8..2c602bcc6d2 100644
--- a/code/modules/client/preference_setup/loadout/loadout_suit.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_suit.dm
@@ -356,6 +356,22 @@
..()
gear_tweaks = list(gear_tweak_free_color_choice)
-/datum/gear/suit/miscellaneous/redandblackjacket
- display_name = "red and black jacket"
- path = /obj/item/clothing/suit/storage/toggle/redandblackjacket
\ No newline at end of file
+/datum/gear/suit/miscellaneous/sec_dep_jacket
+ display_name = "department jacket, security"
+ path = /obj/item/clothing/suit/storage/toggle/sec_dep_jacket
+
+/datum/gear/suit/miscellaneous/engi_dep_jacket
+ display_name = "department jacket, engineering"
+ path = /obj/item/clothing/suit/storage/toggle/engi_dep_jacket
+
+/datum/gear/suit/miscellaneous/supply_dep_jacket
+ display_name = "department jacket, supply"
+ path = /obj/item/clothing/suit/storage/toggle/supply_dep_jacket
+
+/datum/gear/suit/miscellaneous/sci_dep_jacket
+ display_name = "department jacket, science"
+ path = /obj/item/clothing/suit/storage/toggle/sci_dep_jacket
+
+/datum/gear/suit/miscellaneous/med_dep_jacket
+ display_name = "department jacket, medical"
+ path = /obj/item/clothing/suit/storage/toggle/med_dep_jacket
\ No newline at end of file
diff --git a/code/modules/client/preference_setup/preference_setup.dm b/code/modules/client/preference_setup/preference_setup.dm
index f72ff0645c0..b3c253647ef 100644
--- a/code/modules/client/preference_setup/preference_setup.dm
+++ b/code/modules/client/preference_setup/preference_setup.dm
@@ -263,13 +263,14 @@
/datum/category_item/player_setup_item/proc/get_FBP_type()
if(!is_FBP())
return 0 // Not a robot.
- switch(pref.organ_data["brain"])
- if("assisted")
- return PREF_FBP_CYBORG
- if("mechanical")
- return PREF_FBP_POSI
- if("digital")
- return PREF_FBP_SOFTWARE
+ if(O_BRAIN in pref.organ_data)
+ switch(pref.organ_data[O_BRAIN])
+ if("assisted")
+ return PREF_FBP_CYBORG
+ if("mechanical")
+ return PREF_FBP_POSI
+ if("digital")
+ return PREF_FBP_SOFTWARE
return 0 //Something went wrong!
/datum/category_item/player_setup_item/proc/get_min_age()
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 710c072e949..d1d51c52dbf 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -88,6 +88,8 @@ datum/preferences
var/list/rlimb_data = list()
var/list/player_alt_titles = new() // the default name of a job like "Medical Doctor"
+ var/list/body_markings = list() // "name" = "#rgbcolor"
+
var/list/flavor_texts = list()
var/list/flavour_texts_robot = list()
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index dd732d0f7c3..00ea3308928 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -574,12 +574,6 @@ obj/item/clothing/suit/kimono
icon_state = "smw_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_black", slot_l_hand_str = "suit_black")
-/obj/item/clothing/suit/storage/toggle/redandblackjacket
- name = "red and black jacket"
- desc = "A cool red and black jacket to keep you stylish and cozy."
- icon_state = "redandblackjacket"
- flags_inv = HIDEHOLSTER
-
/obj/item/clothing/suit/whitedress
name = "white dress"
desc = "A fancy white dress."
@@ -776,6 +770,44 @@ obj/item/clothing/suit/kimono
name = "brown varsity jacket"
icon_state = "varsity_brown"
+/*
+ * Department Jackets
+ */
+/obj/item/clothing/suit/storage/toggle/sec_dep_jacket
+ name = "department jacket, security"
+ desc = "A cozy jacket in security's colors. Show your department pride!"
+ icon_state = "sec_dep_jacket"
+ item_state_slots = list(slot_r_hand_str = "sec_dep_jacket", slot_l_hand_str = "sec_dep_jacket")
+ flags_inv = HIDEHOLSTER
+
+/obj/item/clothing/suit/storage/toggle/engi_dep_jacket
+ name = "department jacket, engineering"
+ desc = "A cozy jacket in engineering's colors. Show your department pride!"
+ icon_state = "engi_dep_jacket"
+ item_state_slots = list(slot_r_hand_str = "engi_dep_jacket", slot_l_hand_str = "engi_dep_jacket")
+ flags_inv = HIDEHOLSTER
+
+/obj/item/clothing/suit/storage/toggle/supply_dep_jacket
+ name = "department jacket, supply"
+ desc = "A cozy jacket in supply's colors. Show your department pride!"
+ icon_state = "supply_dep_jacket"
+ item_state_slots = list(slot_r_hand_str = "supply_dep_jacket", slot_l_hand_str = "supply_dep_jacket")
+ flags_inv = HIDEHOLSTER
+
+/obj/item/clothing/suit/storage/toggle/sci_dep_jacket
+ name = "department jacket, science"
+ desc = "A cozy jacket in science's colors. Show your department pride!"
+ icon_state = "sci_dep_jacket"
+ item_state_slots = list(slot_r_hand_str = "sci_dep_jacket", slot_l_hand_str = "sci_dep_jacket")
+ flags_inv = HIDEHOLSTER
+
+/obj/item/clothing/suit/storage/toggle/med_dep_jacket
+ name = "department jacket, medical"
+ desc = "A cozy jacket in medical's colors. Show your department pride!"
+ icon_state = "med_dep_jacket"
+ item_state_slots = list(slot_r_hand_str = "med_dep_jacket", slot_l_hand_str = "med_dep_jacket")
+ flags_inv = HIDEHOLSTER
+
/*
* Track Jackets
*/
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index a6267a8d00e..a84a2889dc5 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -268,6 +268,8 @@ var/global/list/damage_icon_parts = list()
icon_key += "[rgb(part.h_col[1],part.h_col[2],part.h_col[3])]"
else
icon_key += "#000000"
+ for(var/M in part.markings)
+ icon_key += "[M][part.markings[M]["color"]]"
if(part.robotic >= ORGAN_ROBOT)
icon_key += "2[part.model ? "-[part.model]": ""]"
diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm
index ca1e8358992..089a0befacb 100644
--- a/code/modules/mob/new_player/sprite_accessories.dm
+++ b/code/modules/mob/new_player/sprite_accessories.dm
@@ -983,6 +983,197 @@
species_allowed = list("Teshari")
gender = NEUTER
+/*
+////////////////////////////
+/ =--------------------= /
+/ == Body Markings == /
+/ =--------------------= /
+////////////////////////////
+*/
+/datum/sprite_accessory/marking
+ icon = 'icons/mob/human_races/markings.dmi'
+ do_colouration = 1 //Almost all of them have it, COLOR_ADD
+
+ //Empty list is unrestricted. Should only restrict the ones that make NO SENSE on other species,
+ //like Tajara inner-ear coloring overlay stuff.
+ species_allowed = list()
+
+ var/body_parts = list() //A list of bodyparts this covers, in organ_tag defines
+ //Reminder: BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN,BP_HEAD
+
+ tat_heart
+ name = "Tattoo (Heart, Torso)"
+ icon_state = "tat_heart"
+ body_parts = list(BP_TORSO)
+
+ tat_hive
+ name = "Tattoo (Hive, Back)"
+ icon_state = "tat_hive"
+ body_parts = list(BP_TORSO)
+
+ tat_nightling
+ name = "Tattoo (Nightling, Back)"
+ icon_state = "tat_nightling"
+ body_parts = list(BP_TORSO)
+
+ tat_campbell
+ name = "Tattoo (Campbell, R.Arm)"
+ icon_state = "tat_campbell"
+ body_parts = list(BP_R_ARM)
+
+ tat_tiger
+ name = "Tattoo (Tiger Stripes, Body)"
+ icon_state = "tat_campbell"
+ body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN)
+
+ taj_paw_socks
+ name = "Socks Coloration (Taj)"
+ icon_state = "taj_pawsocks"
+ body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND)
+ species_allowed = list("Tajara")
+
+ una_paw_socks
+ name = "Socks Coloration (Una)"
+ icon_state = "una_pawsocks"
+ body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND)
+ species_allowed = list("Unathi")
+
+ paw_socks
+ name = "Socks Coloration (Generic)"
+ icon_state = "pawsocks"
+ body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND)
+
+ paw_socks_belly
+ name = "Socks+Belly Coloration (Generic)"
+ icon_state = "pawsocksbelly"
+ body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_GROIN,BP_TORSO)
+
+ belly_hands_feet
+ name = "Hands/Feet/Belly Color (Minor)"
+ icon_state = "bellyhandsfeetsmall"
+ body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_GROIN,BP_TORSO)
+
+ hands_feet_belly_full
+ name = "Hands/Feet/Belly Color (Major)"
+ icon_state = "bellyhandsfeet"
+ body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_GROIN,BP_TORSO)
+
+ patches
+ name = "Color Patches"
+ icon_state = "patches"
+ body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN)
+
+ patchesface
+ name = "Color Patches (Face)"
+ icon_state = "patchesface"
+ body_parts = list(BP_HEAD)
+
+ bands
+ name = "Color Bands"
+ icon_state = "bands"
+ body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN)
+
+ bandsface
+ name = "Color Bands (Face)"
+ icon_state = "bandsface"
+ body_parts = list(BP_HEAD)
+
+ tiger_stripes
+ name = "Tiger Stripes"
+ icon_state = "tiger"
+ body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_TORSO,BP_GROIN)
+ species_allowed = list("Tajara") //There's a tattoo for non-cats
+
+ tigerhead
+ name = "Tiger Stripes (Head, Minor)"
+ icon_state = "tigerhead"
+ body_parts = list(BP_HEAD)
+
+ tigerface
+ name = "Tiger Stripes (Head, Major)"
+ icon_state = "tigerface"
+ body_parts = list(BP_HEAD)
+ species_allowed = list("Tajara") //There's a tattoo for non-cats
+
+ backstripe
+ name = "Back Stripe"
+ icon_state = "backstripe"
+ body_parts = list(BP_TORSO)
+
+ //Taj specific stuff
+ taj_belly
+ name = "Belly Fur (Taj)"
+ icon_state = "taj_belly"
+ body_parts = list(BP_TORSO)
+ species_allowed = list("Tajara")
+
+ taj_bellyfull
+ name = "Belly Fur Wide (Taj)"
+ icon_state = "taj_bellyfull"
+ body_parts = list(BP_TORSO)
+ species_allowed = list("Tajara")
+
+ taj_earsout
+ name = "Outer Ear (Taj)"
+ icon_state = "taj_earsout"
+ body_parts = list(BP_HEAD)
+ species_allowed = list("Tajara")
+
+ taj_earsin
+ name = "Inner Ear (Taj)"
+ icon_state = "taj_earsin"
+ body_parts = list(BP_HEAD)
+ species_allowed = list("Tajara")
+
+ taj_nose
+ name = "Nose Color (Taj)"
+ icon_state = "taj_nose"
+ body_parts = list(BP_HEAD)
+ species_allowed = list("Tajara")
+
+ taj_crest
+ name = "Chest Fur Crest (Taj)"
+ icon_state = "taj_crest"
+ body_parts = list(BP_TORSO)
+ species_allowed = list("Tajara")
+
+ taj_muzzle
+ name = "Muzzle Color (Taj)"
+ icon_state = "taj_muzzle"
+ body_parts = list(BP_HEAD)
+ species_allowed = list("Tajara")
+
+ taj_face
+ name = "Cheeks Color (Taj)"
+ icon_state = "taj_face"
+ body_parts = list(BP_HEAD)
+ species_allowed = list("Tajara")
+
+ taj_all
+ name = "All Taj Head (Taj)"
+ icon_state = "taj_all"
+ body_parts = list(BP_HEAD)
+ species_allowed = list("Tajara")
+
+ //Una specific stuff
+ una_face
+ name = "Face Color (Una)"
+ icon_state = "una_face"
+ body_parts = list(BP_HEAD)
+ species_allowed = list("Unathi")
+
+ una_facelow
+ name = "Face Color Low (Una)"
+ icon_state = "una_facelow"
+ body_parts = list(BP_HEAD)
+ species_allowed = list("Unathi")
+
+ una_scutes
+ name = "Scutes (Una)"
+ icon_state = "una_scutes"
+ body_parts = list(BP_TORSO)
+ species_allowed = list("Unathi")
+
//skin styles - WIP
//going to have to re-integrate this with surgery
//let the icon_state hold an icon preview for now
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index f37fb3b9b8a..e3fabe82f55 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -39,6 +39,7 @@
var/list/h_col // hair colour
var/body_hair // Icon blend for body hair if any.
var/mob/living/applied_pressure
+ var/list/markings = list() // Markings (body_markings) to apply to the icon
// Wound and structural data.
var/wound_update_accuracy = 1 // how often wounds should be updated, a higher number means less often
diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm
index 3c975067a2d..4e381d47ad6 100644
--- a/code/modules/organs/organ_icon.dm
+++ b/code/modules/organs/organ_icon.dm
@@ -69,6 +69,15 @@ var/global/list/limb_icon_cache = list()
overlays |= lip_icon
mob_icon.Blend(lip_icon, ICON_OVERLAY)
+ //Head markings, duplicated (sadly) below.
+ for(var/M in markings)
+ var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"]
+ var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]")
+ mark_s.Blend(markings[M]["color"], ICON_ADD)
+ overlays |= mark_s //So when it's not on your body, it has icons
+ mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons
+ icon_cache_key += "[M][markings[M]["color"]]"
+
if(owner.f_style)
var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style]
if(facial_hair_style && facial_hair_style.species_allowed && (species.get_bodytype(owner) in facial_hair_style.species_allowed))
@@ -119,6 +128,15 @@ var/global/list/limb_icon_cache = list()
mob_icon = new /icon(species.get_icobase(owner, (status & ORGAN_MUTATED)), "[icon_name][gender ? "_[gender]" : ""]")
apply_colouration(mob_icon)
+ //Body markings, does not include head, duplicated (sadly) above.
+ for(var/M in markings)
+ var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"]
+ var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]")
+ mark_s.Blend(markings[M]["color"], ICON_ADD)
+ overlays |= mark_s //So when it's not on your body, it has icons
+ mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons
+ icon_cache_key += "[M][markings[M]["color"]]"
+
if(body_hair && islist(h_col) && h_col.len >= 3)
var/cache_key = "[body_hair]-[icon_name]-[h_col[1]][h_col[2]][h_col[3]]"
if(!limb_icon_cache[cache_key])
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 98dd1f987c4..75d574ed632 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -223,6 +223,38 @@
attached_lock.stored_dna = list()
return 1
+/obj/item/weapon/gun/MouseDrop(obj/over_object as obj)
+ if(!canremove)
+ return
+
+ if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist
+
+ if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
+ return
+
+ if (!( istype(over_object, /obj/screen) ))
+ return ..()
+
+ //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away.
+ //there's got to be a better way of doing this.
+ if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
+ return
+
+ if (( usr.restrained() ) || ( usr.stat ))
+ return
+
+ if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src))
+ return
+
+ switch(over_object.name)
+ if("r_hand")
+ usr.u_equip(src)
+ usr.put_in_r_hand(src)
+ if("l_hand")
+ usr.u_equip(src)
+ usr.put_in_l_hand(src)
+ src.add_fingerprint(usr)
+
/obj/item/weapon/gun/proc/Fire(atom/target, mob/living/user, clickparams, pointblank=0, reflex=0)
if(!user || !target) return
diff --git a/html/changelog.html b/html/changelog.html
index 068437c9d5b..83e24ec6bf8 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -53,6 +53,16 @@
-->