Merge branch 'master' into job-menu-improvements

This commit is contained in:
Poojawa
2019-08-02 11:55:28 -05:00
committed by GitHub
47 changed files with 712 additions and 578 deletions

10
code/__DEFINES/melee.dm Normal file
View File

@@ -0,0 +1,10 @@
//Martial arts defines
#define MARTIALART_BOXING "boxing"
#define MARTIALART_WRESTLING "wrestling"
#define MARTIALART_SLEEPINGCARP "sleeping carp"
#define MARTIALART_PSYCHOBRAWL "psychotic brawling"
#define MARTIALART_MUSHPUNCH "mushroom punch"
#define MARTIALART_KRAVMAGA "krav maga"
#define MARTIALART_CQC "CQC"
#define MARTIALART_PLASMAFIST "plasma fist"

View File

@@ -2,6 +2,7 @@
var/name = "Martial Art"
var/streak = ""
var/max_streak_length = 6
var/id = "" //ID, used by mind/has_martialartcode\game\objects\items\granters.dm:345:error: user.mind.has_martialart: undefined proccode\game\objects\items\granters.dm:345:error: user.mind.has_martialart: undefined proccode\game\objects\items\granters.dm:345:error: user.mind.has_martialart: undefined proccode\game\objects\items\granters.dm:345:error: user.mind.has_martialart: undefined proccode\game\objects\items\granters.dm:345:error: user.mind.has_martialart: undefined proc
var/current_target
var/datum/martial_art/base // The permanent style. This will be null unless the martial art is temporary
var/deflection_chance = 0 //Chance to deflect projectiles

View File

@@ -1,5 +1,6 @@
/datum/martial_art/boxing
name = "Boxing"
id = MARTIALART_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>")

View File

@@ -6,6 +6,7 @@
/datum/martial_art/cqc
name = "CQC"
id = MARTIALART_CQC
help_verb = /mob/living/carbon/human/proc/CQC_help
block_chance = 75
var/just_a_cook = FALSE

View File

@@ -1,5 +1,6 @@
/datum/martial_art/krav_maga
name = "Krav Maga"
id = MARTIALART_KRAVMAGA
var/datum/action/neck_chop/neckchop = new/datum/action/neck_chop()
var/datum/action/leg_sweep/legsweep = new/datum/action/leg_sweep()
var/datum/action/lung_punch/lungpunch = new/datum/action/lung_punch()
@@ -92,7 +93,7 @@
"<span class='userdanger'>[A] leg sweeps you!</span>")
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
D.apply_damage(5, BRUTE)
D.Knockdown(40, override_hardstun = 0.01, 25)
D.Knockdown(40, override_hardstun = 0.01, override_stamdmg = 25)
log_combat(A, D, "leg sweeped")
return 1

View File

@@ -1,5 +1,6 @@
/datum/martial_art/mushpunch
name = "Mushroom Punch"
id = MARTIALART_MUSHPUNCH
/datum/martial_art/mushpunch/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
var/atk_verb

View File

@@ -4,6 +4,7 @@
/datum/martial_art/plasma_fist
name = "Plasma Fist"
id = MARTIALART_PLASMAFIST
help_verb = /mob/living/carbon/human/proc/plasma_fist_help

View File

@@ -1,5 +1,6 @@
/datum/martial_art/psychotic_brawling
name = "Psychotic Brawling"
id = MARTIALART_PSYCHOBRAWL
/datum/martial_art/psychotic_brawling/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
return psycho_attack(A,D)

View File

@@ -6,6 +6,7 @@
/datum/martial_art/the_sleeping_carp
name = "The Sleeping Carp"
id = MARTIALART_SLEEPINGCARP
deflection_chance = 100
reroute_deflection = TRUE
no_guns = TRUE

View File

@@ -10,6 +10,7 @@
/datum/martial_art/wrestling
name = "Wrestling"
id = MARTIALART_WRESTLING
var/datum/action/slam/slam = new/datum/action/slam()
var/datum/action/throw_wrassle/throw_wrassle = new/datum/action/throw_wrassle()
var/datum/action/kick/kick = new/datum/action/kick()

View File

@@ -64,6 +64,8 @@
var/force_escaped = FALSE // Set by Into The Sunset command of the shuttle manipulator
var/list/learned_recipes //List of learned recipe TYPES.
/datum/mind/New(var/key)
src.key = key
soulOwner = src
@@ -779,6 +781,11 @@
mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist)
mind.active = 1 //indicates that the mind is currently synced with a client
/datum/mind/proc/has_martialart(var/string)
if(martial_art && martial_art.id == string)
return martial_art
return FALSE
/mob/dead/new_player/sync_mind()
return

