mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-22 20:43:10 +01:00
Merge branch 'master' into development
This commit is contained in:
@@ -432,6 +432,7 @@
|
||||
#include "code\game\gamemodes\mixed\conflux.dm"
|
||||
#include "code\game\gamemodes\mixed\crossfire.dm"
|
||||
#include "code\game\gamemodes\mixed\infestation.dm"
|
||||
#include "code\game\gamemodes\mixed\intrigue.dm"
|
||||
#include "code\game\gamemodes\mixed\paranoia.dm"
|
||||
#include "code\game\gamemodes\mixed\siege.dm"
|
||||
#include "code\game\gamemodes\mixed\traitorling.dm"
|
||||
|
||||
@@ -125,11 +125,6 @@
|
||||
#define MOB_TINY 4
|
||||
#define MOB_MINISCULE 1
|
||||
|
||||
// Gluttony levels.
|
||||
#define GLUT_TINY 1 // Eat anything tiny and smaller
|
||||
#define GLUT_SMALLER 2 // Eat anything smaller than we are
|
||||
#define GLUT_ANYTHING 3 // Eat anything, ever
|
||||
|
||||
#define BASE_MAX_NUTRITION 400
|
||||
#define HUNGER_FACTOR 0.05 // Factor of how fast mob nutrition decreases. Moved here from chemistry define
|
||||
|
||||
@@ -181,7 +176,7 @@
|
||||
#define TYPE_ORGANIC 1//Almost any creature under /mob/living/carbon and most simple animals
|
||||
#define TYPE_SYNTHETIC 2//Everything under /mob/living/silicon, plus IPCs, viscerators
|
||||
#define TYPE_HUMANOID 4//Humans, skrell, unathi, tajara, vaurca, diona, IPC, vox
|
||||
#define TYPE_WIERD 8//Slimes, constructs, demons, and other creatures of a magical or bluespace nature.
|
||||
#define TYPE_WEIRD 8//Slimes, constructs, demons, and other creatures of a magical or bluespace nature.
|
||||
|
||||
// Maximum number of chickens allowed at once.
|
||||
// If the number of chickens on the map exceeds this, laid eggs will not hatch.
|
||||
|
||||
@@ -96,6 +96,25 @@ var/global/list/syndicate_access = list(access_maint_tunnels, access_syndicate,
|
||||
//Cloaking devices
|
||||
var/global/list/cloaking_devices = list()
|
||||
|
||||
// Devour types (these are typecaches). Only simple_animals check these, other types are handled specially.
|
||||
/var/list/mtl_synthetic = list(
|
||||
/mob/living/simple_animal/hostile/hivebot
|
||||
)
|
||||
|
||||
/var/list/mtl_weird = list(
|
||||
/mob/living/simple_animal/construct,
|
||||
/mob/living/simple_animal/shade,
|
||||
/mob/living/simple_animal/slime,
|
||||
/mob/living/simple_animal/hostile/faithless
|
||||
)
|
||||
|
||||
// Actual human mobs are delibrately not in this list as they are handled elsewhere.
|
||||
/var/list/mtl_humanoid = list(
|
||||
/mob/living/simple_animal/hostile/pirate,
|
||||
/mob/living/simple_animal/hostile/russian,
|
||||
/mob/living/simple_animal/hostile/syndicate
|
||||
)
|
||||
|
||||
//////////////////////////
|
||||
/////Initial Building/////
|
||||
//////////////////////////
|
||||
@@ -194,6 +213,17 @@ var/global/list/cloaking_devices = list()
|
||||
var/datum/poster/P = new T
|
||||
poster_designs += P
|
||||
|
||||
// Some setup work for the eat-types lists.
|
||||
mtl_synthetic = typecacheof(mtl_synthetic) + list(
|
||||
/mob/living/simple_animal/hostile/retaliate/malf_drone,
|
||||
/mob/living/simple_animal/hostile/viscerator,
|
||||
/mob/living/simple_animal/spiderbot
|
||||
)
|
||||
|
||||
mtl_weird = typecacheof(mtl_weird) + /mob/living/simple_animal/adultslime
|
||||
|
||||
mtl_humanoid = typecacheof(mtl_humanoid)
|
||||
|
||||
return 1
|
||||
|
||||
/* // Uncomment to debug chemical reaction list.
|
||||
|
||||
@@ -160,6 +160,7 @@ var/list/gamemode_cache = list()
|
||||
var/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt
|
||||
var/use_age_restriction_for_jobs = 0 //Do jobs use account age restrictions? --requires database
|
||||
var/use_age_restriction_for_antags = 0 //Do antags use account age restrictions? --requires database
|
||||
var/age_restrictions_from_file = 0 // Are hardcoded values used or config ones?
|
||||
var/sql_stats = 0 //Do we record round statistics on the database (deaths, round reports, population, etcetera) or not?
|
||||
var/sql_whitelists = 0 //Defined whether the server uses an SQL based whitelist system, or the legacy one with two .txts. Config option in config.txt
|
||||
var/sql_saves = 0 //Defines whether the server uses an SQL based character and preference saving system. Config option in config.txt
|
||||
@@ -332,6 +333,9 @@ var/list/gamemode_cache = list()
|
||||
if ("use_age_restriction_for_antags")
|
||||
config.use_age_restriction_for_antags = 1
|
||||
|
||||
if ("load_age_restrictions_from_file")
|
||||
config.age_restrictions_from_file = 1
|
||||
|
||||
if ("jobs_have_minimal_access")
|
||||
config.jobs_have_minimal_access = 1
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ var/global/list/bantype_to_antag_age = list()
|
||||
|
||||
// Set up age restrictions for the different antag bantypes.
|
||||
if (!bantype_to_antag_age[A.bantype])
|
||||
if (config.age_restrictions[lowertext(A.bantype)])
|
||||
if (config.age_restrictions_from_file && config.age_restrictions[lowertext(A.bantype)])
|
||||
bantype_to_antag_age[lowertext(A.bantype)] = config.age_restrictions[lowertext(A.bantype)]
|
||||
else
|
||||
bantype_to_antag_age[A.bantype] = 0
|
||||
|
||||
@@ -236,7 +236,7 @@
|
||||
return
|
||||
|
||||
var/types = victim.find_type()
|
||||
if ((!(types & TYPE_ORGANIC)) || ((types & TYPE_WIERD)))
|
||||
if ((!(types & TYPE_ORGANIC)) || ((types & TYPE_WEIRD)))
|
||||
//Invalid sacrifice. Display a message and return
|
||||
speak_to(user, "This soulless automaton cannot satisfy our hunger. We yearn for life essence, it must have a soul.")
|
||||
return
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/datum/game_mode/uprising
|
||||
name = "Uprising (Cult+Rev)"
|
||||
name = "Uprising (Rev+Traitor)"
|
||||
config_tag = "uprising"
|
||||
round_description = "Some crewmembers are attempting to start a revolution while a cult plots in the shadows!"
|
||||
extended_round_description = "Cultists and revolutionaries spawn in this round."
|
||||
round_description = "Some crewmembers are attempting to start a revolution while subversive elements infest the crew!"
|
||||
extended_round_description = "Traitors and revolutionaries spawn in this round."
|
||||
required_players = 15
|
||||
required_enemies = 3
|
||||
end_on_antag_death = 1
|
||||
antag_tags = list(MODE_REVOLUTIONARY, MODE_LOYALIST, MODE_CULTIST)
|
||||
antag_tags = list(MODE_REVOLUTIONARY, MODE_LOYALIST, MODE_TRAITOR)
|
||||
require_all_templates = 1
|
||||
votable = 1
|
||||
|
||||
@@ -119,8 +119,13 @@
|
||||
return (current_positions < total_positions) || (total_positions == -1)
|
||||
|
||||
/datum/job/proc/fetch_age_restriction()
|
||||
if (!config.age_restrictions_from_file)
|
||||
return
|
||||
|
||||
if (config.age_restrictions[lowertext(title)])
|
||||
minimal_player_age = config.age_restrictions[lowertext(title)]
|
||||
else
|
||||
minimal_player_age = 0
|
||||
|
||||
/datum/job/proc/late_equip(var/mob/living/carbon/human/H)
|
||||
if(!H)
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
/obj/item/weapon/storage/fancy/cigarettes/killthroat = 5
|
||||
)
|
||||
prices = list(
|
||||
/obj/item/weapon/storage/fancy/cigarettes = 510,
|
||||
/obj/item/weapon/storage/fancy/cigarettes = 200,
|
||||
/obj/item/weapon/storage/box/matches = 12,
|
||||
/obj/item/weapon/flame/lighter/random = 12
|
||||
)
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
if(!H.gloves)
|
||||
H.apply_effect(250/(target.mob_size*(target.mob_size*0.25)), AGONY)
|
||||
if (!(types & TYPE_SYNTHETIC))
|
||||
target.apply_damage(rand(6,14), BRUTE, def_zone = zone, used_weapon = src)
|
||||
target.apply_damage(rand(6,14), AGONY, def_zone = zone, used_weapon = src)
|
||||
target.apply_damage(rand(1,3), BRUTE, def_zone = zone, used_weapon = src)
|
||||
|
||||
playsound(target.loc, 'sound/effects/snap.ogg', 50, 1)
|
||||
layer = MOB_LAYER - 0.2
|
||||
|
||||
@@ -68,8 +68,8 @@
|
||||
spawn_area_type = /area/engineering/atmos
|
||||
locstrings[numlocs] = "atmospherics"
|
||||
if(LOC_INCIN)
|
||||
spawn_area_type = /area/maintenance/incinerator
|
||||
locstrings[numlocs] = "the incinerator"
|
||||
spawn_area_type = /area/maintenance/disposal
|
||||
locstrings[numlocs] = "waste disposal"
|
||||
if(LOC_CHAPEL)
|
||||
spawn_area_type = /area/chapel/main
|
||||
locstrings[numlocs] = "the chapel"
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
donor.adjustBruteLoss(4)
|
||||
nutrition += 20
|
||||
return
|
||||
else if (types & TYPE_WIERD)
|
||||
else if (types & TYPE_WEIRD)
|
||||
src.visible_message("<span class='danger'>[src] attempts to bite into [donor.name] but passes right through it!.</span>", "<span class='danger'>You attempt to sink your fangs into [donor.name] but pass right through it!</span>")
|
||||
return
|
||||
else if (donor.is_diona())
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
nutrition = max_nutrition
|
||||
|
||||
//handle_trace_chems() implement this later maybe
|
||||
handle_stomach()
|
||||
updatehealth()
|
||||
|
||||
return
|
||||
|
||||
@@ -151,6 +151,9 @@ emp_act
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
|
||||
if(check_attack_throat(I, user))
|
||||
return null
|
||||
|
||||
if(user == src) // Attacking yourself can't miss
|
||||
return target_zone
|
||||
|
||||
|
||||
@@ -44,33 +44,18 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy/mannequin)
|
||||
h_style = "blue IPC screen"
|
||||
. = ..(mapload, "Baseline Frame")
|
||||
|
||||
/mob/living/carbon/human/monkey
|
||||
mob_size = 2.6//Based on howler monkey, rough real world equivilant to on-mob sprite size
|
||||
|
||||
/mob/living/carbon/human/monkey/Initialize(mapload)
|
||||
. = ..(mapload, "Monkey")
|
||||
|
||||
/mob/living/carbon/human/farwa
|
||||
mob_size = 2.6//Roughly the same size as monkey
|
||||
|
||||
/mob/living/carbon/human/farwa/Initialize(mapload)
|
||||
. = ..(mapload, "Farwa")
|
||||
|
||||
/mob/living/carbon/human/neaera
|
||||
mob_size = 2.6//Roughly the same size as monkey
|
||||
|
||||
/mob/living/carbon/human/neaera/Initialize(mapload)
|
||||
. = ..(mapload, "Neaera")
|
||||
|
||||
/mob/living/carbon/human/stok
|
||||
mob_size = 2.6//Roughly the same size as monkey
|
||||
|
||||
/mob/living/carbon/human/stok/Initialize(mapload)
|
||||
. = ..(mapload, "Stok")
|
||||
|
||||
/mob/living/carbon/human/bug
|
||||
mob_size = 2.6//Roughly the same size as monkey
|
||||
|
||||
/mob/living/carbon/human/bug/Initialize(mapload)
|
||||
. = ..(mapload, "V'krexi")
|
||||
src.gender = FEMALE
|
||||
|
||||
@@ -71,9 +71,6 @@
|
||||
//Random events (vomiting etc)
|
||||
handle_random_events()
|
||||
|
||||
//stuff in the stomach
|
||||
handle_stomach()//This function is in devour.dm
|
||||
|
||||
handle_shock()
|
||||
|
||||
handle_pain()
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
cold_level_3 = 0
|
||||
|
||||
eyes = "vox_eyes_s"
|
||||
gluttonous = GLUT_SMALLER
|
||||
gluttonous = TRUE
|
||||
virus_immune = 1
|
||||
|
||||
breath_type = "nitrogen"
|
||||
|
||||
@@ -143,7 +143,8 @@
|
||||
var/sprint_cost_factor = 0.9 // Multiplier on stamina cost for sprinting
|
||||
var/exhaust_threshold = 50 // When stamina runs out, the mob takes oxyloss up til this value. Then collapses and drops to walk
|
||||
|
||||
var/gluttonous // Can eat some mobs. Values can be GLUT_TINY, GLUT_SMALLER, GLUT_ANYTHING.
|
||||
var/gluttonous // Can eat some mobs. Boolean.
|
||||
var/mouth_size // How big the mob's mouth is. Limits how large a mob this species can swallow. Only relevant if gluttonous is TRUE.
|
||||
var/max_nutrition_factor = 1 //Multiplier on maximum nutrition
|
||||
var/nutrition_loss_factor = 1 //Multiplier on passive nutrition losses
|
||||
|
||||
@@ -327,6 +328,7 @@
|
||||
H.mob_push_flags = push_flags
|
||||
H.pass_flags = pass_flags
|
||||
H.mob_size = mob_size
|
||||
H.mouth_size = mouth_size || 2
|
||||
if(!kpg)
|
||||
if(islesserform(H))
|
||||
H.dna.SetSEState(MONKEYBLOCK,1)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
mob_size = MOB_SMALL
|
||||
holder_type = /obj/item/weapon/holder/human
|
||||
short_sighted = 1
|
||||
gluttonous = GLUT_TINY
|
||||
gluttonous = TRUE
|
||||
|
||||
spawn_flags = IS_RESTRICTED
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_EYE_COLOR
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
|
||||
has_fine_manipulation = 0
|
||||
siemens_coefficient = 0
|
||||
gluttonous = GLUT_ANYTHING
|
||||
gluttonous = TRUE
|
||||
mouth_size = 15 // Should be larger than any human-type.
|
||||
mob_size = 14
|
||||
fall_mod = 0
|
||||
|
||||
eyes = "blank_eyes"
|
||||
|
||||
@@ -3,11 +3,9 @@
|
||||
//There are two ways to eat a mob:
|
||||
//Swallowing whole can only be done if the mob is sufficiently small
|
||||
//It will place the mob inside you, and slowly digest it,
|
||||
//Digesting deals genetic damage to the victim,
|
||||
//drains blood from it,
|
||||
//and adds protein to your stomach, based on the quantitys.
|
||||
//Digesting deals brute+fire damage to the victim and adds protein to your stomach based on the damage dealt.
|
||||
//Mob will be deleted from your contents when fully digested.
|
||||
//Mob is fully digested when it has taken genetic damage equal to its max health. This continues past death if necessary
|
||||
//Mob is fully digested when it has taken fire+brute damage equal to its max health plus 50% (calculated after death)
|
||||
|
||||
//Devouring eats the mob piece by piece. Taking a bite periodically
|
||||
//Each bite deals genetic damage, and drains blood.
|
||||
@@ -15,19 +13,13 @@
|
||||
//Mob is fully digested when it has taken genetic damage equal to its max health. This continues past death if necessary
|
||||
//Devouring is interrupted if you or the mob move away from each other, or if the eater gets disabled.
|
||||
|
||||
#define PPM 9//Protein per meat, used for calculating the quantity of protein in an animal
|
||||
#define PPM 9 //Protein per meat, used for calculating the quantity of protein in an animal
|
||||
|
||||
|
||||
/mob/living/var/swallowed_mob = 0
|
||||
//This is set true if there are any mobs in this mob's contents. they will be slowly digested.
|
||||
//just used as a boolean to minimise extra processing
|
||||
|
||||
/mob/living/var/mob/living/devouring = null
|
||||
//If we are currently devouring a mob, a reference to it goes here.
|
||||
/mob/living
|
||||
var/mob/living/devouring // The mob we're currently eating, if any.
|
||||
|
||||
/mob/living/proc/attempt_devour(var/mob/living/victim, var/eat_types, var/mouth_size = null)
|
||||
|
||||
|
||||
//This function will attempt to eat the victim,
|
||||
//either by swallowing them if they're small enough, or starting to devour them otherwise
|
||||
//If a mouth_size is passed in, it will be used instead of this mob's size, for determining whether the victim is small enough to swallow
|
||||
@@ -81,23 +73,28 @@
|
||||
devour_gradual(victim,mouth_size)
|
||||
|
||||
/mob/living/proc/swallow(var/mob/living/victim, var/mouth_size)
|
||||
set waitfor = FALSE
|
||||
//This function will move the victim inside the eater's contents.. There they will be digested over time
|
||||
|
||||
var/swallow_time = max(3 + (victim.mob_size * victim.mob_size) - mouth_size, 3)
|
||||
src.visible_message("[src] starts swallowing \the [victim]!","You start swallowing \the [victim], this will take approximately [swallow_time] seconds.")
|
||||
var/turf/ourloc = src.loc
|
||||
var/turf/victimloc = victim.loc
|
||||
if (do_mob(src, victim, swallow_time*10))
|
||||
devouring = victim
|
||||
if (do_mob(src, victim, swallow_time*10, extra_checks = CALLBACK(src, .proc/devouring_equals, victim)))
|
||||
victim.forceMove(src)
|
||||
LAZYADD(stomach_contents, victim)
|
||||
else if (victimloc != victim.loc)
|
||||
src << "[victim] moved away, you need to keep it still. Try grabbing, stunning or killing it first."
|
||||
else if (ourloc != src.loc)
|
||||
src << "You moved! Can't eat if you move away from the victim"
|
||||
else
|
||||
else if (devouring)
|
||||
src << "Swallowing failed!"//reason unknown, maybe the eater got stunned?
|
||||
|
||||
devouring = null
|
||||
|
||||
/mob/living/proc/devour_gradual(var/mob/living/victim, var/mouth_size)
|
||||
set waitfor = FALSE
|
||||
//This function will start consuming the victim by taking bites out of them.
|
||||
//Victim or attacker moving will interrupt it
|
||||
//A bite will be taken every 4 seconds
|
||||
@@ -135,18 +132,17 @@
|
||||
|
||||
src.visible_message("<span class='danger'>[src] starts devouring [victim]</span>","<span class='danger'>You start devouring [victim], this will take approximately [time_needed_string]. You and the victim must remain still to continue, but you can interrupt feeding anytime and leave with what you've already eaten.</span>")
|
||||
|
||||
var/i = 0
|
||||
for (i=0;i < num_bites_needed;i++)
|
||||
if(do_mob(src, victim, bite_delay*10) && devouring == victim)
|
||||
for (var/i = 1 to num_bites_needed)
|
||||
if(do_mob(src, victim, bite_delay*10, extra_checks = CALLBACK(src, .proc/devouring_equals, victim)))
|
||||
face_atom(victim)
|
||||
victim.adjustCloneLoss(victim_maxhealth*PEPB)
|
||||
victim.adjustHalLoss(victim_maxhealth*PEPB*5)//Being eaten hurts!
|
||||
src.ingested.add_reagent(victim.composition_reagent, victim.composition_reagent_quantity*PEPB)
|
||||
src.visible_message("<span class='danger'>[src] bites a chunk out of [victim]</span>","<span class='danger'>[bitemessage(victim)]</span>")
|
||||
ingested.add_reagent(victim.composition_reagent, victim.composition_reagent_quantity*PEPB)
|
||||
visible_message("<span class='danger'>[src] bites a chunk out of [victim]</span>","<span class='danger'>[bitemessage(victim)]</span>")
|
||||
if (messes < victim.mob_size - 1 && prob(50))
|
||||
handle_devour_mess(src, victim, vessel)
|
||||
if (victim.cloneloss >= victim_maxhealth)
|
||||
src.visible_message("[src] finishes devouring [victim]","You finish devouring [victim]")
|
||||
visible_message("[src] finishes devouring [victim].","You finish devouring [victim].")
|
||||
handle_devour_mess(src, victim, vessel, 1)
|
||||
qdel(victim)
|
||||
devouring = null
|
||||
@@ -156,39 +152,47 @@
|
||||
if (victim && victimloc != victim.loc)
|
||||
src << "<span class='danger'>[victim] moved away, you need to keep it still. Try grabbing, stunning or killing it first.</span>"
|
||||
else if (ourloc != src.loc)
|
||||
src << "<span class='danger'>You moved! Devouring cancelled</span>"
|
||||
src << "<span class='danger'>You moved! Devouring cancelled.</span>"
|
||||
else
|
||||
src << "Devouring Cancelled"//reason unknown, maybe the eater got stunned?
|
||||
src << "Devouring Cancelled."//reason unknown, maybe the eater got stunned?
|
||||
//This can also happen if you start devouring something else
|
||||
break
|
||||
|
||||
/mob/living/proc/devouring_equals(target)
|
||||
return target && devouring == target
|
||||
|
||||
//this function gradually digests things inside the mob's contents.
|
||||
//It is called from life.dm. Any creatures that don't want to digest their contents simply don't call it
|
||||
/mob/living/proc/handle_stomach()
|
||||
for(var/mob/living/M in stomach_contents)
|
||||
if(M.loc != src)//if something somehow escaped the stomach, then we remove it
|
||||
LAZYREMOVE(stomach_contents, M)
|
||||
continue
|
||||
if (stomach_contents)
|
||||
for(var/thing in stomach_contents)
|
||||
var/mob/living/M = thing
|
||||
if(M.loc != src)//if something somehow escaped the stomach, then we remove it
|
||||
LAZYREMOVE(stomach_contents, M)
|
||||
continue
|
||||
|
||||
if(!M.composition_reagent_quantity)
|
||||
M.calculate_composition()
|
||||
if(!M.composition_reagent_quantity)
|
||||
M.calculate_composition()
|
||||
|
||||
var/digestion_power = (((mob_size * mob_size)/10) / (M.mob_size * M.mob_size))
|
||||
var/digestion_time = digestion_power * 60 //Number of seconds it will take to digest in total
|
||||
var/DPPP = 1 / (digestion_time / 2.1) //Digestion percentage per proc
|
||||
M.adjustCloneLoss(M.maxHealth*DPPP)
|
||||
//Digestion power is how much of the creature we can digest per minute. Calculated as a tenth of our mob size squared, divided by the victim's mob size squared
|
||||
//If the resulting value is >1, digestion will take under a minute.
|
||||
src.ingested.add_reagent(M.composition_reagent, M.composition_reagent_quantity*DPPP)
|
||||
if ((M.stat != DEAD) && (M.cloneloss > (M.maxHealth*0.5))) //If we've consumed half of the victim, then it dies
|
||||
M.death()
|
||||
M.stat = DEAD //Just in case the death function doesn't set it
|
||||
src << "Your stomach feels a little more relaxed as \the [M] finally stops fighting."
|
||||
var/dmg_factor = 2*log(M.mob_size) // log(n) is natural log in BYOND.
|
||||
if (dmg_factor <= 0)
|
||||
dmg_factor = 0.5
|
||||
|
||||
if (M.cloneloss >= M.maxHealth) //If we've consumed all of it, then digestion is finished.
|
||||
LAZYREMOVE(stomach_contents, M)
|
||||
src << "Your stomach feels a little more empty as you finish digesting \the [M]."
|
||||
qdel(M)
|
||||
M.adjustBruteLoss(round(dmg_factor * 0.33, 0.1) || 0.1)
|
||||
M.adjustFireLoss(round(dmg_factor * 0.66, 0.1) || 0.1)
|
||||
|
||||
ingested.add_reagent(M.composition_reagent, M.composition_reagent_quantity * 1/dmg_factor)
|
||||
|
||||
if (M.stat == DEAD && !stomach_contents[M]) // If the mob has died, poke the consuming mob about it.
|
||||
src << "Your stomach feels a little more relaxed as \the [M] finally stops fighting."
|
||||
stomach_contents[M] = TRUE // So the message doesn't play more than once.
|
||||
continue
|
||||
|
||||
var/damage_dealt = (M.getFireLoss() * 0.66) + (M.getBruteLoss() * 0.33)
|
||||
if (stomach_contents[M] && (damage_dealt >= M.maxHealth * 1.5)) //If we've consumed all of it (plus a bit), then digestion is finished.
|
||||
LAZYREMOVE(stomach_contents, M)
|
||||
src << "Your stomach feels a little more empty as you finish digesting \the [M]."
|
||||
qdel(M)
|
||||
|
||||
//Helpers
|
||||
/proc/bitemessage(var/mob/living/victim)
|
||||
@@ -238,7 +242,6 @@
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/proc/devour_add_blood(var/mob/living/M, var/turf/location, var/datum/reagents/vessel)
|
||||
for(var/datum/reagent/blood/source in vessel.reagent_list)
|
||||
var/obj/effect/decal/cleanable/blood/B = new /obj/effect/decal/cleanable/blood(location)
|
||||
@@ -269,25 +272,8 @@
|
||||
return 0
|
||||
|
||||
/proc/is_valid_for_devour(var/mob/living/test, var/eat_types)
|
||||
var/mobtypes = test.find_type()//We find a bitfield of types for the victim
|
||||
|
||||
//Then for each type the victim has, we test if we're allowed to eat that type.
|
||||
//eat_types must contain all types that the mob has. For example we need both humanoid and synthetic to eat an IPC
|
||||
if (mobtypes & TYPE_SYNTHETIC)
|
||||
if (!(eat_types & TYPE_SYNTHETIC))
|
||||
return 0
|
||||
if (mobtypes & TYPE_HUMANOID)
|
||||
if (!(eat_types & TYPE_HUMANOID))
|
||||
return 0
|
||||
if (mobtypes & TYPE_WIERD)
|
||||
if (!(eat_types & TYPE_WIERD))
|
||||
return 0
|
||||
if (mobtypes & TYPE_ORGANIC)
|
||||
if (!(eat_types & TYPE_ORGANIC))
|
||||
return 0
|
||||
|
||||
//If we get here, none of the checks have failed, the mob must be valid!
|
||||
return 1
|
||||
//eat_types must contain all types that the mob has. For example we need both humanoid and synthetic to eat an IPC.
|
||||
. = (test.find_type() & eat_types) == eat_types
|
||||
|
||||
/mob/living/proc/calculate_composition()
|
||||
if (!composition_reagent)//if no reagent has been set, then we'll set one
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/mob/living/simple_animal/mouse
|
||||
name = "mouse"
|
||||
real_name = "mouse"
|
||||
desc = "It's a small rodent, often seen hiding in maintenance areas and making a nuisance of itself."
|
||||
desc = "It's a small, disgusting rodent, often found being annoying, and aiding in the spread of disease."
|
||||
|
||||
icon = 'icons/mob/mouse.dmi'
|
||||
icon_state = "mouse_gray"
|
||||
@@ -19,10 +19,10 @@
|
||||
'sound/effects/creatures/mouse_squeaks_3.ogg',
|
||||
'sound/effects/creatures/mouse_squeaks_4.ogg')
|
||||
var/last_softsqueak = null//Used to prevent the same soft squeak twice in a row
|
||||
var/squeals = 5//Spam control. You people are why we cant have nice things >:(
|
||||
var/maxSqueals = 5//SPAM PROTECTION
|
||||
var/squeals = 5//Spam control.
|
||||
var/maxSqueals = 2//SPAM PROTECTION
|
||||
var/last_squealgain = 0// #TODO-FUTURE: Remove from life() once something else is created
|
||||
|
||||
var/squeakcooldown = 0
|
||||
pass_flags = PASSTABLE
|
||||
speak_chance = 5
|
||||
turns_per_move = 5
|
||||
@@ -32,7 +32,7 @@
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "stamps on"
|
||||
response_harm = "stomps on"
|
||||
density = 0
|
||||
meat_amount = 1
|
||||
var/body_color //brown, gray and white, leave blank for random
|
||||
@@ -79,12 +79,12 @@
|
||||
else
|
||||
if ((world.time - timeofdeath) > decompose_time)
|
||||
dust()
|
||||
|
||||
|
||||
/mob/living/simple_animal/mouse/Destroy()
|
||||
SSmob.all_mice -= src
|
||||
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
//Pixel offsetting as they scamper around
|
||||
/mob/living/simple_animal/mouse/Move()
|
||||
if(..())
|
||||
@@ -152,6 +152,8 @@
|
||||
//This is triggered when a mob steps on an NPC mouse, or manually by a playermouse
|
||||
/mob/living/simple_animal/mouse/proc/squeak(var/manual = 1)
|
||||
if (stat == CONSCIOUS)
|
||||
if (squeakcooldown > world.time) return
|
||||
squeakcooldown = world.time + 2 SECONDS
|
||||
playsound(src, 'sound/effects/mousesqueek.ogg', 70, 1)
|
||||
if (manual)
|
||||
log_say("[key_name(src)] squeaks! ",ckey=key_name(src))
|
||||
@@ -165,6 +167,9 @@
|
||||
var/sound = pick(new_squeaks)
|
||||
|
||||
last_softsqueak = sound
|
||||
if (squeakcooldown > world.time) return
|
||||
|
||||
squeakcooldown = world.time + 2 SECONDS
|
||||
playsound(src, sound, 5, 1, -4.6)
|
||||
|
||||
if (manual)
|
||||
@@ -175,6 +180,9 @@
|
||||
//Triggered manually, when a mouse dies, or rarely when its stepped on
|
||||
/mob/living/simple_animal/mouse/proc/squeak_loud(var/manual = 0)
|
||||
if (stat == CONSCIOUS)
|
||||
if (squeakcooldown > world.time) return
|
||||
squeakcooldown = world.time + 4 SECONDS
|
||||
|
||||
if (squeals > 0 || !manual)
|
||||
playsound(src, 'sound/effects/creatures/mouse_squeak_loud.ogg', 50, 1)
|
||||
squeals --
|
||||
@@ -231,7 +239,7 @@
|
||||
squeak(0)
|
||||
else
|
||||
squeak_loud(0)//You trod on its tail
|
||||
|
||||
|
||||
if(!health)
|
||||
return
|
||||
|
||||
@@ -283,7 +291,6 @@
|
||||
icon_rest = "mouse_brown_sleep"
|
||||
holder_type = /obj/item/weapon/holder/mouse/brown
|
||||
|
||||
//TOM IS ALIVE! SQUEEEEEEEE~K :)
|
||||
/mob/living/simple_animal/mouse/brown/Tom
|
||||
name = "Tom"
|
||||
real_name = "Tom"
|
||||
|
||||
+53
-113
@@ -1002,134 +1002,74 @@ proc/is_blind(A)
|
||||
//Below here is stuff related to devouring, but which is generally helpful and thus placed here
|
||||
//See Devour.dm for more info in how these are used
|
||||
|
||||
|
||||
|
||||
//Blacklists of mobs that can be excluded from eating by flags in the bitfield
|
||||
|
||||
//All of these specific human subtypes are here for a reason.
|
||||
//Using /mob/living/carbon/human as a generic type would include monkey/stok/farwa/neara.
|
||||
//We do not want those to count as humanoids, only player species
|
||||
var/list/humanoid_mobs_specific = list( /mob/living/carbon/human,
|
||||
/mob/living/carbon/human/bst,
|
||||
/mob/living/carbon/human/skrell,
|
||||
/mob/living/carbon/human/unathi,
|
||||
/mob/living/carbon/human/diona,
|
||||
/mob/living/carbon/human/tajaran,
|
||||
/mob/living/carbon/human/vox,
|
||||
/mob/living/carbon/human/machine,
|
||||
/mob/living/carbon/human/type_a,
|
||||
/mob/living/carbon/human/type_b
|
||||
)
|
||||
|
||||
var/list/humanoid_mobs_inclusive = list(
|
||||
/mob/living/simple_animal/hostile/pirate,
|
||||
/mob/living/simple_animal/hostile/russian,
|
||||
/mob/living/simple_animal/hostile/syndicate
|
||||
)
|
||||
|
||||
var/list/synthetic_mobs_specific = list(
|
||||
/mob/living/carbon/human/machine,
|
||||
/mob/living/simple_animal/hostile/retaliate/malf_drone,
|
||||
/mob/living/simple_animal/hostile/viscerator,
|
||||
/mob/living/simple_animal/spiderbot
|
||||
)
|
||||
|
||||
|
||||
var/list/synthetic_mobs_inclusive = list( /mob/living/silicon,
|
||||
/mob/living/simple_animal/hostile/hivebot,
|
||||
/mob/living/bot
|
||||
)
|
||||
|
||||
var/list/wierd_mobs_specific = list(/mob/living/simple_animal/adultslime)
|
||||
|
||||
var/list/wierd_mobs_inclusive = list( /mob/living/simple_animal/construct,
|
||||
/mob/living/simple_animal/shade,
|
||||
/mob/living/simple_animal/slime,
|
||||
/mob/living/simple_animal/hostile/faithless,
|
||||
/mob/living/carbon/slime
|
||||
)
|
||||
|
||||
|
||||
// Returns a bitfield representing the mob's type as relevant to the devour system.
|
||||
/mob/proc/find_type()
|
||||
if (istype(src, /mob/living))
|
||||
var/mob/living/L = src
|
||||
return L.find_type()
|
||||
return 0
|
||||
|
||||
/mob/living/find_type()
|
||||
//This function returns a bitfield indicating what type(s) the passed mob is.
|
||||
//Synthetic and wierd are exclusive from organic. We assume it's organic if it's not either of those
|
||||
//var/mob/living/test = src
|
||||
var/mobtypes = 0
|
||||
/mob/living/carbon/human/find_type()
|
||||
. = ..()
|
||||
. |= isSynthetic() ? TYPE_SYNTHETIC : TYPE_ORGANIC
|
||||
if (!islesserform(src))
|
||||
. |= TYPE_HUMANOID
|
||||
|
||||
if (mob_listed(src, synthetic_mobs_specific,1))
|
||||
mobtypes |= TYPE_SYNTHETIC
|
||||
else if (mob_listed(src, synthetic_mobs_inclusive,0))
|
||||
mobtypes |= TYPE_SYNTHETIC
|
||||
else
|
||||
if (isSynthetic())
|
||||
mobtypes |= TYPE_SYNTHETIC
|
||||
/mob/living/carbon/slime/find_type()
|
||||
. = ..()
|
||||
. |= TYPE_WEIRD
|
||||
|
||||
if (mob_listed(src, wierd_mobs_specific,1))
|
||||
mobtypes |= TYPE_WIERD
|
||||
else if (mob_listed(src, wierd_mobs_inclusive,0))
|
||||
mobtypes |= TYPE_WIERD
|
||||
/mob/living/bot/find_type()
|
||||
. = ..()
|
||||
. |= TYPE_SYNTHETIC
|
||||
|
||||
if (!(mobtypes & TYPE_WIERD) && !(mobtypes & TYPE_SYNTHETIC))
|
||||
mobtypes |= TYPE_ORGANIC
|
||||
// Yeah, I'm just going to cheat and do istype(src) checks here.
|
||||
// It's not worth adding a proc for every single one of these types.
|
||||
/mob/living/simple_animal/find_type()
|
||||
. = ..()
|
||||
if (is_type_in_typecache(src, global.mtl_synthetic))
|
||||
. |= TYPE_SYNTHETIC
|
||||
|
||||
if (is_type_in_typecache(src, global.mtl_weird))
|
||||
. |= TYPE_WEIRD
|
||||
|
||||
if (mob_listed(src, humanoid_mobs_specific,1))
|
||||
mobtypes |= TYPE_HUMANOID
|
||||
else if (mob_listed(src, humanoid_mobs_inclusive,0))
|
||||
mobtypes |= TYPE_HUMANOID
|
||||
// If it's not TYPE_SYNTHETIC or TYPE_WEIRD, we can assume it's TYPE_ORGANIC.
|
||||
if (!(. & (TYPE_SYNTHETIC|TYPE_WEIRD)))
|
||||
. |= TYPE_ORGANIC
|
||||
|
||||
return mobtypes
|
||||
if (is_type_in_typecache(src, global.mtl_humanoid))
|
||||
. |= TYPE_HUMANOID
|
||||
|
||||
/mob/living/proc/get_vessel(create = FALSE)
|
||||
if (!create)
|
||||
return
|
||||
|
||||
//This function attempts to find the mob's blood vessel, if it has one.
|
||||
//If it doesn't, and the create var is true, then it will create a new temporary one filled with blood that has fake DNA, and return that
|
||||
//If no vessel and no create var, then null is returned, getting blood isnt possible.
|
||||
//The fake DNA is generally useful for animals, it contains enough information to tell what kind of creature it came from
|
||||
/mob/living/proc/get_vessel(var/create = 0)
|
||||
//Add any other creatures which have blood, here
|
||||
if(istype(src, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = src
|
||||
return H.vessel
|
||||
else if (istype(src, /mob/living/carbon/alien/diona))
|
||||
var/mob/living/carbon/alien/diona/D = src
|
||||
return D.vessel
|
||||
else if (create)
|
||||
//we make a new vessel for whatever creature we're devouring. this allows blood to come from creatures that can't normally bleed
|
||||
//We create an MD5 hash of the mob's reference to use as its DNA string.
|
||||
//This creates unique DNA for each creature in a consistently repeatable process
|
||||
var/datum/reagents/vessel = new/datum/reagents(600)
|
||||
vessel.add_reagent("blood",560)
|
||||
for(var/datum/reagent/blood/B in vessel.reagent_list)
|
||||
if(B.id == "blood")
|
||||
B.data = list(
|
||||
"donor" = src,
|
||||
"viruses" = null,
|
||||
"species" = name,
|
||||
"blood_DNA" = md5("\ref[src]"),
|
||||
"blood_colour" = "#a10808",
|
||||
"blood_type" = null,
|
||||
"resistances" = null,
|
||||
"trace_chem" = null,
|
||||
"virus2" = null,
|
||||
"antibodies" = list()
|
||||
)
|
||||
|
||||
//we make a new vessel for whatever creature we're devouring. this allows blood to come from creatures that can't normally bleed
|
||||
//We create an MD5 hash of the mob's reference to use as its DNA string.
|
||||
//This creates unique DNA for each creature in a consistently repeatable process
|
||||
var/datum/reagents/vessel = new/datum/reagents(600)
|
||||
vessel.add_reagent("blood",560)
|
||||
for(var/datum/reagent/blood/B in vessel.reagent_list)
|
||||
if(B.id == "blood")
|
||||
B.data = list( "donor"=src,"viruses"=null,"species"=src.name,"blood_DNA"=md5("\ref[src]"),"blood_colour"= "#a10808","blood_type"=null, \
|
||||
"resistances"=null,"trace_chem"=null, "virus2" = null, "antibodies" = list())
|
||||
B.color = B.data["blood_colour"]
|
||||
|
||||
B.color = B.data["blood_colour"]
|
||||
return vessel
|
||||
|
||||
return vessel
|
||||
|
||||
else return null
|
||||
|
||||
//This function checks against a list to see if the mob is in it.
|
||||
//Any specified types are checked against exactly, using ==, not istype
|
||||
//Any types ending in * will be tested with isType
|
||||
/proc/mob_listed(var/mob/living/test, var/list/toCheck, var/specific = 0)
|
||||
for (var/i in toCheck)
|
||||
if (specific)
|
||||
if (test.type == i)
|
||||
return 1
|
||||
else
|
||||
if (istype(test, i))
|
||||
return 1
|
||||
return 0
|
||||
/mob/living/carbon/human/get_vessel(create = FALSE)
|
||||
. = vessel
|
||||
|
||||
/mob/living/carbon/alien/diona/get_vessel(create = FALSE)
|
||||
. = vessel
|
||||
|
||||
#define POSESSIVE_PRONOUN 0
|
||||
#define POSESSIVE_ADJECTIVE 1
|
||||
|
||||
+1
-1
@@ -258,7 +258,7 @@ var/list/world_api_rate_limit = list()
|
||||
config.load("config/config.txt")
|
||||
config.load("config/game_options.txt","game_options")
|
||||
|
||||
if (config.use_age_restriction_for_jobs || config.use_age_restriction_for_antags)
|
||||
if (config.age_restrictions_from_file)
|
||||
config.load("config/age_restrictions.txt", "age_restrictions")
|
||||
|
||||
/hook/startup/proc/loadMods()
|
||||
|
||||
@@ -29,6 +29,9 @@ JOBS_HAVE_MINIMAL_ACCESS
|
||||
## Non-automatic antagonist recruitment, such as being converted to cultism is not affected. Has the same database requirements and notes as USE_AGE_RESTRICTION_FOR_JOBS.
|
||||
#USE_AGE_RESTRICTION_FOR_ANTAGS
|
||||
|
||||
## Unhash to enable loading of age restrictions from age_restrictions.txt.
|
||||
#LOAD_AGE_RESTRICTIONS_FROM_FILE
|
||||
|
||||
## Unhash this to use recursive explosions, keep it hashed to use circle explosions. Recursive explosions react to walls, airlocks and blast doors, making them look a lot cooler than the boring old circular explosions. They require more CPU and are (as of january 2013) experimental
|
||||
#USE_RECURSIVE_EXPLOSIONS
|
||||
|
||||
@@ -114,12 +117,18 @@ PROBABILITY S MERCENARY 1
|
||||
PROBABILITY S WIZARD 1
|
||||
PROBABILITY S CHANGELING 1
|
||||
PROBABILITY S CULT 1
|
||||
PROBABILITY S NINJA 1
|
||||
PROBABILITY S HEIST 1
|
||||
PROBABILITY S VAMPIRE 1
|
||||
PROBABILITY S EXTEND-A-TRAITORMONGOUS 6
|
||||
PROBABILITY MS CONFLUX 1
|
||||
PROBABILITY MS CROSSFIRE 1
|
||||
PROBABILITY MS PARANOIA 1
|
||||
PROBABILITY MS UPRISING 1
|
||||
PROBABILITY MS VISITORS 1
|
||||
PROBABILITY MS INTRIGUE 1
|
||||
PROBABILITY MS SIEGE 1
|
||||
PROBABILITY MS TRAITORLING 1
|
||||
PROBABILITY MS EXTENDED 1
|
||||
|
||||
## Hash out to disable random events during the round.
|
||||
|
||||
@@ -56,6 +56,12 @@
|
||||
-->
|
||||
<div class="commit sansserif">
|
||||
|
||||
<h2 class="date">05 August 2017</h2>
|
||||
<h3 class="author">Alberyk updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Changed the uprising gamemode to be revolution and traitor, instead of revolution and cult.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">04 August 2017</h2>
|
||||
<h3 class="author">Lohikar updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
|
||||
@@ -4516,3 +4516,7 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
|
||||
Lohikar:
|
||||
- maptweak: Elevators now use small lights instead of tube lights.
|
||||
- tweak: Lights will no longer mysteriously float in mid-air in elevator shafts.
|
||||
2017-08-05:
|
||||
Alberyk:
|
||||
- tweak: Changed the uprising gamemode to be revolution and traitor, instead of
|
||||
revolution and cult.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Reference in New Issue
Block a user