mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-15 00:53:23 +01:00
Ape Uprising (#31609)
* Allow monkey-like species to craft * Add signal for mobs entering vents * Implement basic uplifted antag datum & nest * Make phrasing nicer * Allow primitive species to vary & add time requirements * Add spawning functionality to nest * Make primitives unable to be humanised a little less violently * Fix linter complaints * Fix typo which made the linter mad * Add objectives and antag teams * Make nests consider other nests for spawn limit * Add greeting text * Add guaranteed early spawns * Allow deconstruction of nests & recovery of scrap * Allow uplifted mobs to ventcrawl with small items * Clarify nest spawning conditions on examine * Tweak NPC numbers & AI * Add obtain objective and give an extra objective * Give thanks to the linter * Change team objective & make the alert nicer * Make event only spawn monkeys by default * Add examine text explaining deconstruction * Allow ghosts to see nest materials * Handle stacks properly in nest deconstruction * Add on-demand ghost spawn to reduce roll spam * Add nest crafting * Allow lesser mobs to use medical stacks I don't believe this should affect anything else, as every other mob capable of holding these items is an advanced tool user. * Add hint about crafting on examine * Ensure only nest monkeys retaliate to nest damage * Add uplifted primitive nests to the spawners menu
This commit is contained in:
@@ -485,6 +485,11 @@
|
||||
if(length(SSticker.mode.zombie_infected))
|
||||
dat += check_role_table_mob("Pre-zombie infected", SSticker.mode.zombie_infected)
|
||||
|
||||
if(length(SSticker.mode.uplifted_primitives))
|
||||
for(var/datum/species/species_path in SSticker.mode.uplifted_primitives)
|
||||
var/minds = SSticker.mode.uplifted_primitives[species_path]
|
||||
dat += check_role_table("Uplifted Primitives ([species_path::name])", minds)
|
||||
|
||||
if(length(GLOB.ts_spiderlist))
|
||||
var/list/spider_minds = list()
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/S in GLOB.ts_spiderlist)
|
||||
|
||||
@@ -26,6 +26,18 @@
|
||||
if(M.mind)
|
||||
M.mind.antag_hud = null
|
||||
|
||||
/datum/atom_hud/antag/hidden/secondary/join_hud(mob/M, slave)
|
||||
if(!istype(M))
|
||||
CRASH("join_hud(): [M] ([M.type]) is not a mob!")
|
||||
add_to_hud(M)
|
||||
if(self_visible)
|
||||
add_hud_to(M)
|
||||
|
||||
/datum/atom_hud/antag/hidden/secondary/leave_hud(mob/M)
|
||||
if(!istype(M))
|
||||
CRASH("leave_hud(): [M] ([M.type]) is not a mob!")
|
||||
remove_from_hud(M)
|
||||
remove_hud_from(M)
|
||||
|
||||
//GAME_MODE PROCS
|
||||
//called to set a mob's antag icon state
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
RESTRICT_TYPE(/datum/antagonist/uplifted_primitive)
|
||||
|
||||
/datum/antagonist/uplifted_primitive
|
||||
name = "Uplifted Primitive"
|
||||
job_rank = ROLE_UPLIFTED_PRIMITIVE
|
||||
special_role = SPECIAL_ROLE_UPLIFTED_PRIMITIVE
|
||||
antag_hud_name = "huduplifted"
|
||||
antag_hud_type = ANTAG_HUD_UPLIFTED_TEAMLESS
|
||||
// TODO: wiki page
|
||||
//wiki_page_name = "Uplifted_Primitive"
|
||||
|
||||
/// The UID of the nest built by the owner.
|
||||
var/nest_uid
|
||||
|
||||
/// The species of the owner at the time this datum was added.
|
||||
var/datum/species/initial_species
|
||||
|
||||
/// The list of objective types which can be selected from when picking a personal objective.
|
||||
var/list/potential_objectives = list(
|
||||
/datum/objective/uplifted/collect_items,
|
||||
/datum/objective/uplifted/collect_animals,
|
||||
/datum/objective/uplifted/barter,
|
||||
/datum/objective/uplifted/fortify,
|
||||
/datum/objective/uplifted/obtain,
|
||||
)
|
||||
|
||||
/datum/antagonist/uplifted_primitive/greet()
|
||||
. = ..()
|
||||
. += SPAN_BOLDNOTICE("Despite your primitive form, you have enlightened with sentience.")
|
||||
. += SPAN_BOLDNOTICE("With this newfound awareness you are able to spread your species by building a nest and supplying it with food and scrap metal.")
|
||||
. += SPAN_BOLDNOTICE("By propagating your kind and working with your fellow primitives, you may finally be able to defend yourself from the crew of the station.")
|
||||
. += SPAN_BOLDNOTICE("Alternatively, you could try to keep a friendly relationship with the crew, though they may see you as a threat not worth keeping alive.")
|
||||
. += SPAN_BOLDNOTICE("Regardless of the method, you must help your species to survive and prosper on the station.")
|
||||
|
||||
/datum/antagonist/uplifted_primitive/give_objectives()
|
||||
add_antag_objective(pick_n_take(potential_objectives))
|
||||
add_antag_objective(pick_n_take(potential_objectives))
|
||||
|
||||
/datum/antagonist/uplifted_primitive/apply_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/carbon/human/H = ..()
|
||||
if(!istype(H))
|
||||
return
|
||||
|
||||
if(H.dna.species.is_small)
|
||||
ADD_TRAIT(H, TRAIT_GENELESS, UNIQUE_TRAIT_SOURCE(src))
|
||||
|
||||
H.ventcrawler = VENTCRAWLER_SIGNAL
|
||||
RegisterSignal(H, COMSIG_LIVING_TRY_VENTCRAWL, PROC_REF(attempt_ventcrawl))
|
||||
RegisterSignal(H, COMSIG_LIVING_ENTER_VENTCRAWL, PROC_REF(apply_ventcrawl_effects))
|
||||
RegisterSignal(H, COMSIG_LIVING_EXIT_VENTCRAWL, PROC_REF(remove_ventcrawl_effects))
|
||||
|
||||
owner.AddSpell(new /datum/spell/uplifted_make_nest)
|
||||
|
||||
/datum/antagonist/uplifted_primitive/remove_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/carbon/human/H = ..()
|
||||
if(!istype(H))
|
||||
return
|
||||
|
||||
REMOVE_TRAIT(H, TRAIT_GENELESS, UNIQUE_TRAIT_SOURCE(src))
|
||||
|
||||
H.ventcrawler = initial(H.ventcrawler)
|
||||
UnregisterSignal(H, COMSIG_LIVING_TRY_VENTCRAWL)
|
||||
UnregisterSignal(H, COMSIG_LIVING_ENTER_VENTCRAWL)
|
||||
UnregisterSignal(H, COMSIG_LIVING_EXIT_VENTCRAWL)
|
||||
|
||||
owner.RemoveSpell(/datum/spell/uplifted_make_nest)
|
||||
|
||||
/datum/antagonist/uplifted_primitive/proc/attempt_ventcrawl()
|
||||
SIGNAL_HANDLER
|
||||
var/mob/living/L = owner.current
|
||||
|
||||
for(var/obj/item/I in L.contents)
|
||||
if(istype(I, /obj/item/bio_chip))
|
||||
continue
|
||||
if(istype(I, /obj/item/reagent_containers/patch))
|
||||
continue
|
||||
if(I.flags & ABSTRACT)
|
||||
continue
|
||||
if(I.w_class > WEIGHT_CLASS_NORMAL)
|
||||
to_chat(L, SPAN_WARNING("You cannot crawl into a vent with large items!"))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/uplifted_primitive/proc/apply_ventcrawl_effects()
|
||||
SIGNAL_HANDLER
|
||||
var/mob/living/L = owner.current
|
||||
ADD_TRAIT(L, TRAIT_RESISTLOWPRESSURE, UNIQUE_TRAIT_SOURCE(src))
|
||||
ADD_TRAIT(L, TRAIT_RESISTHIGHPRESSURE, UNIQUE_TRAIT_SOURCE(src))
|
||||
|
||||
/datum/antagonist/uplifted_primitive/proc/remove_ventcrawl_effects()
|
||||
SIGNAL_HANDLER
|
||||
var/mob/living/L = owner.current
|
||||
REMOVE_TRAIT(L, TRAIT_RESISTLOWPRESSURE, UNIQUE_TRAIT_SOURCE(src))
|
||||
REMOVE_TRAIT(L, TRAIT_RESISTHIGHPRESSURE, UNIQUE_TRAIT_SOURCE(src))
|
||||
|
||||
/datum/antagonist/uplifted_primitive/add_antag_hud(mob/living/antag_mob)
|
||||
var/datum/team/uplifted_primitive/team = get_team()
|
||||
var/datum/atom_hud/antag/global_hud = GLOB.huds[antag_hud_type]
|
||||
|
||||
global_hud.join_hud(antag_mob)
|
||||
if(team)
|
||||
team.team_hud.join_hud(antag_mob)
|
||||
|
||||
set_antag_hud(antag_mob, antag_hud_name)
|
||||
|
||||
/datum/antagonist/uplifted_primitive/remove_antag_hud(mob/living/antag_mob)
|
||||
var/datum/team/uplifted_primitive/team = get_team()
|
||||
var/datum/atom_hud/antag/global_hud = GLOB.huds[antag_hud_type]
|
||||
|
||||
global_hud.leave_hud(antag_mob)
|
||||
if(team)
|
||||
team.team_hud.leave_hud(antag_mob)
|
||||
|
||||
set_antag_hud(antag_mob, null)
|
||||
|
||||
/datum/antagonist/uplifted_primitive/create_team(datum/team/team)
|
||||
var/datum/species/owner_species = get_owner_species()
|
||||
if(!owner_species)
|
||||
return null
|
||||
|
||||
var/datum/team/uplifted_primitive/existing = SSticker.mode.uplifted_teams[owner_species]
|
||||
if(!existing)
|
||||
existing = new /datum/team/uplifted_primitive(new_species = owner_species)
|
||||
return existing
|
||||
|
||||
/datum/antagonist/uplifted_primitive/get_team()
|
||||
var/datum/species/owner_species = get_owner_species()
|
||||
if(!owner_species)
|
||||
return null
|
||||
|
||||
return SSticker.mode.uplifted_teams[owner_species]
|
||||
|
||||
/datum/antagonist/uplifted_primitive/add_owner_to_gamemode()
|
||||
var/datum/species/owner_species = get_owner_species()
|
||||
|
||||
var/list/minds = SSticker.mode.uplifted_primitives[owner_species]
|
||||
if(!minds)
|
||||
minds = list()
|
||||
SSticker.mode.uplifted_primitives[owner_species] = minds
|
||||
minds |= owner
|
||||
|
||||
/datum/antagonist/uplifted_primitive/remove_owner_from_gamemode()
|
||||
var/datum/species/owner_species = get_owner_species()
|
||||
|
||||
var/list/minds = SSticker.mode.uplifted_primitives[owner_species]
|
||||
if(minds)
|
||||
minds -= owner
|
||||
if(!length(minds))
|
||||
SSticker.mode.uplifted_primitives[owner_species] = null
|
||||
SSticker.mode.uplifted_primitives -= owner_species
|
||||
|
||||
/datum/antagonist/uplifted_primitive/proc/get_owner_species()
|
||||
if(initial_species == null)
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(istype(H))
|
||||
initial_species = H.dna.species.type
|
||||
else
|
||||
initial_species = FALSE
|
||||
return initial_species
|
||||
@@ -0,0 +1,77 @@
|
||||
RESTRICT_TYPE(/datum/team/uplifted_primitive)
|
||||
|
||||
/// The number of players a team must have before receiving their team objective.
|
||||
#define TEAM_OBJECTIVE_MEMBER_THRESHOLD 3
|
||||
|
||||
/// An team containing all uplifted primitives of a given species.
|
||||
/datum/team/uplifted_primitive
|
||||
name = "Uplifted Primitives"
|
||||
|
||||
/// The species this team represents.
|
||||
var/datum/species/team_species
|
||||
/// The antag hud specific to this team, only shown to other members of the team.
|
||||
var/datum/atom_hud/antag/team_hud = new()
|
||||
|
||||
/// Whether or not the team objective has been added yet.
|
||||
var/has_added_team_objective = FALSE
|
||||
|
||||
/// All potential objectives which can be added as the team objective.
|
||||
var/list/potential_objectives = list(
|
||||
/datum/objective/uplifted/expand,
|
||||
)
|
||||
|
||||
/// The number of spawns that should always poll ghosts for nests of this team.
|
||||
var/guaranteed_sentient_spawns = 0
|
||||
|
||||
/datum/team/uplifted_primitive/New(list/starting_members, datum/species/new_species = /datum/species/monkey)
|
||||
team_species = new_species
|
||||
return ..(starting_members)
|
||||
|
||||
/datum/team/uplifted_primitive/create_team(list/starting_members)
|
||||
. = ..()
|
||||
name = "[team_species::name] Uprising"
|
||||
|
||||
add_team_objective(/datum/objective/uplifted/propagate)
|
||||
add_team_objective(/datum/objective/uplifted/build_nest_in_area)
|
||||
|
||||
/datum/team/uplifted_primitive/can_create_team()
|
||||
return SSticker.mode.uplifted_teams[team_species] == null
|
||||
|
||||
/datum/team/uplifted_primitive/assign_team(list/starting_members)
|
||||
SSticker.mode.uplifted_teams[team_species] = src
|
||||
|
||||
/datum/team/uplifted_primitive/clear_team_reference()
|
||||
SSticker.mode.uplifted_teams[team_species] = null
|
||||
SSticker.mode.uplifted_teams -= team_species
|
||||
|
||||
/datum/team/uplifted_primitive/handle_adding_member(datum/mind/new_member)
|
||||
..()
|
||||
|
||||
if(!has_added_team_objective && length(members) >= TEAM_OBJECTIVE_MEMBER_THRESHOLD)
|
||||
has_added_team_objective = TRUE
|
||||
addtimer(CALLBACK(src, PROC_REF(add_new_objective)), 10 SECONDS)
|
||||
|
||||
/datum/team/uplifted_primitive/proc/add_new_objective()
|
||||
var/selected_objective_path = pick_n_take(potential_objectives)
|
||||
var/datum/objective/new_objective = new selected_objective_path()
|
||||
add_team_objective(new_objective)
|
||||
announce_new_objective(members, new_objective)
|
||||
|
||||
/datum/team/uplifted_primitive/proc/announce_new_objective(list/announce_to, datum/objective/new_objective)
|
||||
var/message = prepare_new_objective_message(new_objective)
|
||||
for(var/datum/mind/member in announce_to)
|
||||
if(!member.current || !isliving(member.current))
|
||||
continue
|
||||
to_chat(member.current, message)
|
||||
SEND_SOUND(member.current, sound('sound/ambience/alarm4.ogg'))
|
||||
|
||||
/datum/team/uplifted_primitive/proc/prepare_new_objective_message(datum/objective/new_objective)
|
||||
var/list/messages = list()
|
||||
|
||||
messages += SPAN_USERDANGER("Your species grows!")
|
||||
messages += SPAN_NOTICE("With your numbers rising, you devise a new objective:")
|
||||
messages += new_objective.explanation_text
|
||||
|
||||
return chat_box_red(messages.Join("<br>"))
|
||||
|
||||
#undef TEAM_OBJECTIVE_MEMBER_THRESHOLD
|
||||
@@ -12,6 +12,7 @@ GLOBAL_LIST_INIT(special_role_times, list(
|
||||
ROLE_VAMPIRE = 14,
|
||||
ROLE_BLOB = 14,
|
||||
ROLE_REVENANT = 14,
|
||||
ROLE_UPLIFTED_PRIMITIVE = 14,
|
||||
ROLE_OPERATIVE = 21,
|
||||
ROLE_CULTIST = 21,
|
||||
ROLE_ALIEN = 21,
|
||||
|
||||
@@ -222,6 +222,7 @@ GLOBAL_LIST_EMPTY(event_last_fired)
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/space_ninja, 9),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/wizard_adept, 5),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/spawn_morph, 16, is_one_shot = TRUE),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/spawn_uplifted_primitive, 16, is_one_shot = TRUE),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/aurora_caelus, 5, is_one_shot = TRUE),
|
||||
//new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/spawn_pulsedemon, 20, is_one_shot = TRUE)
|
||||
)
|
||||
|
||||
@@ -580,7 +580,10 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
|
||||
to_chat(src, SPAN_WARNING("You cannot crawl into a vent while buckled to something!"))
|
||||
return
|
||||
|
||||
if(iscarbon(src) && length(contents) && ventcrawlerlocal < VENTCRAWLER_ALWAYS) // If we're here you can only ventcrawl while completely nude
|
||||
if(ventcrawlerlocal == VENTCRAWLER_SIGNAL && !SEND_SIGNAL(src, COMSIG_LIVING_TRY_VENTCRAWL))
|
||||
return
|
||||
|
||||
if(ventcrawlerlocal == VENTCRAWLER_NUDE && iscarbon(src) && length(contents)) // If we're here you can only ventcrawl while completely nude
|
||||
for(var/obj/item/I in contents)
|
||||
if(istype(I, /obj/item/bio_chip))
|
||||
continue
|
||||
@@ -602,7 +605,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
|
||||
var/datum/pipeline/pipenet = starting_machine.returnPipenet(target_move)
|
||||
pipenet.add_ventcrawler(src)
|
||||
add_ventcrawl_images(pipenet)
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_ENTER_VENTCRAWL)
|
||||
|
||||
/mob/living/proc/add_ventcrawl_images(datum/pipeline/pipenet)
|
||||
var/list/totalMembers = list()
|
||||
|
||||
@@ -96,7 +96,6 @@
|
||||
var/meat_type = /obj/item/food/meat
|
||||
var/no_equip // bitflags of slots the race can't equip stuff to
|
||||
var/nojumpsuit = 0 // this is sorta... weird. it basically lets you equip stuff that usually needs jumpsuits without one, like belts and pockets and ids
|
||||
var/can_craft = TRUE // Can this mob using crafting or not?
|
||||
|
||||
var/bodyflags = 0
|
||||
var/dietflags = 0 // Make sure you set this, otherwise it won't be able to digest a lot of foods
|
||||
@@ -971,7 +970,7 @@
|
||||
if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB))
|
||||
H.vomit(10, TRUE)
|
||||
|
||||
if(radiation > RAD_MOB_MUTATE)
|
||||
if(radiation > RAD_MOB_MUTATE && !HAS_TRAIT(H, TRAIT_GENELESS))
|
||||
if(prob(1))
|
||||
to_chat(H, SPAN_DANGER("You mutate!"))
|
||||
randmutb(H)
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
greater_form = /datum/species/human
|
||||
no_equip = ITEM_SLOT_BELT | ITEM_SLOT_ID | ITEM_SLOT_LEFT_EAR | ITEM_SLOT_RIGHT_EAR | ITEM_SLOT_EYES | ITEM_SLOT_GLOVES | ITEM_SLOT_SHOES | ITEM_SLOT_OUTER_SUIT | ITEM_SLOT_JUMPSUIT | ITEM_SLOT_LEFT_POCKET | ITEM_SLOT_RIGHT_POCKET | ITEM_SLOT_SUIT_STORE | ITEM_SLOT_PDA | ITEM_SLOT_NECK
|
||||
inherent_factions = list("jungle", "monkey")
|
||||
can_craft = FALSE
|
||||
is_small = 1
|
||||
has_fine_manipulation = 0
|
||||
ventcrawler = VENTCRAWLER_NUDE
|
||||
|
||||
Reference in New Issue
Block a user