View File

@@ -177,6 +177,8 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
desc = "A device used to rapidly pipe things."
icon = 'icons/obj/tools.dmi'
icon_state = "rpd"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
flags_1 = CONDUCT_1
force = 10
throwforce = 10

View File

@@ -1,4 +1,3 @@
///books that teach things (intrinsic actions like bar flinging, spells like fireball or smoke, or martial arts)///
/obj/item/book/granter
@@ -13,19 +12,50 @@
/obj/item/book/granter/proc/turn_page(mob/user)
playsound(user, pick('sound/effects/pageturn1.ogg','sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg'), 30, 1)
if(do_after(user,50, user))
to_chat(user, "<span class='notice'>[pick(remarks)]</span>")
if(remarks.len)
to_chat(user, "<span class='notice'>[pick(remarks)]</span>")
else
to_chat(user, "<span class='notice'>You keep reading...</span>")
return TRUE
return FALSE
/obj/item/book/granter/proc/recoil(mob/user) //nothing so some books can just return
/obj/item/book/granter/proc/already_known(mob/user)
return FALSE
/obj/item/book/granter/proc/on_reading_start(mob/user)
to_chat(user, "<span class='notice'>You start reading [name]...</span>")
/obj/item/book/granter/proc/on_reading_stopped(mob/user)
to_chat(user, "<span class='notice'>You stop reading...</span>")
/obj/item/book/granter/proc/on_reading_finished(mob/user)
to_chat(user, "<span class='notice'>You finish reading [name]!</span>")
/obj/item/book/granter/proc/onlearned(mob/user)
used = TRUE
/obj/item/book/granter/attack_self(mob/user)
if(reading == TRUE)
if(reading)
to_chat(user, "<span class='warning'>You're already reading this!</span>")
return FALSE
if(already_known(user))
return FALSE
if(used && oneuse)
recoil(user)
else
on_reading_start(user)
reading = TRUE
for(var/i=1, i<=pages_to_mastery, i++)
if(!turn_page(user))
on_reading_stopped()
reading = FALSE
return
if(do_after(user,50, user))
on_reading_finished(user)
reading = FALSE
return TRUE
///ACTION BUTTONS///
@@ -34,33 +64,23 @@
var/granted_action
var/actionname = "catching bugs" //might not seem needed but this makes it so you can safely name action buttons toggle this or that without it fucking up the granter, also caps
/obj/item/book/granter/action/attack_self(mob/user)
. = ..()
if(!.)
return
/obj/item/book/granter/action/already_known(mob/user)
if(!granted_action)
return
var/datum/action/G = new granted_action
return TRUE
for(var/datum/action/A in user.actions)
if(A.type == G.type)
if(A.type == granted_action)
to_chat(user, "<span class='notice'>You already know all about [actionname].</span>")
qdel(G)
return
if(used == TRUE && oneuse == TRUE)
recoil(user)
else
to_chat(user, "<span class='notice'>You start reading about [actionname]...</span>")
reading = TRUE
for(var/i=1, i<=pages_to_mastery, i++)
if(!turn_page(user))
to_chat(user, "<span class='notice'>You stop reading...</span>")
reading = FALSE
qdel(G)
return
if(do_after(user,50, user))
to_chat(user, "<span class='notice'>You feel like you've got a good handle on [actionname]!</span>")
G.Grant(user)
reading = FALSE
return TRUE
return FALSE
/obj/item/book/granter/action/on_reading_start(mob/user)
to_chat(user, "<span class='notice'>You start reading about [actionname]...</span>")
/obj/item/book/granter/action/on_reading_finished(mob/user)
to_chat(user, "<span class='notice'>You feel like you've got a good handle on [actionname]!</span>")
var/datum/action/G = new granted_action
G.Grant(user)
onlearned(user)
/obj/item/book/granter/action/drink_fling
granted_action = /datum/action/innate/drink_fling
@@ -120,38 +140,28 @@
var/spell
var/spellname = "conjure bugs"
/obj/item/book/granter/spell/attack_self(mob/user)
. = ..()
if(!.)
return
/obj/item/book/granter/spell/already_known(mob/user)
if(!spell)
return
var/obj/effect/proc_holder/spell/S = new spell
return TRUE
for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list)
if(knownspell.type == S.type)
if(knownspell.type == spell)
if(user.mind)
if(iswizard(user))
to_chat(user,"<span class='notice'>You're already far more versed in this spell than this flimsy howto book can provide.</span>")
to_chat(user,"<span class='notice'>You're already far more versed in this spell than this flimsy how-to book can provide.</span>")
else
to_chat(user,"<span class='notice'>You've already read this one.</span>")
return
if(used == TRUE && oneuse == TRUE)
recoil(user)
else
to_chat(user, "<span class='notice'>You start reading about casting [spellname]...</span>")
reading = TRUE
for(var/i=1, i<=pages_to_mastery, i++)
if(!turn_page(user))
to_chat(user, "<span class='notice'>You stop reading...</span>")
reading = FALSE
qdel(S)
return
if(do_after(user,50, user))
to_chat(user, "<span class='notice'>You feel like you've experienced enough to cast [spellname]!</span>")
user.mind.AddSpell(S)
user.log_message("learned the spell [spellname] ([S])", LOG_ATTACK, color="orange")
onlearned(user)
reading = FALSE
return TRUE
return FALSE
/obj/item/book/granter/spell/on_reading_start(mob/user)
to_chat(user, "<span class='notice'>You start reading about casting [spellname]...</span>")
/obj/item/book/granter/spell/on_reading_finished(mob/user)
to_chat(user, "<span class='notice'>You feel like you've experienced enough to cast [spellname]!</span>")
var/obj/effect/proc_holder/spell/S = new spell
user.mind.AddSpell(S)
user.log_message("learned the spell [spellname] ([S])", LOG_ATTACK, color="orange")
onlearned(user)
/obj/item/book/granter/spell/recoil(mob/user)
user.visible_message("<span class='warning'>[src] glows in a black light!</span>")
@@ -280,7 +290,8 @@
if(ishuman(user))
to_chat(user,"<font size='15' color='red'><b>HORSIE HAS RISEN</b></font>")
var/obj/item/clothing/magichead = new /obj/item/clothing/mask/horsehead/cursed(user.drop_location())
user.dropItemToGround(user.wear_mask, TRUE)
if(!user.dropItemToGround(user.wear_mask))
qdel(user.wear_mask)
user.equip_to_slot_if_possible(magichead, SLOT_WEAR_MASK, TRUE, TRUE)
qdel(src)
else
@@ -327,35 +338,24 @@
var/martialname = "bug jitsu"
var/greet = "You feel like you have mastered the art in breaking code. Nice work, jackass."
/obj/item/book/granter/martial/attack_self(mob/user)
. = ..()
if(!.)
return
/obj/item/book/granter/martial/already_known(mob/user)
if(!martial)
return
return TRUE
var/datum/martial_art/MA = martial
if(user.mind.has_martialart(initial(MA.id)))
to_chat(user,"<span class='warning'>You already know [martialname]!</span>")
return TRUE
return FALSE
/obj/item/book/granter/martial/on_reading_start(mob/user)
to_chat(user, "<span class='notice'>You start reading about [martialname]...</span>")
/obj/item/book/granter/martial/on_reading_finished(mob/user)
to_chat(user, "[greet]")
var/datum/martial_art/MA = new martial
if(user.mind.martial_art)
for(var/datum/martial_art/knownmartial in user.mind.martial_art)
if(knownmartial.type == MA.type)
to_chat(user,"<span class='warning'>You already know [martialname]!</span>")
return
if(used == TRUE && oneuse == TRUE)
recoil(user)
else
to_chat(user, "<span class='notice'>You start reading about [martialname]...</span>")
reading = TRUE
for(var/i=1, i<=pages_to_mastery, i++)
if(!turn_page(user))
to_chat(user, "<span class='notice'>You stop reading...</span>")
reading = FALSE
qdel(MA)
return
if(do_after(user,50, user))
to_chat(user, "[greet]")
MA.teach(user)
user.log_message("learned the martial art [martialname] ([MA])", LOG_ATTACK, color="orange")
onlearned(user)
reading = FALSE
MA.teach(user)
user.log_message("learned the martial art [martialname] ([MA])", LOG_ATTACK, color="orange")
onlearned(user)
/obj/item/book/granter/martial/cqc
martial = /datum/martial_art/cqc
@@ -416,3 +416,18 @@
icon_state = "blankscroll"
// I did not include mushpunch's grant, it is not a book and the item does it just fine.
//Crafting Recipe books
/obj/item/book/granter/crafting_recipe
var/list/crafting_recipe_types = list()
/obj/item/book/granter/crafting_recipe/on_reading_finished(mob/user)
. = ..()
if(!user.mind)
return
for(var/crafting_recipe_type in crafting_recipe_types)
var/datum/crafting_recipe/R = crafting_recipe_type
user.mind.teach_crafting_recipe(crafting_recipe_type)
to_chat(user,"<span class='notice'>You learned how to make [initial(R.name)].</span>")

