Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into Ghommie-cit765
This commit is contained in:
@@ -5,6 +5,61 @@
|
||||
/datum/brain_trauma/magic
|
||||
resilience = TRAUMA_RESILIENCE_LOBOTOMY
|
||||
|
||||
/datum/brain_trauma/magic/lumiphobia
|
||||
name = "Lumiphobia"
|
||||
desc = "Patient has an inexplicable adverse reaction to light."
|
||||
scan_desc = "light hypersensitivity"
|
||||
gain_text = "<span class='warning'>You feel a craving for darkness.</span>"
|
||||
lose_text = "<span class='notice'>Light no longer bothers you.</span>"
|
||||
var/next_damage_warning = 0
|
||||
|
||||
/datum/brain_trauma/magic/lumiphobia/on_life()
|
||||
..()
|
||||
var/turf/T = owner.loc
|
||||
if(istype(T))
|
||||
var/light_amount = T.get_lumcount()
|
||||
if(light_amount > SHADOW_SPECIES_LIGHT_THRESHOLD) //if there's enough light, start dying
|
||||
if(world.time > next_damage_warning)
|
||||
to_chat(owner, "<span class='warning'><b>The light burns you!</b></span>")
|
||||
next_damage_warning = world.time + 100 //Avoid spamming
|
||||
owner.take_overall_damage(0,3)
|
||||
|
||||
/datum/brain_trauma/magic/poltergeist
|
||||
name = "Poltergeist"
|
||||
desc = "Patient appears to be targeted by a violent invisible entity."
|
||||
scan_desc = "paranormal activity"
|
||||
gain_text = "<span class='warning'>You feel a hateful presence close to you.</span>"
|
||||
lose_text = "<span class='notice'>You feel the hateful presence fade away.</span>"
|
||||
|
||||
/datum/brain_trauma/magic/poltergeist/on_life()
|
||||
..()
|
||||
if(prob(4))
|
||||
var/most_violent = -1 //So it can pick up items with 0 throwforce if there's nothing else
|
||||
var/obj/item/throwing
|
||||
for(var/obj/item/I in view(5, get_turf(owner)))
|
||||
if(I.anchored)
|
||||
continue
|
||||
if(I.throwforce > most_violent)
|
||||
most_violent = I.throwforce
|
||||
throwing = I
|
||||
if(throwing)
|
||||
throwing.throw_at(owner, 8, 2)
|
||||
|
||||
/datum/brain_trauma/magic/antimagic
|
||||
name = "Athaumasia"
|
||||
desc = "Patient is completely inert to magical forces."
|
||||
scan_desc = "thaumic blank"
|
||||
gain_text = "<span class='notice'>You realize that magic cannot be real.</span>"
|
||||
lose_text = "<span class='notice'>You realize that magic might be real.</span>"
|
||||
|
||||
/datum/brain_trauma/magic/antimagic/on_gain()
|
||||
ADD_TRAIT(owner, TRAIT_ANTIMAGIC, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/magic/antimagic/on_lose()
|
||||
REMOVE_TRAIT(owner, TRAIT_ANTIMAGIC, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/magic/stalker
|
||||
name = "Stalking Phantom"
|
||||
desc = "Patient is stalked by a phantom only they can see."
|
||||
|
||||
@@ -119,8 +119,9 @@
|
||||
|
||||
/datum/brain_trauma/severe/paralysis/spinesnapped
|
||||
random_gain = FALSE
|
||||
clonable = FALSE
|
||||
paralysis_type = "legs"
|
||||
resilience = TRAUMA_RESILIENCE_LOBOTOMY
|
||||
resilience = TRAUMA_RESILIENCE_LOBOTOMY // It shouldn't fix severed spinal cords really, but there is no specific surgery for that yet.
|
||||
|
||||
/datum/brain_trauma/severe/narcolepsy
|
||||
name = "Narcolepsy"
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glasses
|
||||
name = "Hand Made Glasses"
|
||||
desc = "Hande made glasses that have not been polished at all making them useless. Selling them could still be worth a bit of credits."
|
||||
name = "Handmade Glasses"
|
||||
desc = "Handmade glasses that have not been polished at all making them useless. Selling them could still be worth a few credits."
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "frames_2"
|
||||
@@ -92,7 +92,7 @@
|
||||
time = 150
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
always_availible = FALSE // Disabled til learned
|
||||
always_availible = FALSE // Disabled until learned
|
||||
|
||||
|
||||
/datum/crafting_recipe/bloodsucker/candelabrum
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/*!
|
||||
This component makes it possible to make things edible. What this means is that you can take a bite or force someone to take a bite (in the case of items).
|
||||
These items take a specific time to eat, and can do most of the things our original food items could.
|
||||
Behavior that's still missing from this component that original food items had that should either be put into seperate components or somewhere else:
|
||||
Components:
|
||||
Drying component (jerky etc)
|
||||
Customizable component (custom pizzas etc)
|
||||
Processable component (Slicing and cooking behavior essentialy, making it go from item A to B when conditions are met.)
|
||||
Dunkable component (Dunking things into reagent containers to absorb a specific amount of reagents)
|
||||
Misc:
|
||||
Something for cakes (You can store things inside)
|
||||
*/
|
||||
/datum/component/edible
|
||||
///Amount of reagents taken per bite
|
||||
var/bite_consumption = 2
|
||||
///Amount of bites taken so far
|
||||
var/bitecount = 0
|
||||
///Flags for food
|
||||
var/food_flags = NONE
|
||||
///Bitfield of the types of this food
|
||||
var/foodtypes = NONE
|
||||
///Amount of seconds it takes to eat this food
|
||||
var/eat_time = 30
|
||||
///Defines how much it lowers someones satiety (Need to eat, essentialy)
|
||||
var/junkiness = 0
|
||||
///Message to send when eating
|
||||
var/list/eatverbs
|
||||
///Callback to be ran for when you take a bite of something
|
||||
var/datum/callback/after_eat
|
||||
///Last time we checked for food likes
|
||||
var/last_check_time
|
||||
|
||||
/datum/component/edible/Initialize(list/initial_reagents, food_flags = NONE, foodtypes = NONE, volume = 50, eat_time = 30, list/tastes, list/eatverbs = list("bite","chew","nibble","gnaw","gobble","chomp"), bite_consumption = 2, datum/callback/after_eat)
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
|
||||
RegisterSignal(parent, COMSIG_ATOM_ATTACK_ANIMAL, .proc/UseByAnimal)
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/UseFromHand)
|
||||
else if(isturf(parent))
|
||||
RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/TryToEatTurf)
|
||||
|
||||
src.bite_consumption = bite_consumption
|
||||
src.food_flags = food_flags
|
||||
src.foodtypes = foodtypes
|
||||
src.eat_time = eat_time
|
||||
src.eatverbs = eatverbs
|
||||
src.junkiness = junkiness
|
||||
src.after_eat = after_eat
|
||||
|
||||
var/atom/owner = parent
|
||||
|
||||
owner.create_reagents(volume, INJECTABLE)
|
||||
|
||||
if(initial_reagents)
|
||||
for(var/rid in initial_reagents)
|
||||
var/amount = initial_reagents[rid]
|
||||
if(tastes && tastes.len && (rid == /datum/reagent/consumable/nutriment || rid == /datum/reagent/consumable/nutriment/vitamin))
|
||||
owner.reagents.add_reagent(rid, amount, tastes.Copy())
|
||||
else
|
||||
owner.reagents.add_reagent(rid, amount)
|
||||
|
||||
/datum/component/edible/proc/examine(datum/source, mob/user, list/examine_list)
|
||||
if(!(food_flags & FOOD_IN_CONTAINER))
|
||||
switch (bitecount)
|
||||
if (0)
|
||||
return
|
||||
if(1)
|
||||
examine_list += "[parent] was bitten by someone!"
|
||||
if(2,3)
|
||||
examine_list += "[parent] was bitten [bitecount] times!"
|
||||
else
|
||||
examine_list += "[parent] was bitten multiple times!"
|
||||
|
||||
/datum/component/edible/proc/UseFromHand(obj/item/source, mob/living/M, mob/living/user)
|
||||
return TryToEat(M, user)
|
||||
|
||||
/datum/component/edible/proc/TryToEatTurf(datum/source, mob/user)
|
||||
return TryToEat(user, user)
|
||||
|
||||
///All the checks for the act of eating itself and
|
||||
/datum/component/edible/proc/TryToEat(mob/living/eater, mob/living/feeder)
|
||||
|
||||
set waitfor = FALSE
|
||||
|
||||
var/atom/owner = parent
|
||||
|
||||
if(feeder.a_intent == INTENT_HARM)
|
||||
return
|
||||
if(!owner.reagents.total_volume)//Shouldn't be needed but it checks to see if it has anything left in it.
|
||||
to_chat(feeder, "<span class='warning'>None of [owner] left, oh no!</span>")
|
||||
if(isturf(parent))
|
||||
var/turf/T = parent
|
||||
T.ScrapeAway(1, CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
qdel(parent)
|
||||
return
|
||||
if(!CanConsume(eater, feeder))
|
||||
return
|
||||
var/fullness = eater.nutrition + 10 //The theoretical fullness of the person eating if they were to eat this
|
||||
for(var/datum/reagent/consumable/C in eater.reagents.reagent_list) //we add the nutrition value of what we're currently digesting
|
||||
fullness += C.nutriment_factor * C.volume / C.metabolization_rate
|
||||
|
||||
. = COMPONENT_ITEM_NO_ATTACK //Point of no return I suppose
|
||||
|
||||
if(eater == feeder)//If you're eating it yourself.
|
||||
if(!do_mob(feeder, eater, eat_time)) //Gotta pass the minimal eat time
|
||||
return
|
||||
var/eatverb = pick(eatverbs)
|
||||
if(junkiness && eater.satiety < -150 && eater.nutrition > NUTRITION_LEVEL_STARVING + 50 && !HAS_TRAIT(eater, TRAIT_VORACIOUS))
|
||||
to_chat(eater, "<span class='warning'>You don't feel like eating any more junk food at the moment!</span>")
|
||||
return
|
||||
else if(fullness <= 50)
|
||||
eater.visible_message("<span class='notice'>[eater] hungrily [eatverb]s \the [parent], gobbling it down!</span>", "<span class='notice'>You hungrily [eatverb] \the [parent], gobbling it down!</span>")
|
||||
else if(fullness > 50 && fullness < 150)
|
||||
eater.visible_message("<span class='notice'>[eater] hungrily [eatverb]s \the [parent].</span>", "<span class='notice'>You hungrily [eatverb] \the [parent].</span>")
|
||||
else if(fullness > 150 && fullness < 500)
|
||||
eater.visible_message("<span class='notice'>[eater] [eatverb]s \the [parent].</span>", "<span class='notice'>You [eatverb] \the [parent].</span>")
|
||||
else if(fullness > 500 && fullness < 600)
|
||||
eater.visible_message("<span class='notice'>[eater] unwillingly [eatverb]s a bit of \the [parent].</span>", "<span class='notice'>You unwillingly [eatverb] a bit of \the [parent].</span>")
|
||||
else if(fullness > (600 * (1 + eater.overeatduration / 2000))) // The more you eat - the more you can eat
|
||||
eater.visible_message("<span class='warning'>[eater] cannot force any more of \the [parent] to go down [eater.p_their()] throat!</span>", "<span class='warning'>You cannot force any more of \the [parent] to go down your throat!</span>")
|
||||
return
|
||||
else //If you're feeding it to someone else.
|
||||
if(isbrain(eater))
|
||||
to_chat(feeder, "<span class='warning'>[eater] doesn't seem to have a mouth!</span>")
|
||||
return
|
||||
if(fullness <= (600 * (1 + eater.overeatduration / 1000)))
|
||||
eater.visible_message("<span class='danger'>[feeder] attempts to feed [eater] [parent].</span>", \
|
||||
"<span class='userdanger'>[feeder] attempts to feed you [parent].</span>")
|
||||
else
|
||||
eater.visible_message("<span class='warning'>[feeder] cannot force any more of [parent] down [eater]'s throat!</span>", \
|
||||
"<span class='warning'>[feeder] cannot force any more of [parent] down your throat!</span>")
|
||||
return
|
||||
if(!do_mob(feeder, eater)) //Wait 3 seconds before you can feed
|
||||
return
|
||||
|
||||
log_combat(feeder, eater, "fed", owner.reagents.log_list())
|
||||
eater.visible_message("<span class='danger'>[feeder] forces [eater] to eat [parent]!</span>", \
|
||||
"<span class='userdanger'>[feeder] forces you to eat [parent]!</span>")
|
||||
|
||||
TakeBite(eater, feeder)
|
||||
|
||||
///This function lets the eater take a bite and transfers the reagents to the eater.
|
||||
/datum/component/edible/proc/TakeBite(mob/living/eater, mob/living/feeder)
|
||||
|
||||
var/atom/owner = parent
|
||||
|
||||
if(!owner?.reagents)
|
||||
return FALSE
|
||||
if(eater.satiety > -200)
|
||||
eater.satiety -= junkiness
|
||||
playsound(eater.loc,'sound/items/eatfood.ogg', rand(10,50), TRUE)
|
||||
if(owner.reagents.total_volume)
|
||||
SEND_SIGNAL(parent, COMSIG_FOOD_EATEN, eater, feeder)
|
||||
var/fraction = min(bite_consumption / owner.reagents.total_volume, 1)
|
||||
owner.reagents.reaction(eater, INGEST, fraction)
|
||||
owner.reagents.trans_to(eater, bite_consumption)
|
||||
bitecount++
|
||||
On_Consume(eater)
|
||||
checkLiked(fraction, eater)
|
||||
|
||||
//Invoke our after eat callback if it is valid
|
||||
if(after_eat)
|
||||
after_eat.Invoke(eater, feeder)
|
||||
|
||||
return TRUE
|
||||
|
||||
///Checks whether or not the eater can actually consume the food
|
||||
/datum/component/edible/proc/CanConsume(mob/living/eater, mob/living/feeder)
|
||||
if(!iscarbon(eater))
|
||||
return FALSE
|
||||
var/mob/living/carbon/C = eater
|
||||
var/covered = ""
|
||||
if(C.is_mouth_covered(head_only = 1))
|
||||
covered = "headgear"
|
||||
else if(C.is_mouth_covered(mask_only = 1))
|
||||
covered = "mask"
|
||||
if(covered)
|
||||
var/who = (isnull(feeder) || eater == feeder) ? "your" : "[eater.p_their()]"
|
||||
to_chat(feeder, "<span class='warning'>You have to remove [who] [covered] first!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
///Check foodtypes to see if we should send a moodlet
|
||||
/datum/component/edible/proc/checkLiked(var/fraction, mob/M)
|
||||
if(last_check_time + 50 > world.time)
|
||||
return FALSE
|
||||
if(!ishuman(M))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(HAS_TRAIT(H, TRAIT_AGEUSIA) && foodtypes & H.dna.species.toxic_food)
|
||||
to_chat(H, "<span class='warning'>You don't feel so good...</span>")
|
||||
H.adjust_disgust(25 + 30 * fraction)
|
||||
else
|
||||
if(foodtypes & H.dna.species.toxic_food)
|
||||
to_chat(H,"<span class='warning'>What the hell was that thing?!</span>")
|
||||
H.adjust_disgust(25 + 30 * fraction)
|
||||
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "toxic_food", /datum/mood_event/disgusting_food)
|
||||
else if(foodtypes & H.dna.species.disliked_food)
|
||||
to_chat(H,"<span class='notice'>That didn't taste very good...</span>")
|
||||
H.adjust_disgust(11 + 15 * fraction)
|
||||
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "gross_food", /datum/mood_event/gross_food)
|
||||
else if(foodtypes & H.dna.species.liked_food)
|
||||
to_chat(H,"<span class='notice'>I love this taste!</span>")
|
||||
H.adjust_disgust(-5 + -2.5 * fraction)
|
||||
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "fav_food", /datum/mood_event/favorite_food)
|
||||
if((foodtypes & BREAKFAST) && world.time - SSticker.round_start_time < STOP_SERVING_BREAKFAST)
|
||||
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "breakfast", /datum/mood_event/breakfast)
|
||||
last_check_time = world.time
|
||||
|
||||
///Delete the item when it is fully eaten
|
||||
/datum/component/edible/proc/On_Consume(mob/living/eater)
|
||||
|
||||
var/atom/owner = parent
|
||||
|
||||
if(!eater)
|
||||
return
|
||||
if(!owner.reagents.total_volume)
|
||||
if(isturf(parent))
|
||||
var/turf/T = parent
|
||||
T.ScrapeAway(1, CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
qdel(parent)
|
||||
|
||||
///Ability to feed food to puppers
|
||||
/datum/component/edible/proc/UseByAnimal(datum/source, mob/user)
|
||||
|
||||
var/atom/owner = parent
|
||||
|
||||
if(!isdog(user))
|
||||
return
|
||||
var/mob/living/L = user
|
||||
if(bitecount == 0 || prob(50))
|
||||
L.emote("me", 1, "nibbles away at \the [parent]")
|
||||
bitecount++
|
||||
. = COMPONENT_ITEM_NO_ATTACK
|
||||
L.taste(owner.reagents) // why should carbons get all the fun?
|
||||
if(bitecount >= 5)
|
||||
var/sattisfaction_text = pick("burps from enjoyment", "yaps for more", "woofs twice", "looks at the area where \the [parent] was")
|
||||
if(sattisfaction_text)
|
||||
L.emote("me", 1, "[sattisfaction_text]")
|
||||
qdel(parent)
|
||||
@@ -69,8 +69,9 @@
|
||||
out += "[out ? " and it " : "[master] "]seems to be glowing a bit."
|
||||
if(RAD_AMOUNT_HIGH to INFINITY) //At this level the object can contaminate other objects
|
||||
out += "[out ? " and it " : "[master] "]hurts to look at."
|
||||
else
|
||||
out += "."
|
||||
if(!LAZYLEN(out))
|
||||
return
|
||||
out += "."
|
||||
examine_list += out.Join()
|
||||
|
||||
/datum/component/radioactive/proc/rad_attack(datum/source, atom/movable/target, mob/living/user)
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
var/list/faction = list("mining")
|
||||
|
||||
/datum/component/spawner/Initialize(_mob_types, _spawn_time, _faction, _spawn_text, _max_mobs)
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
if(_spawn_time)
|
||||
spawn_time=_spawn_time
|
||||
if(_mob_types)
|
||||
@@ -19,20 +21,25 @@
|
||||
if(_max_mobs)
|
||||
max_mobs=_max_mobs
|
||||
|
||||
RegisterSignal(parent, list(COMSIG_PARENT_QDELETING), .proc/stop_spawning)
|
||||
RegisterSignal(parent, COMSIG_PARENT_QDELETING, .proc/stop_spawning)
|
||||
RegisterSignal(parent, COMSIG_OBJ_ATTACK_GENERIC, .proc/on_attack_generic)
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
/datum/component/spawner/process()
|
||||
try_spawn_mob()
|
||||
|
||||
|
||||
/datum/component/spawner/proc/stop_spawning(force, hint)
|
||||
/datum/component/spawner/proc/stop_spawning(datum/source, force, hint)
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
for(var/mob/living/simple_animal/L in spawned_mobs)
|
||||
if(L.nest == src)
|
||||
L.nest = null
|
||||
spawned_mobs = null
|
||||
|
||||
// Stopping clientless simple mobs' from indiscriminately bashing their own spawners due DestroySurroundings() et similars.
|
||||
/datum/component/spawner/proc/on_attack_generic(datum/source, mob/user, damage_amount, damage_type, damage_flag, sound_effect, armor_penetration)
|
||||
if(!user.client && ((user.faction & faction) || (user in spawned_mobs)))
|
||||
return COMPONENT_STOP_GENERIC_ATTACK
|
||||
|
||||
/datum/component/spawner/proc/try_spawn_mob()
|
||||
var/atom/P = parent
|
||||
if(spawned_mobs.len >= max_mobs)
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
|
||||
/datum/disease/transformation/Copy()
|
||||
var/datum/disease/transformation/D = ..()
|
||||
D.stage1 = stage1.Copy()
|
||||
D.stage2 = stage2.Copy()
|
||||
D.stage3 = stage3.Copy()
|
||||
D.stage4 = stage4.Copy()
|
||||
D.stage5 = stage5.Copy()
|
||||
D.stage1 = stage1?.Copy()
|
||||
D.stage2 = stage2?.Copy()
|
||||
D.stage3 = stage3?.Copy()
|
||||
D.stage4 = stage4?.Copy()
|
||||
D.stage5 = stage5?.Copy()
|
||||
D.new_form = D.new_form
|
||||
return D
|
||||
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
if(. == ELEMENT_INCOMPATIBLE || !isatom(target) || isarea(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
beauty = beautyamount
|
||||
RegisterSignal(target, COMSIG_ENTER_AREA, .proc/enter_area)
|
||||
RegisterSignal(target, COMSIG_EXIT_AREA, .proc/exit_area)
|
||||
|
||||
if(ismovable(target))
|
||||
RegisterSignal(target, COMSIG_ENTER_AREA, .proc/enter_area)
|
||||
RegisterSignal(target, COMSIG_EXIT_AREA, .proc/exit_area)
|
||||
|
||||
var/area/A = get_area(target)
|
||||
if(A)
|
||||
enter_area(null, A)
|
||||
|
||||
@@ -23,10 +23,14 @@
|
||||
var/end_sound
|
||||
var/chance
|
||||
var/volume = 100
|
||||
var/vary = FALSE
|
||||
var/max_loops
|
||||
var/direct
|
||||
var/extra_range = 0
|
||||
var/falloff
|
||||
|
||||
var/timerid
|
||||
var/init_timerid
|
||||
|
||||
/datum/looping_sound/New(list/_output_atoms=list(), start_immediately=FALSE, _direct=FALSE)
|
||||
if(!mid_sounds)
|
||||
@@ -47,13 +51,15 @@
|
||||
/datum/looping_sound/proc/start(atom/add_thing)
|
||||
if(add_thing)
|
||||
output_atoms |= add_thing
|
||||
if(timerid)
|
||||
if(timerid || init_timerid)
|
||||
return
|
||||
on_start()
|
||||
|
||||
/datum/looping_sound/proc/stop(atom/remove_thing)
|
||||
if(remove_thing)
|
||||
output_atoms -= remove_thing
|
||||
if(init_timerid)
|
||||
deltimer(init_timerid)
|
||||
if(!timerid)
|
||||
return
|
||||
on_stop()
|
||||
@@ -80,7 +86,7 @@
|
||||
if(direct)
|
||||
SEND_SOUND(thing, S)
|
||||
else
|
||||
playsound(thing, S, volume)
|
||||
playsound(thing, S, volume, vary, extra_range, falloff)
|
||||
|
||||
/datum/looping_sound/proc/get_sound(starttime, _mid_sounds)
|
||||
. = _mid_sounds || mid_sounds
|
||||
@@ -92,7 +98,7 @@
|
||||
if(start_sound)
|
||||
play(start_sound)
|
||||
start_wait = start_length
|
||||
addtimer(CALLBACK(src, .proc/sound_loop), start_wait, TIMER_CLIENT_TIME)
|
||||
init_timerid = addtimer(CALLBACK(src, .proc/sound_loop), start_wait, TIMER_CLIENT_TIME | TIMER_STOPPABLE)
|
||||
|
||||
/datum/looping_sound/proc/on_stop()
|
||||
if(end_sound)
|
||||
|
||||
@@ -6,8 +6,6 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
/datum/material
|
||||
var/name = "material"
|
||||
var/desc = "its..stuff."
|
||||
///Var that's mostly used by science machines to identify specific materials, should most likely be phased out at some point
|
||||
var/id = "mat"
|
||||
///Base color of the material, is used for greyscale. Item isn't changed in color if this is null.
|
||||
var/color
|
||||
///Base alpha of the material, is used for greyscale icons.
|
||||
@@ -26,6 +24,20 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
var/armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1)
|
||||
///How beautiful is this material per unit?
|
||||
var/beauty_modifier = 0
|
||||
///Can be used to override the sound items make, lets add some SLOSHing.
|
||||
var/item_sound_override
|
||||
///Can be used to override the stepsound a turf makes. MORE SLOOOSH
|
||||
var/turf_sound_override
|
||||
///what texture icon state to overlay
|
||||
var/texture_layer_icon_state
|
||||
///a cached filter for the texture icon
|
||||
var/cached_texture_filter
|
||||
|
||||
/datum/material/New()
|
||||
. = ..()
|
||||
if(texture_layer_icon_state)
|
||||
var/texture_icon = icon('icons/materials/composite.dmi', texture_layer_icon_state)
|
||||
cached_texture_filter = filter(type="layer", icon=texture_icon, blend_mode = BLEND_INSET_OVERLAY)
|
||||
|
||||
///This proc is called when the material is added to an object.
|
||||
/datum/material/proc/on_applied(atom/source, amount, material_flags)
|
||||
@@ -34,16 +46,27 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
source.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
if(alpha)
|
||||
source.alpha = alpha
|
||||
if(texture_layer_icon_state)
|
||||
ADD_KEEP_TOGETHER(source, MATERIAL_SOURCE(src))
|
||||
source.filters += cached_texture_filter
|
||||
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = "[name] [source.name]"
|
||||
|
||||
if(istype(source, /obj)) //objs
|
||||
on_applied_obj(source, amount, material_flags)
|
||||
|
||||
if(beauty_modifier)
|
||||
addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, beauty_modifier * amount)), 0)
|
||||
|
||||
if(istype(source, /obj)) //objs
|
||||
on_applied_obj(source, amount, material_flags)
|
||||
|
||||
else if(isturf(source, /turf)) //turfs
|
||||
on_applied_turf(source, amount, material_flags)
|
||||
|
||||
source.mat_update_desc(src)
|
||||
|
||||
///This proc is called when a material updates an object's description
|
||||
/atom/proc/mat_update_desc(/datum/material/mat)
|
||||
return
|
||||
///This proc is called when the material is added to an object specifically.
|
||||
/datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
@@ -61,6 +84,24 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
for(var/i in current_armor)
|
||||
temp_armor_list[i] = current_armor[i] * armor_modifiers[i]
|
||||
o.armor = getArmor(arglist(temp_armor_list))
|
||||
if(!isitem(o))
|
||||
return
|
||||
var/obj/item/I = o
|
||||
if(!item_sound_override)
|
||||
return
|
||||
I.hitsound = item_sound_override
|
||||
I.usesound = item_sound_override
|
||||
I.throwhitsound = item_sound_override
|
||||
|
||||
/datum/material/proc/on_applied_turf(var/turf/T, amount, material_flags)
|
||||
if(isopenturf(T))
|
||||
if(!turf_sound_override)
|
||||
return
|
||||
var/turf/open/O = T
|
||||
O.footstep = turf_sound_override
|
||||
O.barefootstep = turf_sound_override
|
||||
O.clawfootstep = turf_sound_override
|
||||
O.heavyfootstep = turf_sound_override
|
||||
|
||||
///This proc is called when the material is removed from an object.
|
||||
/datum/material/proc/on_removed(atom/source, material_flags)
|
||||
@@ -68,6 +109,9 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
if(color)
|
||||
source.remove_atom_colour(FIXED_COLOUR_PRIORITY, color)
|
||||
source.alpha = initial(source.alpha)
|
||||
if(texture_layer_icon_state)
|
||||
source.filters -= cached_texture_filter
|
||||
REMOVE_KEEP_TOGETHER(source, MATERIAL_SOURCE(src))
|
||||
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = initial(source.name)
|
||||
@@ -75,10 +119,16 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
if(istype(source, /obj)) //objs
|
||||
on_removed_obj(source, material_flags)
|
||||
|
||||
else if(istype(source, /turf)) //turfs
|
||||
on_removed_turf(source, material_flags)
|
||||
|
||||
///This proc is called when the material is removed from an object specifically.
|
||||
/datum/material/proc/on_removed_obj(var/obj/o, amount, material_flags)
|
||||
/datum/material/proc/on_removed_obj(obj/o, material_flags)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
|
||||
/datum/material/proc/on_removed_turf(turf/T, material_flags)
|
||||
return
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
///Has no special properties.
|
||||
/datum/material/iron
|
||||
name = "iron"
|
||||
id = "iron"
|
||||
desc = "Common iron ore often found in sedimentary and igneous layers of the crust."
|
||||
color = "#878687"
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/metal
|
||||
value_per_unit = 0.0025
|
||||
|
||||
///Breaks extremely easily but is transparent.
|
||||
/datum/material/glass
|
||||
name = "glass"
|
||||
id = "glass"
|
||||
desc = "Glass forged by melting sand."
|
||||
color = "#88cdf1"
|
||||
alpha = 150
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
integrity_modifier = 0.1
|
||||
sheet_type = /obj/item/stack/sheet/glass
|
||||
value_per_unit = 0.0025
|
||||
@@ -30,10 +28,9 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Has no special properties. Could be good against vampires in the future perhaps.
|
||||
/datum/material/silver
|
||||
name = "silver"
|
||||
id = "silver"
|
||||
desc = "Silver"
|
||||
color = list(255/255, 284/255, 302/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/silver
|
||||
value_per_unit = 0.025
|
||||
beauty_modifier = 0.075
|
||||
@@ -41,11 +38,10 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Slight force increase
|
||||
/datum/material/gold
|
||||
name = "gold"
|
||||
id = "gold"
|
||||
desc = "Gold"
|
||||
color = list(340/255, 240/255, 50/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //gold is shiny, but not as bright as bananium
|
||||
strength_modifier = 1.2
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/gold
|
||||
value_per_unit = 0.0625
|
||||
beauty_modifier = 0.15
|
||||
@@ -54,11 +50,10 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Has no special properties
|
||||
/datum/material/diamond
|
||||
name = "diamond"
|
||||
id = "diamond"
|
||||
desc = "Highly pressurized carbon"
|
||||
color = list(48/255, 272/255, 301/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
|
||||
alpha = 132
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/diamond
|
||||
value_per_unit = 0.25
|
||||
beauty_modifier = 0.3
|
||||
@@ -67,10 +62,9 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Is slightly radioactive
|
||||
/datum/material/uranium
|
||||
name = "uranium"
|
||||
id = "uranium"
|
||||
desc = "Uranium"
|
||||
color = rgb(48, 237, 26)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/uranium
|
||||
value_per_unit = 0.05
|
||||
beauty_modifier = 0.3 //It shines so beautiful
|
||||
@@ -88,10 +82,9 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Adds firestacks on hit (Still needs support to turn into gas on destruction)
|
||||
/datum/material/plasma
|
||||
name = "plasma"
|
||||
id = "plasma"
|
||||
desc = "Isn't plasma a state of matter? Oh whatever."
|
||||
color = list(298/255, 46/255, 352/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/plasma
|
||||
value_per_unit = 0.1
|
||||
beauty_modifier = 0.15
|
||||
@@ -111,7 +104,6 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Can cause bluespace effects on use. (Teleportation) (Not yet implemented)
|
||||
/datum/material/bluespace
|
||||
name = "bluespace crystal"
|
||||
id = "bluespace_crystal"
|
||||
desc = "Crystals with bluespace properties"
|
||||
color = list(119/255, 217/255, 396/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
|
||||
alpha = 200
|
||||
@@ -123,10 +115,9 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Honks and slips
|
||||
/datum/material/bananium
|
||||
name = "bananium"
|
||||
id = "bananium"
|
||||
desc = "Material with hilarious properties"
|
||||
color = list(460/255, 464/255, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //obnoxiously bright yellow
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/bananium
|
||||
value_per_unit = 0.5
|
||||
beauty_modifier = 0.5
|
||||
@@ -146,11 +137,10 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Mediocre force increase
|
||||
/datum/material/titanium
|
||||
name = "titanium"
|
||||
id = "titanium"
|
||||
desc = "Titanium"
|
||||
color = "#b3c0c7"
|
||||
strength_modifier = 1.3
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/titanium
|
||||
value_per_unit = 0.0625
|
||||
beauty_modifier = 0.05
|
||||
@@ -158,11 +148,10 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
|
||||
/datum/material/runite
|
||||
name = "runite"
|
||||
id = "runite"
|
||||
desc = "Runite"
|
||||
color = "#3F9995"
|
||||
strength_modifier = 1.3
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/runite
|
||||
beauty_modifier = 0.5
|
||||
armor_modifiers = list("melee" = 1.35, "bullet" = 2, "laser" = 0.5, "energy" = 1.25, "bomb" = 1.25, "bio" = 1, "rad" = 1, "fire" = 1.4, "acid" = 1) //rune is weak against magic lasers but strong against bullets. This is the combat triangle.
|
||||
@@ -170,7 +159,6 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Force decrease
|
||||
/datum/material/plastic
|
||||
name = "plastic"
|
||||
id = "plastic"
|
||||
desc = "Plastic"
|
||||
color = "#caccd9"
|
||||
strength_modifier = 0.85
|
||||
@@ -182,7 +170,6 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Force decrease and mushy sound effect. (Not yet implemented)
|
||||
/datum/material/biomass
|
||||
name = "biomass"
|
||||
id = "biomass"
|
||||
desc = "Organic matter"
|
||||
color = "#735b4d"
|
||||
strength_modifier = 0.8
|
||||
@@ -190,12 +177,11 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
|
||||
/datum/material/wood
|
||||
name = "wood"
|
||||
id = "wood"
|
||||
desc = "Flexible, durable, but flamable. Hard to come across in space."
|
||||
color = "#bb8e53"
|
||||
strength_modifier = 0.5
|
||||
sheet_type = /obj/item/stack/sheet/mineral/wood
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
value_per_unit = 0.06
|
||||
beauty_modifier = 0.1
|
||||
armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 0.4, "energy" = 0.4, "bomb" = 1, "bio" = 0.2, "rad" = 0, "fire" = 0, "acid" = 0.3)
|
||||
@@ -215,11 +201,10 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///Stronk force increase
|
||||
/datum/material/adamantine
|
||||
name = "adamantine"
|
||||
id = "adamantine"
|
||||
desc = "A powerful material made out of magic, I mean science!"
|
||||
color = "#6d7e8e"
|
||||
strength_modifier = 1.5
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/adamantine
|
||||
value_per_unit = 0.25
|
||||
beauty_modifier = 0.4
|
||||
@@ -228,10 +213,9 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
///RPG Magic. (Admin only)
|
||||
/datum/material/mythril
|
||||
name = "mythril"
|
||||
id = "mythril"
|
||||
desc = "How this even exists is byond me"
|
||||
color = "#f2d5d7"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE)
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/mythril
|
||||
value_per_unit = 0.75
|
||||
beauty_modifier = 0.5
|
||||
@@ -246,3 +230,134 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
. = ..()
|
||||
if(istype(source, /obj/item))
|
||||
qdel(source.GetComponent(/datum/component/fantasy))
|
||||
|
||||
//I don't like sand. It's coarse, and rough, and irritating, and it gets everywhere.
|
||||
/datum/material/sand
|
||||
name = "sand"
|
||||
desc = "You know, it's amazing just how structurally sound sand can be."
|
||||
color = "#EDC9AF"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/sandblock
|
||||
value_per_unit = 0.001
|
||||
strength_modifier = 0.5
|
||||
integrity_modifier = 0.1
|
||||
armor_modifiers = list("melee" = 0.25, "bullet" = 0.25, "laser" = 1.25, "energy" = 0.25, "bomb" = 0.25, "bio" = 0.25, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5)
|
||||
beauty_modifier = 0.25
|
||||
turf_sound_override = FOOTSTEP_SAND
|
||||
texture_layer_icon_state = "sand"
|
||||
|
||||
//And now for our lavaland dwelling friends, sand, but in stone form! Truly revolutionary.
|
||||
/datum/material/sandstone
|
||||
name = "sandstone"
|
||||
desc = "Bialtaakid 'ant taerif ma hdha."
|
||||
color = "#B77D31"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/sandstone
|
||||
value_per_unit = 0.0025
|
||||
armor_modifiers = list("melee" = 0.5, "bullet" = 0.5, "laser" = 1.25, "energy" = 0.5, "bomb" = 0.5, "bio" = 0.25, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5)
|
||||
beauty_modifier = 0.3
|
||||
turf_sound_override = FOOTSTEP_WOOD
|
||||
texture_layer_icon_state = "brick"
|
||||
|
||||
/datum/material/snow
|
||||
name = "snow"
|
||||
desc = "There's no business like snow business."
|
||||
color = "#FFFFFF"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/snow
|
||||
value_per_unit = 0.0025
|
||||
armor_modifiers = list("melee" = 0.25, "bullet" = 0.25, "laser" = 0.25, "energy" = 0.25, "bomb" = 0.25, "bio" = 0.25, "rad" = 1.5, "fire" = 0.25, "acid" = 1.5)
|
||||
beauty_modifier = 0.3
|
||||
turf_sound_override = FOOTSTEP_SAND
|
||||
texture_layer_icon_state = "sand"
|
||||
|
||||
/datum/material/runedmetal
|
||||
name = "runed metal"
|
||||
desc = "Mir'ntrath barhah Nar'sie."
|
||||
color = "#3C3434"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/runed_metal
|
||||
value_per_unit = 0.75
|
||||
armor_modifiers = list("melee" = 1.2, "bullet" = 1.2, "laser" = 1, "energy" = 1, "bomb" = 1.2, "bio" = 1.2, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5)
|
||||
beauty_modifier = -0.15
|
||||
texture_layer_icon_state = "runed"
|
||||
|
||||
/datum/material/bronze
|
||||
name = "bronze"
|
||||
desc = "Clock Cult? Never heard of it."
|
||||
color = "#92661A"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/tile/bronze
|
||||
value_per_unit = 0.025
|
||||
armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5)
|
||||
beauty_modifier = 0.2
|
||||
|
||||
/datum/material/paper
|
||||
name = "paper"
|
||||
desc = "Ten thousand folds of pure starchy power."
|
||||
color = "#E5DCD5"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/paperframes
|
||||
value_per_unit = 0.0025
|
||||
armor_modifiers = list("melee" = 0.1, "bullet" = 0.1, "laser" = 0.1, "energy" = 0.1, "bomb" = 0.1, "bio" = 0.1, "rad" = 1.5, "fire" = 0, "acid" = 1.5)
|
||||
beauty_modifier = 0.3
|
||||
turf_sound_override = FOOTSTEP_SAND
|
||||
texture_layer_icon_state = "paper"
|
||||
|
||||
/datum/material/paper/on_applied_obj(obj/source, amount, material_flags)
|
||||
. = ..()
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/obj/paper = source
|
||||
paper.resistance_flags |= FLAMMABLE
|
||||
paper.obj_flags |= UNIQUE_RENAME
|
||||
|
||||
/datum/material/paper/on_removed_obj(obj/source, material_flags)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/obj/paper = source
|
||||
paper.resistance_flags &= ~FLAMMABLE
|
||||
return ..()
|
||||
|
||||
/datum/material/cardboard
|
||||
name = "cardboard"
|
||||
desc = "They say cardboard is used by hobos to make incredible things."
|
||||
color = "#5F625C"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/cardboard
|
||||
value_per_unit = 0.003
|
||||
armor_modifiers = list("melee" = 0.25, "bullet" = 0.25, "laser" = 0.25, "energy" = 0.25, "bomb" = 0.25, "bio" = 0.25, "rad" = 1.5, "fire" = 0, "acid" = 1.5)
|
||||
beauty_modifier = -0.1
|
||||
|
||||
/datum/material/cardboard/on_applied_obj(obj/source, amount, material_flags)
|
||||
. = ..()
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/obj/cardboard = source
|
||||
cardboard.resistance_flags |= FLAMMABLE
|
||||
cardboard.obj_flags |= UNIQUE_RENAME
|
||||
|
||||
/datum/material/cardboard/on_removed_obj(obj/source, material_flags)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/obj/cardboard = source
|
||||
cardboard.resistance_flags &= ~FLAMMABLE
|
||||
return ..()
|
||||
|
||||
/datum/material/bone
|
||||
name = "bone"
|
||||
desc = "Man, building with this will make you the coolest caveman on the block."
|
||||
color = "#e3dac9"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/bone
|
||||
value_per_unit = 0.05
|
||||
armor_modifiers = list("melee" = 1.2, "bullet" = 0.75, "laser" = 0.75, "energy" = 1.2, "bomb" = 1, "bio" = 1, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5)
|
||||
beauty_modifier = -0.2
|
||||
|
||||
/datum/material/bamboo
|
||||
name = "bamboo"
|
||||
desc = "If it's good enough for pandas, it's good enough for you."
|
||||
color = "#339933"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/bamboo
|
||||
value_per_unit = 0.0025
|
||||
armor_modifiers = list("melee" = 0.5, "bullet" = 0.5, "laser" = 0.5, "energy" = 0.5, "bomb" = 0.5, "bio" = 0.51, "rad" = 1.5, "fire" = 0.5, "acid" = 1.5)
|
||||
beauty_modifier = 0.2
|
||||
turf_sound_override = FOOTSTEP_WOOD
|
||||
texture_layer_icon_state = "bamboo"
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
///It's gross, gets the name of it's owner, and is all kinds of fucked up
|
||||
/datum/material/meat
|
||||
name = "meat"
|
||||
desc = "Meat"
|
||||
color = rgb(214, 67, 67)
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/meat
|
||||
value_per_unit = 0.05
|
||||
beauty_modifier = -0.3
|
||||
strength_modifier = 0.7
|
||||
armor_modifiers = list("melee" = 0.3, "bullet" = 0.3, "laser" = 1.2, "energy" = 1.2, "bomb" = 0.3, "bio" = 0, "rad" = 0.7, "fire" = 1, "acid" = 1)
|
||||
item_sound_override = 'sound/effects/meatslap.ogg'
|
||||
turf_sound_override = FOOTSTEP_MEAT
|
||||
texture_layer_icon_state = "meat"
|
||||
|
||||
/datum/material/meat/on_removed(atom/source, material_flags)
|
||||
. = ..()
|
||||
qdel(source.GetComponent(/datum/component/edible))
|
||||
|
||||
/datum/material/meat/on_applied_obj(obj/O, amount, material_flags)
|
||||
. = ..()
|
||||
O.obj_flags |= UNIQUE_RENAME //So you can name it after the person its made from, a depressing comprimise.
|
||||
make_edible(O, amount, material_flags)
|
||||
|
||||
/datum/material/meat/on_applied_turf(turf/T, amount, material_flags)
|
||||
. = ..()
|
||||
make_edible(T, amount, material_flags)
|
||||
|
||||
/datum/material/meat/proc/make_edible(atom/source, amount, material_flags)
|
||||
var/nutriment_count = 3 * (amount / MINERAL_MATERIAL_AMOUNT)
|
||||
var/oil_count = 2 * (amount / MINERAL_MATERIAL_AMOUNT)
|
||||
source.AddComponent(/datum/component/edible, list(/datum/reagent/consumable/nutriment = nutriment_count, /datum/reagent/consumable/cooking_oil = oil_count), null, RAW | MEAT | GROSS, null, 30, list("Fleshy"))
|
||||
@@ -0,0 +1,30 @@
|
||||
/datum/material/pizza
|
||||
name = "pizza"
|
||||
desc = "~Jamme, jamme, n'coppa, jamme ja! Jamme, jamme, n'coppa jamme ja, funi-culi funi-cala funi-culi funi-cala!! Jamme jamme ja funiculi funicula!~"
|
||||
color = "#FF9F23"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/pizza
|
||||
value_per_unit = 0.05
|
||||
beauty_modifier = 0.1
|
||||
strength_modifier = 0.7
|
||||
armor_modifiers = list("melee" = 0.3, "bullet" = 0.3, "laser" = 1.2, "energy" = 1.2, "bomb" = 0.3, "bio" = 0, "rad" = 0.7, "fire" = 1, "acid" = 1)
|
||||
item_sound_override = 'sound/effects/meatslap.ogg'
|
||||
turf_sound_override = FOOTSTEP_MEAT
|
||||
texture_layer_icon_state = "pizza"
|
||||
|
||||
/datum/material/pizza/on_removed(atom/source, material_flags)
|
||||
. = ..()
|
||||
qdel(source.GetComponent(/datum/component/edible))
|
||||
|
||||
/datum/material/pizza/on_applied_obj(obj/O, amount, material_flags)
|
||||
. = ..()
|
||||
make_edible(O, amount, material_flags)
|
||||
|
||||
/datum/material/pizza/on_applied_turf(turf/T, amount, material_flags)
|
||||
. = ..()
|
||||
make_edible(T, amount, material_flags)
|
||||
|
||||
/datum/material/pizza/proc/make_edible(atom/source, amount, material_flags)
|
||||
var/nutriment_count = 3 * (amount / MINERAL_MATERIAL_AMOUNT)
|
||||
var/oil_count = 2 * (amount / MINERAL_MATERIAL_AMOUNT)
|
||||
source.AddComponent(/datum/component/edible, list(/datum/reagent/consumable/nutriment = nutriment_count, /datum/reagent/consumable/cooking_oil = oil_count), null, GRAIN | MEAT | DAIRY | VEGETABLES, null, 30, list("crust", "tomato", "cheese", "meat"))
|
||||
+1
-1
@@ -67,7 +67,7 @@
|
||||
var/datum/skill_holder/skill_holder
|
||||
|
||||
/datum/mind/New(var/key)
|
||||
skill_holder = new()
|
||||
skill_holder = new(src)
|
||||
src.key = key
|
||||
soulOwner = src
|
||||
martial_art = default_martial_art
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
school = "evocation"
|
||||
charge_max = 600
|
||||
clothes_req = NONE
|
||||
antimagic_allowed = TRUE
|
||||
range = 20
|
||||
base_icon_state = "fireball"
|
||||
action_icon_state = "fireball0"
|
||||
@@ -122,6 +123,7 @@
|
||||
desc = "A rare genome that attracts odd forces not usually observed. May sometimes pull you in randomly."
|
||||
school = "evocation"
|
||||
clothes_req = NONE
|
||||
antimagic_allowed = TRUE
|
||||
charge_max = 600
|
||||
invocation = "DOOOOOOOOOOOOOOOOOOOOM!!!"
|
||||
invocation_type = "shout"
|
||||
@@ -155,6 +157,7 @@
|
||||
dropmessage = "You let the electricity from your hand dissipate."
|
||||
hand_path = /obj/item/melee/touch_attack/shock
|
||||
charge_max = 400
|
||||
antimagic_allowed = TRUE
|
||||
clothes_req = NONE
|
||||
action_icon_state = "zap"
|
||||
|
||||
@@ -212,6 +215,7 @@
|
||||
desc = "Get a scent off of the item you're currently holding to track it. With an empty hand, you'll track the scent you've remembered."
|
||||
charge_max = 100
|
||||
clothes_req = NONE
|
||||
antimagic_allowed = TRUE
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
action_icon_state = "nose"
|
||||
@@ -290,6 +294,7 @@
|
||||
name = "Drop a limb"
|
||||
desc = "Concentrate to make a random limb pop right off your body."
|
||||
clothes_req = NONE
|
||||
antimagic_allowed = TRUE
|
||||
charge_max = 100
|
||||
action_icon_state = "autotomy"
|
||||
|
||||
@@ -327,6 +332,7 @@
|
||||
name = "Lay Web"
|
||||
desc = "Drops a web. Only you will be able to traverse your web easily, making it pretty good for keeping you safe."
|
||||
clothes_req = NONE
|
||||
antimagic_allowed = TRUE
|
||||
charge_max = 4 SECONDS //the same time to lay a web
|
||||
action_icon = 'icons/mob/actions/actions_genetic.dmi'
|
||||
action_icon_state = "lay_web"
|
||||
@@ -368,6 +374,7 @@
|
||||
name = "Launch spike"
|
||||
desc = "Shoot your tongue out in the direction you're facing, embedding it and dealing damage until they remove it."
|
||||
clothes_req = NONE
|
||||
antimagic_allowed = TRUE
|
||||
charge_max = 100
|
||||
action_icon = 'icons/mob/actions/actions_genetic.dmi'
|
||||
action_icon_state = "spike"
|
||||
|
||||
@@ -462,6 +462,10 @@
|
||||
suffix = "whiteship_pod"
|
||||
name = "Salvage Pod"
|
||||
|
||||
/datum/map_template/shuttle/whiteship/cog
|
||||
suffix = "cog"
|
||||
name = "NT Prisoner Transport"
|
||||
|
||||
/datum/map_template/shuttle/cargo/box
|
||||
suffix = "box"
|
||||
name = "supply shuttle (Box)"
|
||||
@@ -628,4 +632,4 @@
|
||||
|
||||
/datum/map_template/shuttle/hunter/bounty
|
||||
suffix = "bounty"
|
||||
name = "Bounty Hunter Ship"
|
||||
name = "Bounty Hunter Ship"
|
||||
|
||||
@@ -11,6 +11,66 @@
|
||||
if(!mind.skill_holder)
|
||||
to_chat(usr, "<span class='warning'>How do you check the skills of [(usr == src)? "yourself when you are" : "something"] without the capability for skills? (PROBABLY A BUG, PRESS F1.)</span>")
|
||||
return
|
||||
var/datum/browser/B = new(usr, "skilldisplay_[REF(src)]", "Skills of [src]")
|
||||
B.set_content(mind.skill_html_readout())
|
||||
B.open()
|
||||
|
||||
mind.skill_holder.ui_interact(src)
|
||||
|
||||
/datum/skill_holder/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "skillpanel", "[owner.name]'s Skills", 620, 580, master_ui, state)
|
||||
ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input.
|
||||
ui.open()
|
||||
else if(need_static_data_update)
|
||||
update_static_data(user)
|
||||
need_static_data_update = FALSE
|
||||
|
||||
/datum/skill_holder/ui_static_data(mob/user)
|
||||
. = list()
|
||||
.["skills"] = list()
|
||||
for(var/path in GLOB.skill_datums)
|
||||
var/datum/skill/S = GLOB.skill_datums[path]
|
||||
var/list/dat = S.get_skill_data(src)
|
||||
if(islist(dat["modifiers"]))
|
||||
dat["modifiers"] = jointext(dat["modifiers"], ", ")
|
||||
dat["percent_base"] = (dat["value_base"] / dat["max_value"])
|
||||
dat["percent_mod"] = (dat["value_mod"] / dat["max_value"])
|
||||
.["skills"] += list(dat)
|
||||
|
||||
/datum/skill_holder/ui_data(mob/user)
|
||||
. = list()
|
||||
.["playername"] = owner.name
|
||||
.["see_skill_mods"] = see_skill_mods
|
||||
.["admin"] = check_rights(R_DEBUG)
|
||||
|
||||
/datum/skill_holder/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("toggle_mods")
|
||||
see_skill_mods = !see_skill_mods
|
||||
return TRUE
|
||||
if ("adj_exp")
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
var/skill = text2path(params["skill"])
|
||||
var/number = input("Please insert the amount of experience/progress you'd like to add/subtract:") as num|null
|
||||
if (number)
|
||||
owner.set_skill_value(skill, owner.get_skill_value(skill, FALSE) + number)
|
||||
return TRUE
|
||||
if ("set_exp")
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
var/skill = text2path(params["skill"])
|
||||
var/number = input("Please insert the number you want to set the player's exp/progress to:") as num|null
|
||||
if (!isnull(number))
|
||||
owner.set_skill_value(skill, number)
|
||||
return TRUE
|
||||
if ("set_lvl")
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
var/datum/skill/level/S = GLOB.skill_datums[text2path(params["skill"])]
|
||||
var/number = input("Please insert a whole number between 0[S.associative ? " ([S.unskilled_tier])" : ""] and [S.max_levels][S.associative ? " ([S.levels[S.max_levels]])" : ""] corresponding to the level you'd like to set the player to.") as num|null
|
||||
if (number >= 0 && number <= S.max_levels)
|
||||
owner.set_skill_value(S.type, S.get_skill_level_value(number))
|
||||
return TRUE
|
||||
|
||||
@@ -8,6 +8,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
continue
|
||||
S = new path
|
||||
.[S.type] = S
|
||||
. = sortTim(., /proc/cmp_skill_categories, TRUE)
|
||||
|
||||
/**
|
||||
* Skill datums
|
||||
@@ -34,6 +35,8 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
var/competency_multiplier = 1
|
||||
/// A list of ways this skill can affect or be affected through actions and skill modifiers.
|
||||
var/list/skill_traits = list(SKILL_SANITY, SKILL_INTELLIGENCE)
|
||||
/// Index of this skill in the UI
|
||||
var/ui_category = SKILL_UI_CAT_MISC
|
||||
|
||||
/**
|
||||
* Ensures what someone's setting as a value for this skill is valid.
|
||||
@@ -57,10 +60,28 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
return new_value > existing
|
||||
|
||||
/**
|
||||
* Standard value "render"
|
||||
* Get a list of data used in the skill panel menu.
|
||||
*/
|
||||
/datum/skill/proc/standard_render_value(value, level)
|
||||
return value
|
||||
/datum/skill/proc/get_skill_data(datum/skill_holder/H)
|
||||
var/skill_value = H.owner.get_skill_value(type, FALSE)
|
||||
. = list(
|
||||
"name" = name,
|
||||
"desc" = desc,
|
||||
"path" = type,
|
||||
"value_base" = skill_value,
|
||||
"value_mod" = skill_value,
|
||||
"modifiers" = "None",
|
||||
"max_value" = 1 //To avoid division by zero later on.
|
||||
)
|
||||
var/list/mods = LAZYACCESS(H.skill_value_mods, type)
|
||||
if(mods)
|
||||
var/list/mod_names = list()
|
||||
for(var/k in mods)
|
||||
var/datum/skill_modifier/M = GLOB.skill_modifiers[k]
|
||||
mod_names |= M.name
|
||||
skill_value = M.apply_modifier(skill_value, type, H, MODIFIER_TARGET_VALUE)
|
||||
.["value_mod"] = skill_value
|
||||
.["modifiers"] = mod_names //Will be jointext()'d later.
|
||||
|
||||
// Just saying, the choice to use different sub-parent-types is to force coders to resolve issues as I won't be implementing custom procs to grab skill levels in a certain context.
|
||||
// Aka: So people don't forget to change checks if they change a skill's progression type.
|
||||
@@ -71,10 +92,12 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
competency_thresholds = list(THRESHOLD_COMPETENT = FALSE, THRESHOLD_EXPERT = TRUE, THRESHOLD_MASTER = TRUE)
|
||||
|
||||
/datum/skill/binary/sanitize_value(new_value)
|
||||
return new_value? TRUE : FALSE
|
||||
return new_value >= 1 ? TRUE : FALSE
|
||||
|
||||
/datum/skill/binary/standard_render_value(value, level)
|
||||
return value? "Yes" : "No"
|
||||
/datum/skill/binary/get_skill_data(datum/skill_holder/H)
|
||||
. = ..()
|
||||
.["base_readout"] = .["value_base"] ? "Learned: Yes" : "Learned: No"
|
||||
.["mod_readout"] = .["value_mod"] ? "Learned: Yes" : "Learned: No"
|
||||
|
||||
/datum/skill/numerical
|
||||
abstract_type = /datum/skill/numerical
|
||||
@@ -84,14 +107,15 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
var/max_value = 100
|
||||
/// Min value of this skill
|
||||
var/min_value = 0
|
||||
/// Display as a percent in standard_render_value?
|
||||
var/display_as_percent = FALSE
|
||||
|
||||
/datum/skill/numerical/sanitize_value(new_value)
|
||||
return clamp(new_value, min_value, max_value)
|
||||
|
||||
/datum/skill/numerical/standard_render_value(value, level)
|
||||
return display_as_percent? "[round(value/max_value/100, 0.01)]%" : "[value] / [max_value]"
|
||||
/datum/skill/numerical/get_skill_data(datum/skill_holder/H)
|
||||
. = ..()
|
||||
.["base_readout"] = "Skill Progress: \[[.["value_base"]] / [max_value]\]"
|
||||
.["mod_readout"] = "Skill Progress: \[[.["value_mod"]] / [max_value]\]"
|
||||
.["max_value"] = max_value
|
||||
|
||||
/datum/skill/enum
|
||||
abstract_type = /datum/skill/enum
|
||||
@@ -123,13 +147,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
var/max_assoc = ""
|
||||
var/max_assoc_start = 1
|
||||
for(var/lvl in 1 to max_levels)
|
||||
var/value
|
||||
switch(level_up_method)
|
||||
if(STANDARD_LEVEL_UP)
|
||||
value = XP_LEVEL(standard_xp_lvl_up, xp_lvl_multiplier, lvl)
|
||||
if(DWARFY_LEVEL_UP)
|
||||
value = DORF_XP_LEVEL(standard_xp_lvl_up, xp_lvl_multiplier, lvl)
|
||||
value = round(value, 1)
|
||||
var/value = round(get_skill_level_value(lvl), 1)
|
||||
if(!associative)
|
||||
levels += value
|
||||
continue
|
||||
@@ -167,8 +185,13 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
else if(. < 0)
|
||||
to_chat(M.current, "<span class='warning'>I feel like I've become worse at [name]!</span>")
|
||||
|
||||
/datum/skill/level/standard_render_value(value, level)
|
||||
var/current_lvl = associative ? (!level ? unskilled_tier : levels[level]) : level
|
||||
/datum/skill/level/get_skill_data(datum/skill_holder/H)
|
||||
. = ..()
|
||||
var/skill_value_base = .["value_base"]
|
||||
var/skill_value_mod = .["value_mod"]
|
||||
.["level_based"] = TRUE
|
||||
|
||||
var/level = LAZYACCESS(H.skill_levels, type) || 0
|
||||
var/current_lvl_xp_sum = 0
|
||||
if(level)
|
||||
current_lvl_xp_sum = associative ? levels[levels[level]] : levels[level]
|
||||
@@ -176,8 +199,50 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
var/next_lvl_xp = associative ? levels[levels[next_index]] : levels[next_index]
|
||||
if(next_lvl_xp > current_lvl_xp_sum)
|
||||
next_lvl_xp -= current_lvl_xp_sum
|
||||
.["lvl_base_num"] = .["lvl_mod_num"] = level
|
||||
.["lvl_base"] = .["lvl_mod"] = associative ? (!level ? unskilled_tier : levels[level]) : level
|
||||
.["base_style"] = .["mod_style"] = "font-weight:bold; color:hsl([(level+1)*(350/max_levels+1)], 50%, 50%)"
|
||||
.["xp_next_lvl_base"] = .["xp_next_lvl_mod"] = "\[[skill_value_base - current_lvl_xp_sum]/[next_lvl_xp]\]"
|
||||
|
||||
return "[associative ? current_lvl : "Lvl. [current_lvl]"] ([value - current_lvl_xp_sum]/[next_lvl_xp])[level == max_levels ? " \[MAX!\]" : ""]"
|
||||
.["max_lvl"] = max_levels
|
||||
var/max_value = associative ? levels[levels[max_levels]] : levels[max_levels]
|
||||
.["max_value"] = max_value
|
||||
|
||||
.["base_readout"] = "Overall Skill Progress: \[[skill_value_base]/[max_value]\]"
|
||||
.["mod_readout"] = "Overall Skill Progress: \[[skill_value_mod]/[max_value]\]"
|
||||
|
||||
var/list/mods = LAZYACCESS(H.skill_level_mods, type)
|
||||
if(mods) //I'm not proud of doing the same-ish process twice a row but here we go.
|
||||
var/list/mod_names = .["modifiers"]
|
||||
if(!mod_names)
|
||||
.["modifiers"] = mod_names = list()
|
||||
for(var/k in mods)
|
||||
var/datum/skill_modifier/M = GLOB.skill_modifiers[k]
|
||||
mod_names |= M.name
|
||||
level = M.apply_modifier(level, type, H, MODIFIER_TARGET_LEVEL)
|
||||
|
||||
if(level)
|
||||
current_lvl_xp_sum = associative ? levels[levels[level]] : levels[level]
|
||||
else
|
||||
current_lvl_xp_sum = 0
|
||||
next_index = min(max_levels, level+1)
|
||||
next_lvl_xp = associative ? levels[levels[next_index]] : levels[next_index]
|
||||
if(next_lvl_xp > current_lvl_xp_sum)
|
||||
next_lvl_xp -= current_lvl_xp_sum
|
||||
.["lvl_mod_num"] = level
|
||||
.["lvl_mod"] = associative ? (!level ? unskilled_tier : levels[level]) : level
|
||||
.["mod_style"] = "font-weight:bold; color:hsl([(level+1)*(300/(max_levels+1))], 50%, 50%)"
|
||||
.["xp_next_lvl_mod"] = "\[[skill_value_mod - current_lvl_xp_sum]/[next_lvl_xp]\]"
|
||||
|
||||
/**
|
||||
* Gets the base value required to reach a level specified by the 'num' arg.
|
||||
*/
|
||||
/datum/skill/level/proc/get_skill_level_value(num)
|
||||
switch(level_up_method)
|
||||
if(STANDARD_LEVEL_UP)
|
||||
. = XP_LEVEL(standard_xp_lvl_up, xp_lvl_multiplier, num)
|
||||
if(DWARFY_LEVEL_UP)
|
||||
. = DORF_XP_LEVEL(standard_xp_lvl_up, xp_lvl_multiplier, num)
|
||||
|
||||
/datum/skill/level/job
|
||||
abstract_type = /datum/skill/level/job
|
||||
|
||||
@@ -20,6 +20,18 @@
|
||||
var/list/original_values
|
||||
var/list/original_affinities
|
||||
var/list/original_levels
|
||||
/// The mind datum this skill is associated with, only used for the check_skills UI
|
||||
var/datum/mind/owner
|
||||
/// For UI updates.
|
||||
var/need_static_data_update = TRUE
|
||||
/// Whether modifiers and final skill values or only base values are displayed.
|
||||
var/see_skill_mods = TRUE
|
||||
/// The current selected skill category.
|
||||
var/selected_category
|
||||
|
||||
/datum/skill_holder/New(owner)
|
||||
..()
|
||||
src.owner = owner
|
||||
|
||||
/**
|
||||
* Grabs the value of a skill.
|
||||
@@ -79,6 +91,7 @@
|
||||
CRASH("Invalid set_skill_value call. Use skill typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
|
||||
var/datum/skill/S = GLOB.skill_datums[skill]
|
||||
value = S.sanitize_value(value)
|
||||
skill_holder.need_static_data_update = TRUE
|
||||
if(!isnull(value))
|
||||
LAZYINITLIST(skill_holder.skills)
|
||||
S.set_skill_value(skill_holder, value, src, silent)
|
||||
@@ -183,18 +196,3 @@
|
||||
divisor++
|
||||
if(divisor)
|
||||
. = modifier_is_multiplier ? value*(sum/divisor) : value/(sum/divisor)
|
||||
|
||||
/**
|
||||
* Generates a HTML readout of our skills.
|
||||
* Port to tgui-next when?
|
||||
*/
|
||||
/datum/mind/proc/skill_html_readout()
|
||||
var/list/out = list("<center><h1>Skills</h1></center><hr>")
|
||||
out += "<table style=\"width:100%\"><tr><th><b>Skill</b><th><b>Value</b></tr>"
|
||||
for(var/path in GLOB.skill_datums)
|
||||
var/datum/skill/S = GLOB.skill_datums[path]
|
||||
var/skill_value = get_skill_value(path)
|
||||
var/skill_level = get_skill_level(path, round = TRUE)
|
||||
out += "<tr><td><font color='[S.name_color]'>[S.name]</font></td><td>[S.standard_render_value(skill_value, skill_level)]</td></tr>"
|
||||
out += "</table>"
|
||||
return out.Join("")
|
||||
|
||||
@@ -7,6 +7,8 @@ GLOBAL_LIST_EMPTY(potential_mods_per_skill)
|
||||
* and cause lots of edge cases. These are fairly simple overall... make a subtype though, don't use this one.
|
||||
*/
|
||||
/datum/skill_modifier
|
||||
/// Name and description of the skill modifier, used in the UI
|
||||
var/name = "???"
|
||||
/// flags for this skill modifier.
|
||||
var/modifier_flags = NONE
|
||||
/// target skills, can be a specific skill typepath or a list of skill traits.
|
||||
@@ -110,6 +112,7 @@ GLOBAL_LIST_EMPTY(potential_mods_per_skill)
|
||||
if(M.modifier_flags & MODIFIER_SKILL_LEVEL)
|
||||
ADD_MOD_STEP(skill_holder.skill_level_mods, path, skill_holder.original_levels, get_skill_level(path, FALSE))
|
||||
LAZYSET(skill_holder.all_current_skill_modifiers, id, TRUE)
|
||||
skill_holder.need_static_data_update = TRUE
|
||||
|
||||
if(M.modifier_flags & MODIFIER_SKILL_BODYBOUND)
|
||||
M.RegisterSignal(src, COMSIG_MIND_TRANSFER, /datum/skill_modifier.proc/on_mind_transfer)
|
||||
@@ -141,6 +144,7 @@ GLOBAL_LIST_EMPTY(potential_mods_per_skill)
|
||||
if(M.modifier_flags & MODIFIER_SKILL_LEVEL && skill_holder.skill_level_mods)
|
||||
REMOVE_MOD_STEP(skill_holder.skill_level_mods, path, skill_holder.original_levels)
|
||||
LAZYREMOVE(skill_holder.all_current_skill_modifiers, id)
|
||||
skill_holder.need_static_data_update = TRUE
|
||||
|
||||
if(!mind_transfer && M.modifier_flags & MODIFIER_SKILL_BODYBOUND)
|
||||
M.UnregisterSignal(src, COMSIG_MIND_TRANSFER)
|
||||
@@ -165,11 +169,7 @@ GLOBAL_LIST_EMPTY(potential_mods_per_skill)
|
||||
var/datum/skill/S = GLOB.skill_datums[skillpath]
|
||||
if(method == MODIFIER_TARGET_VALUE && S.progression_type == SKILL_PROGRESSION_LEVEL)
|
||||
var/datum/skill/level/L = S
|
||||
switch(L.level_up_method)
|
||||
if(STANDARD_LEVEL_UP)
|
||||
mod = XP_LEVEL(L.standard_xp_lvl_up, L.xp_lvl_multiplier, S.competency_thresholds[mod])
|
||||
if(DWARFY_LEVEL_UP)
|
||||
mod = DORF_XP_LEVEL(L.standard_xp_lvl_up, L.xp_lvl_multiplier, S.competency_thresholds[mod])
|
||||
mod = L.get_skill_level_value(L.competency_thresholds[mod])
|
||||
else
|
||||
mod = S.competency_thresholds[mod]
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/datum/skill/level/job/wiring
|
||||
name = "Wiring"
|
||||
desc = "How proficient and knowledged you are at wiring beyond laying cables on the floor."
|
||||
desc = "How proficient and knowledged you are at wiring beyond making post-futuristic wire art."
|
||||
name_color = COLOR_PALE_ORANGE
|
||||
skill_traits = list(SKILL_SANITY, SKILL_INTELLIGENCE, SKILL_USE_TOOL, SKILL_TRAINING_TOOL)
|
||||
ui_category = SKILL_UI_CAT_ENG
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/datum/skill/numerical/surgery
|
||||
name = "Surgery"
|
||||
desc = "How proficient you are at doing surgery."
|
||||
desc = "How proficient you are at performing surgical procedures."
|
||||
name_color = COLOR_PALE_BLUE_GRAY
|
||||
competency_multiplier = 1.5 // 60% surgery speed up at max value of 100, considering the base multiplier.
|
||||
ui_category = SKILL_UI_CAT_MED
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/// Jobbie skill modifiers.
|
||||
|
||||
/datum/skill_modifier/job
|
||||
name = "Job Training"
|
||||
modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_VIRTUE|MODIFIER_SKILL_ORIGIN_DIFF
|
||||
priority = MODIFIER_SKILL_PRIORITY_MAX
|
||||
|
||||
@@ -23,7 +24,7 @@
|
||||
modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_VIRTUE|MODIFIER_SKILL_ORIGIN_DIFF
|
||||
level_mod = JOB_SKILL_TRAINED
|
||||
|
||||
/datum/skill_modifier/job/level/New(id)
|
||||
/datum/skill_modifier/job/level/New(id, register = FALSE)
|
||||
if(level_mod)
|
||||
value_mod = GET_STANDARD_LVL(level_mod)
|
||||
..()
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/datum/skill_modifier/bad_mood
|
||||
name = "Mood (Dejected)"
|
||||
modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_MULT|MODIFIER_SKILL_BODYBOUND
|
||||
target_skills = list(SKILL_SANITY)
|
||||
|
||||
/datum/skill_modifier/great_mood
|
||||
name = "Mood (Elated)"
|
||||
modifier_flags = MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_MULT|MODIFIER_SKILL_BODYBOUND
|
||||
target_skills = list(SKILL_SANITY)
|
||||
affinity_mod = 1.2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/datum/skill_modifier/brain_damage
|
||||
name = "Brain Damage"
|
||||
target_skills = list(SKILL_INTELLIGENCE)
|
||||
modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_MULT|MODIFIER_SKILL_BODYBOUND
|
||||
value_mod = 0.85
|
||||
@@ -6,6 +7,7 @@
|
||||
affinity_mod = 0.85
|
||||
|
||||
/datum/skill_modifier/heavy_brain_damage
|
||||
name = "Brain Damage (Severe)"
|
||||
target_skills = list(SKILL_INTELLIGENCE)
|
||||
modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_BODYBOUND|MODIFIER_SKILL_HANDICAP|MODIFIER_USE_THRESHOLDS
|
||||
priority = MODIFIER_SKILL_PRIORITY_LOW
|
||||
|
||||
@@ -81,11 +81,11 @@
|
||||
owner.adjustStaminaLoss(-0.5) //reduce stamina loss by 0.5 per tick, 10 per 2 seconds
|
||||
if(human_owner && human_owner.drunkenness)
|
||||
human_owner.drunkenness *= 0.997 //reduce drunkenness by 0.3% per tick, 6% per 2 seconds
|
||||
if(prob(20))
|
||||
if(carbon_owner)
|
||||
carbon_owner.handle_dreams()
|
||||
if(prob(10) && owner.health > owner.crit_threshold)
|
||||
owner.emote("snore")
|
||||
if(carbon_owner && !carbon_owner.dreaming && prob(2))
|
||||
carbon_owner.dream()
|
||||
// 2% per second, tick interval is in deciseconds
|
||||
if(prob((tick_interval+1) * 0.2) && owner.health > owner.crit_threshold)
|
||||
owner.emote("snore")
|
||||
|
||||
/datum/status_effect/staggered
|
||||
id = "staggered"
|
||||
@@ -711,8 +711,9 @@ datum/status_effect/pacify
|
||||
if(hearing_args[HEARING_SPEAKER] == owner)
|
||||
return
|
||||
var/mob/living/carbon/C = owner
|
||||
var/hypnomsg = uncostumize_say(hearing_args[HEARING_RAW_MESSAGE], hearing_args[HEARING_MESSAGE_MODE])
|
||||
C.cure_trauma_type(/datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY) //clear previous hypnosis
|
||||
addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, hearing_args[HEARING_RAW_MESSAGE]), 10)
|
||||
addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, hypnomsg), 10)
|
||||
addtimer(CALLBACK(C, /mob/living.proc/Stun, 60, TRUE, TRUE), 15) //Take some time to think about it
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
var/id = "effect" //Used for screen alerts.
|
||||
var/duration = -1 //How long the status effect lasts in DECISECONDS. Enter -1 for an effect that never ends unless removed through some means.
|
||||
var/tick_interval = 10 //How many deciseconds between ticks, approximately. Leave at 10 for every second.
|
||||
var/next_tick //The scheduled time for the next tick.
|
||||
var/mob/living/owner //The mob affected by the status effect.
|
||||
var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted
|
||||
var/examine_text //If defined, this text will appear when the mob is examined - to use he, she etc. use "SUBJECTPRONOUN" and replace it in the examines themselves
|
||||
@@ -31,7 +32,7 @@
|
||||
return
|
||||
if(duration != -1)
|
||||
duration = world.time + duration
|
||||
tick_interval = world.time + tick_interval
|
||||
next_tick = world.time + tick_interval
|
||||
if(alert_type)
|
||||
var/obj/screen/alert/status_effect/A = owner.throw_alert(id, alert_type)
|
||||
A.attached_effect = src //so the alert can reference us, if it needs to
|
||||
@@ -52,9 +53,9 @@
|
||||
if(!owner)
|
||||
qdel(src)
|
||||
return
|
||||
if(tick_interval < world.time)
|
||||
if(next_tick < world.time)
|
||||
tick()
|
||||
tick_interval = world.time + initial(tick_interval)
|
||||
next_tick = world.time + tick_interval
|
||||
if(duration != -1 && duration < world.time)
|
||||
qdel(src)
|
||||
|
||||
@@ -221,7 +222,7 @@
|
||||
threshold_crossed = FALSE //resets threshold effect if we fall below threshold so threshold effect can trigger again
|
||||
on_threshold_drop()
|
||||
if(stacks_added > 0)
|
||||
tick_interval += delay_before_decay //refreshes time until decay
|
||||
next_tick += delay_before_decay //refreshes time until decay
|
||||
stacks = min(stacks, max_stacks)
|
||||
status_overlay.icon_state = "[overlay_state][stacks]"
|
||||
status_underlay.icon_state = "[underlay_state][stacks]"
|
||||
|
||||
Reference in New Issue
Block a user