diff --git a/code/__DEFINES/economy.dm b/code/__DEFINES/economy.dm
index f3533503779605..551b242acc6188 100644
--- a/code/__DEFINES/economy.dm
+++ b/code/__DEFINES/economy.dm
@@ -90,13 +90,13 @@
/// The symbol for the default type of money used in the code.
#define MONEY_SYMBOL "♎︎︎" // REDSHIFT EDIT - #define MONEY_SYMBOL "cr"
/// The name for the default type of money used in the code.
-#define MONEY_NAME = "libre" // REDSHIFT EDIT - #define MONEY_NAME "credits"
-#define MONEY_NAME_SINGULAR = "libra" // REDSHIFT EDIT - #define MONEY_NAME_SINGULAR "credit"
-#define MONEY_NAME_CAPITALIZED = "Libre" // REDSHIFT EDIT - #define MONEY_NAME_CAPITALIZED "Credits"
+#define MONEY_NAME "libre" // REDSHIFT EDIT - #define MONEY_NAME "credits"
+#define MONEY_NAME_SINGULAR "libra" // REDSHIFT EDIT - #define MONEY_NAME_SINGULAR "credit"
+#define MONEY_NAME_CAPITALIZED "Libre" // REDSHIFT EDIT - #define MONEY_NAME_CAPITALIZED "Credits"
// Due to the ways macros work, I cant just directly use credit\s.
// You will need to verify there is no loose use cases of credit\s.
// As of present there is none left floating around.
-#define MONEY_NAME_AUTOPLURAL(amount) "libr[##amount == 1 ? "a" : "e"]" // REDSHIFT EDIT - #define MONEY_NAME_AUTOPURAL(amount) "credit[##amount == 1 ? "" : "s"]"
+#define MONEY_NAME_AUTOPURAL(amount) "libr[##amount == 1 ? "a" : "e"]" // REDSHIFT EDIT - #define MONEY_NAME_AUTOPURAL(amount) "credit[##amount == 1 ? "" : "s"]"
#define MONEY_MINING_SYMBOL "mp"
#define MONEY_BITRUNNING_SYMBOL "np"
diff --git a/code/__DEFINES/~redshift_defines/attributes.dm b/code/__DEFINES/~redshift_defines/attributes_and_skills.dm
similarity index 76%
rename from code/__DEFINES/~redshift_defines/attributes.dm
rename to code/__DEFINES/~redshift_defines/attributes_and_skills.dm
index 927db2fe6a4ca0..8c056ca086c89b 100644
--- a/code/__DEFINES/~redshift_defines/attributes.dm
+++ b/code/__DEFINES/~redshift_defines/attributes_and_skills.dm
@@ -15,3 +15,10 @@
#define MAX_ATTRIBUTE_SCORE 10
/// The default value of an attribute
#define DEFAULT_ATTRIBUTE_SCORE 5
+
+/// The maximum value that a skill can hold
+#define MAX_SKILL_LEVEL 15
+
+// All skills that a mob can have are defined below
+/// Skill at using non-weapon items as a weapon
+#define SKILL_WEAPON_ECCENTRIC "Eccentric Weapon User"
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index a148296a873139..d063d1adaab5b5 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -317,12 +317,24 @@
return ATTACK_FAILED
/mob/living/attacked_by(obj/item/attacking_item, mob/living/user, list/modifiers, list/attack_modifiers)
-
+ // REDSHIFT ADDITION
+ var/chance_to_actually_get_hit = 100
+ if(user != src) // If we're attacking ourselves we always hit
+ chance_to_actually_get_hit += get_melee_dodge_modifier()
+ if(!isnull(attacking_item.combat_skill_hit_chance))
+ chance_to_actually_get_hit += user.target_chance_skill_modifier(attacking_item.combat_skill_hit_chance)
+ if(!prob(chance_to_actually_get_hit))
+ make_attack_dodge_message(attacking_item, user)
+ // REDSHIFT ADDITION END
var/targeting = check_zone(user.zone_selected)
if(user != src)
var/zone_hit_chance = 80
if(body_position == LYING_DOWN)
zone_hit_chance += 10
+ // REDSHIFT ADDITION
+ if(!isnull(attacking_item.combat_skill_hit_chance))
+ zone_hit_chance += user.target_chance_skill_modifier(attacking_item.combat_skill_hit_chance)
+ // REDSHIFT ADDITION END
targeting = get_random_valid_zone(targeting, zone_hit_chance)
var/targeting_human_readable = parse_zone_with_bodypart(targeting)
@@ -339,6 +351,10 @@
), ARMOR_MAX_BLOCK)
var/final_force = CALCULATE_FORCE(attacking_item, attack_modifiers)
+ // REDSHIFT ADDITION
+ if(!isnull(attacking_item.combat_attribute_damage_modifier))
+ final_force = get_weapon_damage_mod(attacking_item.combat_attribute_damage_modifier, final_force)
+ // REDSHIFT ADDITION END
if(mob_biotypes & (MOB_ROBOTIC|MOB_MINERAL|MOB_SKELETAL)) // this should probably check hit bodypart for humanoids
final_force *= attacking_item.get_demolition_modifier(src)
@@ -530,9 +546,9 @@
if(user == src)
attack_message_victim = "You [message_verb_simple] yourself[message_hit_area] with [weapon]."
visible_message(span_danger("[attack_message_spectator]"),\
- span_userdanger("[attack_message_victim]"), null, COMBAT_MESSAGE_RANGE, user)
+ span_boldselfwarning("[attack_message_victim]"), null, COMBAT_MESSAGE_RANGE, user) // REDSHIFT EDIT - span_userdanger("[attack_message_victim]") , null, COMBAT_MESSAGE_RANGE, user)
if(is_blind())
- to_chat(src, span_danger("Someone hits you[message_hit_area]!"))
+ to_chat(src, span_selfwarning("Someone hits you[message_hit_area]!")) // REDSHIFT EDIT - to_chat(src, span_danger("Someone hits you[message_hit_area]!"))
to_chat(user, span_danger("[attack_message_attacker]"))
return 1
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 52348098402eef..0c42bfc811f7f7 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -131,7 +131,7 @@
if(user == src)
attack_message_victim = "You [message_verb_simple] yourself[message_hit_area] with [weapon][extra_wound_details]!"
visible_message(span_danger("[attack_message_spectator]"),\
- span_userdanger("[attack_message_victim]"), null, COMBAT_MESSAGE_RANGE, user)
+ span_boldselfwarning("[attack_message_victim]"), null, COMBAT_MESSAGE_RANGE, user) // REDSHIFT EDIT - span_userdanger("[attack_message_victim]"), null, COMBAT_MESSAGE_RANGE, user)
if(user != src)
to_chat(user, span_danger("[attack_message_attacker]"))
return TRUE
diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm
index 735794b93edd34..79907d20581cea 100644
--- a/code/modules/mob/living/carbon/human/_species.dm
+++ b/code/modules/mob/living/carbon/human/_species.dm
@@ -860,7 +860,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
if(!damage || !affecting || prob(miss_chance))//future-proofing for species that have 0 damage/weird cases where no zone is targeted
playsound(target.loc, attacking_bodypart.unarmed_miss_sound, 25, TRUE, -1)
target.visible_message(span_danger("[user]'s [atk_verb] misses [target]!"), \
- span_danger("You avoid [user]'s [atk_verb]!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, user)
+ span_selfwarning("You avoid [user]'s [atk_verb]!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, user) // REDSHIFT EDIT - span_danger("You avoid [user]'s [atk_verb]!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] misses [target]!"))
log_combat(user, target, "attempted to punch")
return FALSE
@@ -888,7 +888,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
atk_verb_continuous = attacking_bodypart.grappled_attack_verb_continuous
target.visible_message(span_danger("[user] [atk_verb_continuous] [target]!"), \
- span_userdanger("[user] [atk_verb_continuous] you!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, user)
+ span_boldselfwarning("[user] [atk_verb_continuous] you!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, user) // REDSHIFT EDIT - span_userdanger("[user] [atk_verb_continuous] you!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_danger("You [atk_verb] [target]!"))
target.lastattacker = user.real_name
@@ -944,13 +944,13 @@ GLOBAL_LIST_EMPTY(features_by_species)
if (-INFINITY to 0) //Mostly a gimmie, this one just keeps them staggered briefly
target.adjust_staggered_up_to(1 SECONDS, 10 SECONDS)
target.visible_message(span_warning("[user]'s [atk_verb] briefly winds [target]!"), \
- span_warning("You are briefly winded by [user]'s [atk_verb]!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
+ span_boldselfwarning("You are briefly winded by [user]'s [atk_verb]!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user) // REDSHIFT EDIT - span_warning("You are briefly winded by [user]'s [atk_verb]!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] briefly winds [target]!"))
if (1 to 10)
target.adjust_eye_blur_up_to(5 SECONDS, 10 SECONDS)
target.visible_message(span_warning("[user]'s [atk_verb] hits [target] so hard, their eyes water! Ouch!"), \
- span_warning("You are hit viciously by [user]'s [atk_verb], and your eyes begin to water!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
+ span_boldselfwarning("You are hit viciously by [user]'s [atk_verb], and your eyes begin to water!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user) // REDSHIFT EDIT - span_warning("You are hit viciously by [user]'s [atk_verb], and your eyes begin to water!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] causes [target] to tear up!"))
if (11 to 30)
@@ -958,7 +958,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
target.adjust_eye_blur_up_to(5 SECONDS, 10 SECONDS)
target.adjust_confusion_up_to(5 SECONDS, 10 SECONDS)
target.visible_message(span_warning("[user]'s [atk_verb] hits [target] so hard, they are sent reeling in agony! Damn!"), \
- span_warning("You are hit viciously by [user]'s [atk_verb], and everything becomes a dizzying blur!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
+ span_boldselfwarning("You are hit viciously by [user]'s [atk_verb], and everything becomes a dizzying blur!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user) // REDSHIFT EDIT - pan_warning("You are hit viciously by [user]'s [atk_verb], and everything becomes a dizzying blur!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] causes [target] to go stumbling about in a confuzed daze!"))
if(31 to 40)
@@ -966,13 +966,13 @@ GLOBAL_LIST_EMPTY(features_by_species)
target.adjust_confusion_up_to(5 SECONDS, 10 SECONDS)
target.adjust_temp_blindness_up_to(5 SECONDS, 10 SECONDS)
target.visible_message(span_warning("[user]'s [atk_verb] hits [target] so hard, they are sent reeling blindly in agony! Goddamn!"), \
- span_warning("You are hit viciously by [user]'s [atk_verb], and everything becomes a dizzying, blinding blur!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
+ span_boldselfwarning("You are hit viciously by [user]'s [atk_verb], and everything becomes a dizzying, blinding blur!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user) // REDSHIFT EDIT - span_warning("You are hit viciously by [user]'s [atk_verb], and everything becomes a dizzying, blinding blur!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] causes [target] to go stumbling about in a confuzed, blind daze!"))
if (41 to 45)
target.apply_effect(4 SECONDS, EFFECT_KNOCKDOWN, armor_block)
target.visible_message(span_warning("[user]'s [atk_verb] hits [target] so hard, you knock them off their feet! Holy shit!"), \
- span_warning("You are hit viciously by [user]'s [atk_verb] and sent toppling head over heels!"), span_hear("You hear a sickening thud!"), COMBAT_MESSAGE_RANGE, user)
+ span_boldselfwarning("You are hit viciously by [user]'s [atk_verb] and sent toppling head over heels!"), span_hear("You hear a sickening thud!"), COMBAT_MESSAGE_RANGE, user) // REDSHIFT EDIT - span_warning("You are hit viciously by [user]'s [atk_verb] and sent toppling head over heels!"), span_hear("You hear a sickening thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] lands, and you send [target] sailing off their feet!"))
if (46 to INFINITY)
@@ -980,7 +980,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/obj/item/bodypart/affecting = target.get_bodypart(target.get_random_valid_zone(user.zone_selected))
target.apply_damage(5, BRUTE, affecting, armor_block, wound_bonus = limb_accuracy * 2) //Mostly for the crunchy wounding effect than actually doing damage
target.visible_message(span_warning("[user]'s [atk_verb] hits [target] so hard, you hit them off their feet with a loud crunch! Fucking hell!"), \
- span_warning("You are hit viciously by [user]'s [atk_verb], and suddenly feel an overwhelming pain as you topple head over heels!"), span_hear("You hear a sickening crack and a loud thud!"), COMBAT_MESSAGE_RANGE, user)
+ span_boldselfwarning("You are hit viciously by [user]'s [atk_verb], and suddenly feel an overwhelming pain as you topple head over heels!"), span_hear("You hear a sickening crack and a loud thud!"), COMBAT_MESSAGE_RANGE, user) // REDSHIFT EDIT - span_warning("You are hit viciously by [user]'s [atk_verb], and suddenly feel an overwhelming pain as you topple head over heels!"), span_hear("You hear a sickening crack and a loud thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] lands, and [target] is sent crashing to the floor with the immense force! Good god!"))
@@ -1006,7 +1006,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
if((owner != target) && target.check_block(owner, 0, owner.name, attack_type = UNARMED_ATTACK))
log_combat(owner, target, "attempted to touch")
target.visible_message(span_warning("[owner] attempts to touch [target]!"), \
- span_danger("[owner] attempts to touch you!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, owner)
+ span_selfwarning("[owner] attempts to touch you!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, owner) // REDSHIFT EDIT - span_danger("[owner] attempts to touch you!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, owner)
to_chat(owner, span_warning("You attempt to touch [target]!"))
return
diff --git a/redshift/attributes/attributes.dm b/redshift/attributes_and_skills/attributes.dm
similarity index 64%
rename from redshift/attributes/attributes.dm
rename to redshift/attributes_and_skills/attributes.dm
index a7fe3277204080..205e5dd084564f 100644
--- a/redshift/attributes/attributes.dm
+++ b/redshift/attributes_and_skills/attributes.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon
+/mob/living
/// List of all of this mob's attributes and their values
var/list/attributes = list(
ATTRIBUTE_AURA = DEFAULT_ATTRIBUTE_SCORE,
@@ -10,39 +10,39 @@
)
/// List of current attribute modifiers, ATTRIBUTE_WHATEVER = modifier number
var/list/attribute_modifiers = list(
- ATTRIBUTE_AURA = 0,
- ATTRIBUTE_SMARTS = 0,
- ATTRIBUTE_INTUITION = 0,
- ATTRIBUTE_MUSCLE = 0,
- ATTRIBUTE_REFLEX = 0,
- ATTRIBUTE_AWARENESS = 0,
+ ATTRIBUTE_AURA = -INFINITY,
+ ATTRIBUTE_SMARTS = 3,
+ ATTRIBUTE_INTUITION = -3,
+ ATTRIBUTE_MUSCLE = -4,
+ ATTRIBUTE_REFLEX = 1,
+ ATTRIBUTE_AWARENESS = 5,
)
-/mob/living/carbon/verb/view_attributes()
+/mob/living/verb/view_attributes()
set name = "Attributes"
set category = "Redshift"
set desc = "View your character's attributes."
attributes_to_chat()
/// Prints a box with all of the carbon's attributes to chat
-/mob/living/carbon/proc/attributes_to_chat()
+/mob/living/proc/attributes_to_chat()
var/attributes_text = ""
for(var/attribute in attributes)
var/modifier = attribute_modifiers[attribute]
- attributes_text += "[capitalize(attribute)] ([get_attribute_title(attribute, get_attribute_score(attribute))])"
+ attributes_text += "[get_attribute_title(attribute, get_attribute_score(attribute))] [capitalize(attribute)]"
attributes_text += " - [get_attribute_score(attribute)]"
if(modifier == 0)
attributes_text += "
"
continue
- attributes_text += " - [attributes[attribute]][modifier < 0 ? span_red("[modifier]") : span_green("+[modifier]")]
"
+ attributes_text += "([attributes[attribute]][modifier < 0 ? span_red("[modifier]") : span_green("+[modifier]")])
"
to_chat(src, fieldset_block("Attributes", attributes_text, "boxed_message"))
/// Adjusts a carbon's attribute modifier by a given amount
-/mob/living/carbon/proc/adjust_attribute_modifier(attribute, adjustment)
+/mob/living/proc/adjust_attribute_modifier(attribute, adjustment)
attribute_modifiers[attribute] += adjustment
/// Get's a carbon's score for an attribute, optionally adjusted by modifiers
-/mob/living/carbon/proc/get_attribute_score(attribute, modified = TRUE)
+/mob/living/proc/get_attribute_score(attribute, modified = TRUE)
if(!attribute)
return 0
var/score = attributes[attribute]
@@ -51,8 +51,30 @@
score += attribute_modifiers[attribute]
return score
+/// Returns a modifier to a chance to get hit by a melee attack depending on both awareness and reflex
+/mob/living/proc/get_melee_dodge_modifier()
+ var/reflex_score = get_attribute_score(ATTRIBUTE_REFLEX, TRUE)
+ var/awareness_score = get_attribute_score(ATTRIBUTE_AWARENESS, TRUE)
+ var/dodge_attribute_score = (reflex_score + awareness_score) / 2
+ switch(dodge_attribute_score)
+ if(1 to 5)
+ return 0
+ if(6 to MAX_ATTRIBUTE_SCORE)
+ return (dodge_attribute_score - 5) * -5
+
+/// Returns a multiplied damage amount based on the user's relevant attribute
+/mob/living/proc/get_weapon_damage_mod(relevant_attribute, original_force)
+ var/relevant_score = get_attribute_score(relevant_attribute)
+ switch(relevant_score)
+ if(0 to 4) // * 0.5 at 0, * 0.9 at 4
+ return original_force * (0.5 + (0.1 * relevant_score))
+ if(5 to 7)
+ return original_force
+ if(8 to MAX_ATTRIBUTE_SCORE) // * 1.1 (8) to * 1.3 (10)
+ return original_force * (1 + (0.1 * (relevant_score - 7)))
+
/// Returns a multiplied time for a given attribute or attributes via a list and an original time
-/proc/attributes_adjusted_time(mob/living/carbon/holder, list/attributes_to_check, original_time)
+/proc/attributes_adjusted_time(mob/living/holder, list/attributes_to_check, original_time)
if(isnull(holder) || isnull(attributes_to_check) || isnull(original_time))
return
var/score_to_use = 0
@@ -75,15 +97,16 @@
/// Returns a title for a specific attribute level per attribute
/proc/get_attribute_title(attribute, score)
+ score = clamp(score, 0, MAX_ATTRIBUTE_SCORE)
switch(attribute)
if(ATTRIBUTE_AURA)
switch(score)
if(0)
- return "Indebted"
+ return "Bankrupt"
if(1)
return "Zero"
if(2)
- return "Nobody"
+ return "Unobservable"
if(3 to 4)
return "Small-Time"
if(5 to 8)
@@ -93,7 +116,7 @@
if(ATTRIBUTE_SMARTS)
switch(score)
if(0)
- return "Thoughtless"
+ return "Zero"
if(1 to 3)
return "Low"
if(4 to 6)
@@ -115,7 +138,7 @@
if(8 to 9)
return "Quick"
if(10)
- return "Engineer"
+ return "Engineer's"
if(ATTRIBUTE_MUSCLE)
switch(score)
if(0 to 1)
@@ -141,7 +164,7 @@
if(ATTRIBUTE_AWARENESS)
switch(score)
if(0)
- return "Practically Blind"
+ return "Practically No"
if(1 to 2)
return "Unobservant"
if(3 to 4)
diff --git a/redshift/attributes_and_skills/skills.dm b/redshift/attributes_and_skills/skills.dm
new file mode 100644
index 00000000000000..215226b2816a0d
--- /dev/null
+++ b/redshift/attributes_and_skills/skills.dm
@@ -0,0 +1,82 @@
+/mob/living
+ /// List of all skills a mob has
+ var/list/skills = list(
+ // Weapons skills
+ SKILL_WEAPON_ECCENTRIC = 0
+ )
+
+/// Get's a mob's score for a skill
+/mob/living/proc/get_skill_value(skill)
+ if(!skill)
+ return 0
+ var/score = skills[skill]
+ return score
+
+/mob/living/verb/view_skills()
+ set name = "Skills"
+ set category = "Redshift"
+ set desc = "View your character's skills."
+ skills_to_chat()
+
+/// Prints a box with all of the mob's skills to chat
+/mob/living/proc/skills_to_chat()
+ var/skills_text = ""
+ for(var/skill in skills)
+ skills_text += "[get_skill_title(get_skill_value(skill))] [skill]"
+ skills_text += " - [get_skill_value(skill)]"
+ to_chat(src, fieldset_block("Skills", skills_text, "boxed_message"))
+
+/// Returns a title for a skill value
+/proc/get_skill_title(score)
+ switch(score)
+ if(0)
+ return "Miserable"
+ if(1)
+ return "Novice"
+ if(2)
+ return "Adequate"
+ if(3)
+ return "Competent"
+ if(4)
+ return "Skilled"
+ if(5)
+ return "Proficient"
+ if(6)
+ return "Talented"
+ if(7)
+ return "Adept"
+ if(8)
+ return "Expert"
+ if(9)
+ return "Professional"
+ if(10)
+ return "Accomplished"
+ if(11)
+ return "Elite"
+ if(12)
+ return "Master"
+ if(13)
+ return "High Master"
+ if(14)
+ return "Grand Master"
+ if(15)
+ return "Legendary"
+
+/// Returns a modifier for chance to hit the target (or target limb) depending on relevant weapon skill
+/mob/living/proc/target_chance_skill_modifier(target_skill)
+ var/skill_value = get_skill_value(target_skill)
+ switch(skill_value)
+ if(0)
+ return -25
+ if(1 to 2)
+ return -10
+ if(3 to 4)
+ return -5
+ if(5 to 6)
+ return 0
+ if(7 to 10)
+ return 5
+ if(11 to 13)
+ return 10
+ if(14 to INFINITY)
+ return 25
diff --git a/redshift/species/species_types/aquatic/bodyparts.dm b/redshift/species/species_types/aquatic/bodyparts.dm
index c82af4f3a3d4dc..18e5119ef8a15e 100644
--- a/redshift/species/species_types/aquatic/bodyparts.dm
+++ b/redshift/species/species_types/aquatic/bodyparts.dm
@@ -17,7 +17,6 @@
limb_id = SPECIES_AQUATIC
should_draw_greyscale = TRUE
unarmed_attack_verbs = list("slash", "scratch", "claw")
- unarmed_attack_verbs = list("slashed", "scratched", "clawed")
grappled_attack_verb = "lacerate"
grappled_attack_verb_continuous = "lacerates"
unarmed_attack_effect = ATTACK_EFFECT_CLAW
@@ -29,7 +28,6 @@
limb_id = SPECIES_AQUATIC
should_draw_greyscale = TRUE
unarmed_attack_verbs = list("slash", "scratch", "claw")
- unarmed_attack_verbs = list("slashed", "scratched", "clawed")
grappled_attack_verb = "lacerate"
grappled_attack_verb_continuous = "lacerates"
unarmed_attack_effect = ATTACK_EFFECT_CLAW
diff --git a/redshift/species/species_types/avian/bodyparts.dm b/redshift/species/species_types/avian/bodyparts.dm
index bf19d7d9be5a7f..e5f26cb88c526b 100644
--- a/redshift/species/species_types/avian/bodyparts.dm
+++ b/redshift/species/species_types/avian/bodyparts.dm
@@ -17,7 +17,6 @@
limb_id = SPECIES_AVIAN
should_draw_greyscale = TRUE
unarmed_attack_verbs = list("slash", "scratch", "claw")
- unarmed_attack_verbs = list("slashed", "scratched", "clawed")
grappled_attack_verb = "lacerate"
grappled_attack_verb_continuous = "lacerates"
unarmed_attack_effect = ATTACK_EFFECT_CLAW
@@ -29,7 +28,6 @@
limb_id = SPECIES_AVIAN
should_draw_greyscale = TRUE
unarmed_attack_verbs = list("slash", "scratch", "claw")
- unarmed_attack_verbs = list("slashed", "scratched", "clawed")
grappled_attack_verb = "lacerate"
grappled_attack_verb_continuous = "lacerates"
unarmed_attack_effect = ATTACK_EFFECT_CLAW
diff --git a/redshift/species/species_types/furries/bodyparts.dm b/redshift/species/species_types/furries/bodyparts.dm
index 432b0e96af9023..944648fd00f7f1 100644
--- a/redshift/species/species_types/furries/bodyparts.dm
+++ b/redshift/species/species_types/furries/bodyparts.dm
@@ -17,7 +17,6 @@
limb_id = SPECIES_FURRIES
should_draw_greyscale = TRUE
unarmed_attack_verbs = list("slash", "scratch", "claw")
- unarmed_attack_verbs = list("slashed", "scratched", "clawed")
grappled_attack_verb = "lacerate"
grappled_attack_verb_continuous = "lacerates"
unarmed_attack_effect = ATTACK_EFFECT_CLAW
@@ -29,7 +28,6 @@
limb_id = SPECIES_FURRIES
should_draw_greyscale = TRUE
unarmed_attack_verbs = list("slash", "scratch", "claw")
- unarmed_attack_verbs = list("slashed", "scratched", "clawed")
grappled_attack_verb = "lacerate"
grappled_attack_verb_continuous = "lacerates"
unarmed_attack_effect = ATTACK_EFFECT_CLAW
diff --git a/redshift/species/species_types/insects/bodyparts.dm b/redshift/species/species_types/insects/bodyparts.dm
index 6ae6a97e202b4a..88dffe56995809 100644
--- a/redshift/species/species_types/insects/bodyparts.dm
+++ b/redshift/species/species_types/insects/bodyparts.dm
@@ -17,7 +17,6 @@
limb_id = SPECIES_INSECT
should_draw_greyscale = TRUE
unarmed_attack_verbs = list("slash", "scratch", "claw")
- unarmed_attack_verbs = list("slashed", "scratched", "clawed")
grappled_attack_verb = "lacerate"
grappled_attack_verb_continuous = "lacerates"
unarmed_attack_effect = ATTACK_EFFECT_CLAW
@@ -29,7 +28,6 @@
limb_id = SPECIES_INSECT
should_draw_greyscale = TRUE
unarmed_attack_verbs = list("slash", "scratch", "claw")
- unarmed_attack_verbs = list("slashed", "scratched", "clawed")
grappled_attack_verb = "lacerate"
grappled_attack_verb_continuous = "lacerates"
unarmed_attack_effect = ATTACK_EFFECT_CLAW
diff --git a/redshift/species/species_types/reptile/bodyparts.dm b/redshift/species/species_types/reptile/bodyparts.dm
index 03cfcfda6e0122..0fd9194ed788b3 100644
--- a/redshift/species/species_types/reptile/bodyparts.dm
+++ b/redshift/species/species_types/reptile/bodyparts.dm
@@ -1,2 +1,8 @@
/obj/item/bodypart/head/lizard
head_flags = HEAD_DEFAULT_FEATURES
+
+/obj/item/bodypart/arm/left/lizard
+ unarmed_attack_verbs = list("slash", "scratch", "claw")
+
+/obj/item/bodypart/arm/right/lizard
+ unarmed_attack_verbs = list("slash", "scratch", "claw")
diff --git a/redshift/swing_system/mob_attack_messages.dm b/redshift/swing_system/mob_attack_messages.dm
new file mode 100644
index 00000000000000..2623bc2e4f576c
--- /dev/null
+++ b/redshift/swing_system/mob_attack_messages.dm
@@ -0,0 +1,15 @@
+/// Displays a message for if an attack was dodged due to rng
+/mob/living/proc/make_attack_dodge_message(attacking_item, user)
+ var/attack_message_spectator = "[src] misses with [attacking_item]!"
+ var/attack_message_victim = "Something misses you with [attacking_item]!"
+ var/attack_message_attacker = "You miss [src] with [attacking_item]!"
+ if(user in viewers(src, null))
+ attack_message_spectator = "[user] misses [src] with [attacking_item]!"
+ attack_message_victim = "[user] misses you with [attacking_item]!"
+ if(user == src)
+ attack_message_victim = "You miss yourself with [attacking_item]."
+ visible_message(span_danger("[attack_message_spectator]"),\
+ span_selfwarning("[attack_message_victim]"), null, COMBAT_MESSAGE_RANGE, user)
+ if(is_blind())
+ to_chat(src, span_selfwarning("Someone misses you!"))
+ to_chat(user, span_danger("[attack_message_attacker]"))
diff --git a/redshift/swing_system/swing.dm b/redshift/swing_system/swing.dm
index decac013aa6d90..36371ebc249279 100644
--- a/redshift/swing_system/swing.dm
+++ b/redshift/swing_system/swing.dm
@@ -5,6 +5,10 @@
var/secondary_swing_attack_speed
/// If the weapon can hit multiple living targets in swing attacks
var/swing_multihits = FALSE
+ /// If this item uses a specific skill define for combat when determining hit chance
+ var/combat_skill_hit_chance = SKILL_WEAPON_ECCENTRIC
+ /// If this weapon uses a specific attribute define for doing more or less damage
+ var/combat_attribute_damage_modifier = null
/obj/item/Initialize(mapload)
. = ..()
diff --git a/tgstation.dme b/tgstation.dme
index fb5d9814dab82d..a434af1dc4ef6a 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -436,7 +436,7 @@
#include "code\__DEFINES\traits\macros.dm"
#include "code\__DEFINES\traits\sources.dm"
#include "code\__DEFINES\~redshift_defines\armor.dm"
-#include "code\__DEFINES\~redshift_defines\attributes.dm"
+#include "code\__DEFINES\~redshift_defines\attributes_and_skills.dm"
#include "code\__DEFINES\~redshift_defines\jobs.dm"
#include "code\__DEFINES\~redshift_defines\language.dm"
#include "code\__DEFINES\~redshift_defines\loadout.dm"
@@ -7233,7 +7233,8 @@
#include "redshift\armor_system\check_armor.dm"
#include "redshift\armor_system\debug_armors_delete_later.dm"
#include "redshift\armor_system\item_changes.dm"
-#include "redshift\attributes\attributes.dm"
+#include "redshift\attributes_and_skills\attributes.dm"
+#include "redshift\attributes_and_skills\skills.dm"
#include "redshift\carry_weight\core.dm"
#include "redshift\character_customization\preferences.dm"
#include "redshift\character_customization\preferences_setup.dm"
@@ -7309,7 +7310,7 @@
#include "redshift\species\species_types\insects\organs.dm"
#include "redshift\species\species_types\reptile\bodyparts.dm"
#include "redshift\species\species_types\reptile\reptile.dm"
-#include "redshift\species\species_types\slimes\slimes.dm"
#include "redshift\swing_system\helpers.dm"
+#include "redshift\swing_system\mob_attack_messages.dm"
#include "redshift\swing_system\swing.dm"
// END_INCLUDE