View File

@@ -21,7 +21,7 @@
return
if(!H.mind)
return
if(istype(H.mind.martial_art, /datum/martial_art/krav_maga))
if(H.mind.has_martialart(MARTIALART_KRAVMAGA))
style.remove(H)
else
style.teach(H,1)

View File

@@ -18,7 +18,7 @@
/obj/item/stack/medical/attack(mob/living/M, mob/user)
if(M.stat == DEAD)
if(M.stat == DEAD && !stop_bleeding)
var/t_him = "it"
if(M.gender == MALE)
t_him = "him"

View File

@@ -230,24 +230,23 @@
/obj/effect/proc_holder/changeling/sting/LSD
name = "Hallucination Sting"
desc = "Causes terror in the target."
helptext = "We evolve the ability to sting a target with a powerful hallucinogenic chemical. The target does not notice they have been stung, and the effect begins after a few seconds."
desc = "Causes terror in the target and deals a minor amount of toxin damage."
helptext = "We evolve the ability to sting a target with a powerful toxic hallucinogenic chemical. The target does not notice they have been stung, and the effect begins instantaneously. This ability is somewhat loud, and carries a small risk of our blood gaining violent sensitivity to heat."
sting_icon = "sting_lsd"
chemical_cost = 10
dna_cost = 1
loudness = 1
action_icon = 'icons/mob/actions/actions_changeling.dmi'
action_icon_state = "ling_sting_lsd"
action_background_icon_state = "bg_ling"
/obj/effect/proc_holder/changeling/sting/LSD/sting_action(mob/user, mob/living/carbon/target)
/obj/effect/proc_holder/changeling/sting/LSD/sting_action(mob/user, mob/target)
log_combat(user, target, "stung", "LSD sting")
addtimer(CALLBACK(src, .proc/hallucination_time, target), rand(100,200))
if(target.reagents)
target.reagents.add_reagent("regenerative_materia", 5)
target.reagents.add_reagent("mindbreaker", 5)
return TRUE
/obj/effect/proc_holder/changeling/sting/LSD/proc/hallucination_time(mob/living/carbon/target)
if(target)
target.hallucination = max(90, target.hallucination)
/obj/effect/proc_holder/changeling/sting/cryo
name = "Cryogenic Sting"
desc = "We silently sting a human with a cocktail of chemicals that freeze them."

View File

@@ -317,6 +317,8 @@
var/list/cant_craft = list()
for(var/rec in GLOB.crafting_recipes)
var/datum/crafting_recipe/R = rec
if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
continue
if((R.category != cur_category) || (R.subcategory != cur_subcategory))
continue
if(check_contents(R, surroundings))
@@ -431,3 +433,10 @@
data["tool_text"] = tool_text
return data
//Mind helpers
/datum/mind/proc/teach_crafting_recipe(R)
if(!learned_recipes)
learned_recipes = list()
learned_recipes |= R

View File

@@ -9,6 +9,7 @@
var/chem_catalysts[] = list() //like tools but for reagents
var/category = CAT_NONE //where it shows up in the crafting UI
var/subcategory = CAT_NONE
var/always_availible = TRUE //Set to FALSE if it needs to be learned first.
/datum/crafting_recipe/pin_removal
name = "Pin Removal"

View File

@@ -283,7 +283,7 @@
tastes = list("blackberry" = 2, "strawberries" = 2, "chocolate" = 2, "sweetness" = 2,"cake" = 3)
foodtype = GRAIN | DAIRY | FRUIT | SUGAR
obj/item/reagent_containers/food/snacks/store/cake/holy_cake
/obj/item/reagent_containers/food/snacks/store/cake/holy_cake
name = "angel food cake"
desc = "A cake made for angels and chaplains alike! Contains holy water."
icon = 'modular_citadel/icons/obj/food/cake.dmi'
@@ -322,7 +322,7 @@ obj/item/reagent_containers/food/snacks/store/cake/pound_cake
tastes = list("cake" = 5, "sweetness" = 5, "batter" = 1)
foodtype = GRAIN | DAIRY | SUGAR | JUNKFOOD
obj/item/reagent_containers/food/snacks/store/cake/hardware_cake
/obj/item/reagent_containers/food/snacks/store/cake/hardware_cake
name = "hardware cake"
desc = "A cake that is made with electronic boards and leaks acid..."
icon = 'modular_citadel/icons/obj/food/cake.dmi'

View File

@@ -432,7 +432,21 @@
/mob/dead/new_player/proc/LateChoices()
var/list/dat = list("<div class='notice'>Round Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]</div>")
var/level = "green"
switch(GLOB.security_level)
if(SEC_LEVEL_GREEN)
level = "green"
if(SEC_LEVEL_BLUE)
level = "blue"
if(SEC_LEVEL_AMBER)
level = "amber"
if(SEC_LEVEL_RED)
level = "red"
if(SEC_LEVEL_DELTA)
level = "delta"
var/dat = "<div class='notice'>Round Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]<br>Alert Level: [capitalize(level)]</div>"
if(SSshuttle.emergency)
switch(SSshuttle.emergency.mode)
if(SHUTTLE_ESCAPE)
@@ -601,4 +615,4 @@
message_admins("[src.ckey] just got booted back to lobby with no jobs enabled, but antag rolling enabled. Likely antag rolling abuse.")
return FALSE //This is the only case someone should actually be completely blocked from antag rolling as well
return TRUE
return TRUE

View File

@@ -699,9 +699,10 @@
clear_fullscreen("critvision")
//Oxygen damage overlay
if(oxyloss)
var/windedup = getOxyLoss() + getStaminaLoss() * 0.2 + stamdamageoverlaytemp
if(windedup)
var/severity = 0
switch(oxyloss)
switch(windedup)
if(10 to 20)
severity = 1
if(20 to 25)

View File

@@ -61,5 +61,6 @@
var/next_hallucination = 0
var/cpr_time = 1 //CPR cooldown.
var/damageoverlaytemp = 0
var/stamdamageoverlaytemp = 0
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects

View File

@@ -1781,6 +1781,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(CLONE)
H.adjustCloneLoss(damage * hit_percent * H.physiology.clone_mod)
if(STAMINA)
H.stamdamageoverlaytemp = 20
if(BP)
if(damage > 0 ? BP.receive_damage(0, 0, damage * hit_percent * H.physiology.stamina_mod) : BP.heal_damage(0, 0, abs(damage * hit_percent * H.physiology.stamina_mod), only_robotic = FALSE, only_organic = FALSE))
H.update_stamina()

View File

@@ -4,8 +4,9 @@
if(notransform)
return
if(damageoverlaytemp)
if(damageoverlaytemp || stamdamageoverlaytemp)
damageoverlaytemp = 0
stamdamageoverlaytemp = 0
update_damage_hud()
if(stat != DEAD) //Reagent processing needs to come before breathing, to prevent edge cases.

View File

@@ -62,3 +62,8 @@
e_cost = 200
select_name = "stun"
projectile_type = /obj/item/projectile/energy/tesla/revolver
/obj/item/ammo_casing/energy/emitter
fire_sound = 'sound/weapons/emitter.ogg'
e_cost = 2000 //20,000 is in the cell making this 10 shots before reload
projectile_type = /obj/item/projectile/beam/emitter

View File

@@ -304,3 +304,22 @@
/obj/item/gun/energy/gravity_gun/security
pin = /obj/item/firing_pin
//Emitter Gun
/obj/item/gun/energy/emitter
name = "Emitter Carbine"
desc = "A small emitter fitted into a handgun case, do to size constraints and safety it can only shoot about ten times when fully charged."
icon_state = "emitter_carbine"
force = 12
w_class = WEIGHT_CLASS_SMALL
cell_type = /obj/item/stock_parts/cell/super
ammo_type = list(/obj/item/ammo_casing/energy/emitter)
/obj/item/gun/energy/emitter/update_icon()
..()
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
if(!QDELETED(cell) && (cell.charge > shot.e_cost))
add_overlay("emitter_carbine_empty")
else
add_overlay("emitter_carbine")

View File

@@ -414,8 +414,8 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/dangerous/rapier
name = "Rapier"
desc = "A fancy rapier with a diamond tip piercing anything that it comes into contack with. \
The rapier comes with its own shielf, this is rather noticeable as only the captain is known to carry a shielf. \
The shielf itself can be used to block melee attacks only. Its also jet black colours."
The rapier comes with its own sheath, this is rather noticeable as only the captain is known to carry a sheath. \
The sheath itself can be used to block melee attacks only. Its also jet black colours."
item = /obj/item/storage/belt/sabre/rapier
cost = 8
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
@@ -1837,6 +1837,13 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
item = /obj/item/clothing/shoes/clown_shoes/taeclowndo
restricted_roles = list("Clown")
/datum/uplink_item/role_restricted/emitter_cannon
name = "Emitter Cannon"
desc = "A small emitter fitted into a gun case, do to size constraints and safety it can only shoot about ten times when fully charged."
cost = 5 //Low ammo, and deals same as 10mm but emp-able
item = /obj/item/gun/energy/emitter
restricted_roles = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
// Pointless
/datum/uplink_item/badass
category = "(Pointless) Badassery"