mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
Basic Mob Gorillas (#78918)
## About The Pull Request Now we can make basic mobs with hands easily so I did, they don't actually use their hands for anything with AI. In the future we can come back and share the monkey AI where they pick up items to hit people with, but frankly few weapons are more deadly than a gorilla's fists. IIRC I didn't really change their behaviour much, this is mostly just a straight conversion. Main difference is that they will prioritise eating nearby bananas and fruit salads over punching people. When I make these conversions nowadays I need to decide between "does this attack at the speed that it did as an NPC mob or the speed it did as a player?" I am arbitrarily deciding that gorillas are usually not players and electing for the former, but tell me if you disagree. I also made "show basic inhand sprites" into a component shared by Gorillas, Drones, and Dextrous Guardians (all also now available to become basic, once I get around to it), And I added an AI behaviour to run a basic emote. This is similar but different to "random speech", which kind of sucks and needs rewriting anyway. Gorillas don't speak, only ooga. ## Why It's Good For The Game https://www.youtube.com/watch?v=npuuTBlEb1U ## Changelog 🆑 refactor: Gorillas now use the basic mob framework. Please report any unusual side effects. /🆑
This commit is contained in:
@@ -11,6 +11,11 @@
|
||||
///How close a mob must be for us to select it as a target, if that is less than how far we can maintain it as a target
|
||||
#define BB_AGGRO_RANGE "BB_aggro_range"
|
||||
|
||||
/// Store a single or list of emotes at this key
|
||||
#define BB_EMOTE_KEY "BB_emotes"
|
||||
/// Chance to perform an emote per second
|
||||
#define BB_EMOTE_CHANCE "BB_EMOTE_CHANCE"
|
||||
|
||||
///Turf we want a mob to move to
|
||||
#define BB_TRAVEL_DESTINATION "BB_travel_destination"
|
||||
|
||||
@@ -105,4 +110,4 @@
|
||||
#define BB_EMOTE_HEAR "emote_hear"
|
||||
#define BB_EMOTE_SEE "emote_see"
|
||||
#define BB_EMOTE_SOUND "emote_sound"
|
||||
#define BB_EMOTE_CHANCE "emote_chance"
|
||||
#define BB_SPEAK_CHANCE "emote_chance"
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
/// From base of /mob/living/simple_animal/bot/proc/bot_step()
|
||||
#define COMSIG_MOB_BOT_STEP "mob_bot_step"
|
||||
|
||||
/// From base of /mob/proc/update_held_items
|
||||
#define COMSIG_MOB_UPDATE_HELD_ITEMS "mob_update_held_items"
|
||||
|
||||
/// From base of /client/Move(): (list/move_args)
|
||||
#define COMSIG_MOB_CLIENT_PRE_LIVING_MOVE "mob_client_pre_living_move"
|
||||
/// Should we stop the current living movement attempt
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
/// If drones are blacklisted from certain sensitive machines
|
||||
GLOBAL_VAR_INIT(drone_machine_blacklist_enabled, FALSE)
|
||||
|
||||
#define DRONE_HANDS_LAYER 1
|
||||
#define DRONE_HEAD_LAYER 2
|
||||
#define DRONE_TOTAL_LAYERS 2
|
||||
#define DRONE_HEAD_LAYER 1
|
||||
#define DRONE_TOTAL_LAYERS 1
|
||||
|
||||
/// Message displayed when new drone spawns in drone network
|
||||
#define DRONE_NET_CONNECT span_notice("DRONE NETWORK: [name] connected.")
|
||||
|
||||
@@ -3,6 +3,5 @@
|
||||
#define GUARDIAN_THEME_CARP "carp"
|
||||
#define GUARDIAN_THEME_MINER "miner"
|
||||
|
||||
#define GUARDIAN_COLOR_LAYER 2
|
||||
#define GUARDIAN_HANDS_LAYER 1
|
||||
#define GUARDIAN_TOTAL_LAYERS 2
|
||||
#define GUARDIAN_COLOR_LAYER 1
|
||||
#define GUARDIAN_TOTAL_LAYERS 1
|
||||
|
||||
33
code/datums/ai/basic_mobs/basic_subtrees/run_emote.dm
Normal file
33
code/datums/ai/basic_mobs/basic_subtrees/run_emote.dm
Normal file
@@ -0,0 +1,33 @@
|
||||
/// Intermittently run an emote
|
||||
/datum/ai_planning_subtree/run_emote
|
||||
var/emote_key = BB_EMOTE_KEY
|
||||
var/emote_chance_key = BB_EMOTE_CHANCE
|
||||
|
||||
/datum/ai_planning_subtree/run_emote/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
|
||||
var/emote_chance = controller.blackboard[emote_chance_key] || 0
|
||||
if (!SPT_PROB(emote_chance, seconds_per_tick))
|
||||
return
|
||||
controller.queue_behavior(/datum/ai_behavior/run_emote, emote_key)
|
||||
|
||||
/// Emote from a blackboard key
|
||||
/datum/ai_behavior/run_emote
|
||||
|
||||
/datum/ai_behavior/run_emote/perform(seconds_per_tick, datum/ai_controller/controller, emote_key)
|
||||
var/mob/living/living_pawn = controller.pawn
|
||||
if (!isliving(living_pawn))
|
||||
finish_action(controller, FALSE)
|
||||
return
|
||||
|
||||
var/list/emote_list = controller.blackboard[emote_key]
|
||||
var/emote
|
||||
if (islist(emote_list))
|
||||
emote = length(emote_list) ? pick(emote_list) : null
|
||||
else
|
||||
emote = emote_list
|
||||
|
||||
if(isnull(emote))
|
||||
finish_action(controller, FALSE)
|
||||
return
|
||||
|
||||
living_pawn.emote(emote)
|
||||
finish_action(controller, TRUE)
|
||||
@@ -228,6 +228,6 @@
|
||||
emote_see = speech_lines[BB_EMOTE_SEE] || list()
|
||||
emote_hear = speech_lines[BB_EMOTE_HEAR] || list()
|
||||
sound = speech_lines[BB_EMOTE_SOUND] || list()
|
||||
speech_chance = speech_lines[BB_EMOTE_CHANCE] ? speech_lines[BB_EMOTE_CHANCE] : initial(speech_chance)
|
||||
speech_chance = speech_lines[BB_SPEAK_CHANCE] ? speech_lines[BB_SPEAK_CHANCE] : initial(speech_chance)
|
||||
|
||||
return ..()
|
||||
|
||||
50
code/datums/components/basic_inhands.dm
Normal file
50
code/datums/components/basic_inhands.dm
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Basic handling for showing held items in a mob's hands
|
||||
*/
|
||||
/datum/component/basic_inhands
|
||||
/// Layer index we show our inhands upon
|
||||
var/display_layer
|
||||
/// Y offset to apply to inhands
|
||||
var/y_offset
|
||||
/// X offset to apply to inhands, is inverted for the left hand
|
||||
var/x_offset
|
||||
/// What overlays are we currently showing?
|
||||
var/list/cached_overlays
|
||||
|
||||
/datum/component/basic_inhands/Initialize(display_layer = 1, y_offset = 0, x_offset = 0)
|
||||
. = ..()
|
||||
if (!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
src.display_layer = display_layer
|
||||
src.y_offset = y_offset
|
||||
src.x_offset = x_offset
|
||||
cached_overlays = list()
|
||||
|
||||
/datum/component/basic_inhands/RegisterWithParent()
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_updated_overlays))
|
||||
RegisterSignal(parent, COMSIG_MOB_UPDATE_HELD_ITEMS, PROC_REF(on_updated_held_items))
|
||||
|
||||
/datum/component/basic_inhands/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_MOB_UPDATE_HELD_ITEMS))
|
||||
|
||||
/// When your overlays update, add your held overlays
|
||||
/datum/component/basic_inhands/proc/on_updated_overlays(atom/parent_atom, list/overlays)
|
||||
SIGNAL_HANDLER
|
||||
overlays += cached_overlays
|
||||
|
||||
/// When your number of held items changes, regenerate held icons
|
||||
/datum/component/basic_inhands/proc/on_updated_held_items(mob/living/holding_mob)
|
||||
SIGNAL_HANDLER
|
||||
var/list/held_overlays = list()
|
||||
for(var/obj/item/held in holding_mob.held_items)
|
||||
var/is_right = holding_mob.get_held_index_of_item(held) % 2 == 0
|
||||
var/icon_file = is_right ? held.righthand_file : held.lefthand_file
|
||||
var/mutable_appearance/held_overlay = held.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE)
|
||||
held_overlay.pixel_y += y_offset
|
||||
held_overlay.pixel_x += x_offset * (is_right ? 1 : -1)
|
||||
held_overlays += held_overlay
|
||||
|
||||
cached_overlays = held_overlays
|
||||
holding_mob.update_appearance(UPDATE_OVERLAYS)
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
/// Chop one off
|
||||
/datum/element/amputating_limbs/proc/amputate(mob/living/surgeon, mob/living/carbon/victim, obj/item/bodypart/to_remove)
|
||||
surgeon.visible_message(span_warning("[surgeon] begins [surgery_verb] [to_remove] off of [victim]!"))
|
||||
surgeon.visible_message(span_warning("[surgeon] [surgery_verb] [to_remove] off of [victim]!"))
|
||||
if (surgery_time > 0 && !do_after(surgeon, delay = surgery_time, target = victim))
|
||||
return
|
||||
to_remove.dismember()
|
||||
|
||||
@@ -257,6 +257,7 @@
|
||||
/mob/living/basic/cow/wisdom,
|
||||
/mob/living/basic/crab,
|
||||
/mob/living/basic/goat,
|
||||
/mob/living/basic/gorilla,
|
||||
/mob/living/basic/headslug,
|
||||
/mob/living/basic/killer_tomato,
|
||||
/mob/living/basic/lizard,
|
||||
@@ -274,7 +275,6 @@
|
||||
/mob/living/basic/statue,
|
||||
/mob/living/basic/stickman,
|
||||
/mob/living/basic/stickman/dog,
|
||||
/mob/living/simple_animal/hostile/gorilla,
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/lesser,
|
||||
/mob/living/simple_animal/parrot,
|
||||
/mob/living/simple_animal/pet/cat,
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
show_in_report = FALSE // Selective attention test. Did you spot the gorilla?
|
||||
|
||||
/// The gorilla we created, we only hold this ref until the round starts.
|
||||
var/mob/living/simple_animal/hostile/gorilla/cargo_domestic/cargorilla
|
||||
var/mob/living/basic/gorilla/cargorilla/cargorilla
|
||||
|
||||
/datum/station_trait/cargorilla/New()
|
||||
. = ..()
|
||||
@@ -189,7 +189,7 @@
|
||||
cargorilla = null
|
||||
|
||||
/// Get us a ghost for the gorilla.
|
||||
/datum/station_trait/cargorilla/proc/get_ghost_for_gorilla(mob/living/simple_animal/hostile/gorilla/cargo_domestic/gorilla)
|
||||
/datum/station_trait/cargorilla/proc/get_ghost_for_gorilla(mob/living/basic/gorilla/cargorilla/gorilla)
|
||||
if(QDELETED(gorilla))
|
||||
return
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
/datum/reagent/medicine/strange_reagent = 5,
|
||||
)
|
||||
tastes = list("the jungle" = 1, "bananas" = 1, "jimmies" = 1)
|
||||
spawned_mob = /mob/living/simple_animal/hostile/gorilla
|
||||
spawned_mob = /mob/living/basic/gorilla
|
||||
|
||||
/obj/item/food/monkeycube/chicken
|
||||
name = "chicken cube"
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
JOB_CHIEF_MEDICAL_OFFICER = /mob/living/simple_animal/pet/cat/runtime,
|
||||
JOB_CHIEF_ENGINEER = /mob/living/simple_animal/parrot/poly,
|
||||
JOB_QUARTERMASTER = list(
|
||||
/mob/living/basic/gorilla/cargorilla,
|
||||
/mob/living/basic/sloth/citrus,
|
||||
/mob/living/basic/sloth/paperwork,
|
||||
/mob/living/simple_animal/hostile/gorilla/cargo_domestic,
|
||||
)
|
||||
)
|
||||
/// The head that we are targetting
|
||||
|
||||
@@ -286,6 +286,10 @@
|
||||
I.dropped(src)
|
||||
return FALSE
|
||||
|
||||
/// Returns true if a mob is holding something
|
||||
/mob/proc/is_holding_items()
|
||||
return !!locate(/obj/item) in held_items
|
||||
|
||||
/mob/proc/drop_all_held_items()
|
||||
. = FALSE
|
||||
for(var/obj/item/I in held_items)
|
||||
|
||||
@@ -291,6 +291,7 @@
|
||||
update_held_items()
|
||||
|
||||
/mob/living/basic/update_held_items()
|
||||
. = ..()
|
||||
if(isnull(client) || isnull(hud_used) || hud_used.hud_version == HUD_STYLE_NOHUD)
|
||||
return
|
||||
var/turf/our_turf = get_turf(src)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
BB_EMOTE_SAY = list("HONK", "Honk!", "Welcome to clown planet!"),
|
||||
BB_EMOTE_HEAR = list("honks", "squeaks"),
|
||||
BB_EMOTE_SOUND = list('sound/items/bikehorn.ogg'), //WE LOVE TO PARTY
|
||||
BB_EMOTE_CHANCE = 5,
|
||||
BB_SPEAK_CHANCE = 5,
|
||||
)
|
||||
///do we waddle (honk)
|
||||
var/waddles = TRUE
|
||||
@@ -150,9 +150,9 @@
|
||||
),
|
||||
BB_EMOTE_HEAR = list("honks", "contemplates its existence"),
|
||||
BB_EMOTE_SEE = list("sweats", "jiggles"),
|
||||
BB_EMOTE_CHANCE = 5,
|
||||
BB_SPEAK_CHANCE = 5,
|
||||
)
|
||||
|
||||
|
||||
/mob/living/basic/clown/fleshclown/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
|
||||
@@ -185,7 +185,7 @@
|
||||
emotes = list(
|
||||
BB_EMOTE_SAY = list("YA-HONK!!!"),
|
||||
BB_EMOTE_HEAR = list("honks", "squeaks"),
|
||||
BB_EMOTE_CHANCE = 60,
|
||||
BB_SPEAK_CHANCE = 60,
|
||||
)
|
||||
|
||||
/mob/living/basic/clown/clownhulk
|
||||
@@ -221,7 +221,7 @@
|
||||
BB_EMOTE_SAY = list("HONK", "Honk!", "HAUAUANK!!!", "GUUURRRRAAAHHH!!!"),
|
||||
BB_EMOTE_HEAR = list("honks", "grunts"),
|
||||
BB_EMOTE_SEE = list("sweats"),
|
||||
BB_EMOTE_CHANCE = 5,
|
||||
BB_SPEAK_CHANCE = 5,
|
||||
)
|
||||
|
||||
/mob/living/basic/clown/clownhulk/chlown
|
||||
@@ -252,7 +252,7 @@
|
||||
emotes = list(
|
||||
BB_EMOTE_SAY = list("HONK", "Honk!", "Bruh", "cheeaaaahhh?"),
|
||||
BB_EMOTE_SEE = list("asserts his dominance", "emasculates everyone implicitly"),
|
||||
BB_EMOTE_CHANCE = 5,
|
||||
BB_SPEAK_CHANCE = 5,
|
||||
)
|
||||
|
||||
/mob/living/basic/clown/clownhulk/honkmunculus
|
||||
@@ -318,7 +318,7 @@
|
||||
BB_EMOTE_SAY = list("HONK!!!", "The Honkmother is merciful, so I must act out her wrath.", "parce mihi ad beatus honkmother placet mihi ut peccata committere,", "DIE!!!"),
|
||||
BB_EMOTE_HEAR = list("honks", "grunts"),
|
||||
BB_EMOTE_SEE = list("sweats"),
|
||||
BB_EMOTE_CHANCE = 5,
|
||||
BB_SPEAK_CHANCE = 5,
|
||||
)
|
||||
|
||||
/mob/living/basic/clown/mutant
|
||||
@@ -354,7 +354,7 @@
|
||||
emotes = list(
|
||||
BB_EMOTE_SAY = list("aaaaaahhhhuuhhhuhhhaaaaa", "AAAaaauuuaaAAAaauuhhh", "huuuuuh... hhhhuuuooooonnnnkk", "HuaUAAAnKKKK"),
|
||||
BB_EMOTE_SEE = list("squirms", "writhes", "pulsates", "froths", "oozes"),
|
||||
BB_EMOTE_CHANCE = 10,
|
||||
BB_SPEAK_CHANCE = 10,
|
||||
)
|
||||
|
||||
/mob/living/basic/clown/mutant/slow
|
||||
|
||||
181
code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm
Normal file
181
code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm
Normal file
@@ -0,0 +1,181 @@
|
||||
/// Where do we draw gorilla held overlays?
|
||||
#define GORILLA_HANDS_LAYER 1
|
||||
|
||||
/**
|
||||
* Like a bigger monkey
|
||||
* They make a lot of noise and punch limbs off unconscious folks
|
||||
*/
|
||||
/mob/living/basic/gorilla
|
||||
name = "Gorilla"
|
||||
desc = "A ground-dwelling, predominantly herbivorous ape which usually inhabits the forests of central Africa but today is quite far away from there."
|
||||
icon = 'icons/mob/simple/gorilla.dmi'
|
||||
icon_state = "crawling"
|
||||
icon_living = "crawling"
|
||||
icon_dead = "dead"
|
||||
health_doll_icon = "crawling"
|
||||
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
maxHealth = 220
|
||||
health = 220
|
||||
response_help_continuous = "prods"
|
||||
response_help_simple = "prod"
|
||||
response_disarm_continuous = "challenges"
|
||||
response_disarm_simple = "challenge"
|
||||
response_harm_continuous = "thumps"
|
||||
response_harm_simple = "thump"
|
||||
speed = 0.5
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 18
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1.5, TOX = 1.5, CLONE = 0, STAMINA = 0, OXY = 1.5)
|
||||
obj_damage = 20
|
||||
attack_verb_continuous = "pummels"
|
||||
attack_verb_simple = "pummel"
|
||||
attack_sound = 'sound/weapons/punch1.ogg'
|
||||
unique_name = TRUE
|
||||
ai_controller = /datum/ai_controller/basic_controller/gorilla
|
||||
faction = list(FACTION_MONKEY, FACTION_JUNGLE)
|
||||
butcher_results = list(/obj/item/food/meat/slab/gorilla = 4, /obj/effect/gibspawner/generic/animal = 1)
|
||||
/// How likely our meaty fist is to stun someone
|
||||
var/paralyze_chance = 20
|
||||
/// A counter for when we can scream again
|
||||
var/oogas = 0
|
||||
/// Types of things we want to find and eat
|
||||
var/static/list/gorilla_food = list(
|
||||
/obj/item/food/bread/banana,
|
||||
/obj/item/food/breadslice/banana,
|
||||
/obj/item/food/cnds/banana_honk,
|
||||
/obj/item/food/grown/banana,
|
||||
/obj/item/food/popsicle/topsicle/banana,
|
||||
/obj/item/food/salad/fruit,
|
||||
/obj/item/food/salad/jungle,
|
||||
/obj/item/food/sundae,
|
||||
)
|
||||
|
||||
/mob/living/basic/gorilla/Initialize(mapload)
|
||||
. = ..()
|
||||
add_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP), ROUNDSTART_TRAIT)
|
||||
AddElement(/datum/element/wall_smasher)
|
||||
AddElement(/datum/element/dextrous)
|
||||
AddElement(/datum/element/footstep, FOOTSTEP_MOB_BAREFOOT)
|
||||
AddElement(/datum/element/basic_eating, heal_amt = 10, food_types = gorilla_food)
|
||||
AddElement(
|
||||
/datum/element/amputating_limbs, \
|
||||
surgery_time = 0 SECONDS, \
|
||||
surgery_verb = "punches",\
|
||||
)
|
||||
AddComponent(/datum/component/personal_crafting)
|
||||
AddComponent(/datum/component/basic_inhands, y_offset = -1)
|
||||
ai_controller?.set_blackboard_key(BB_BASIC_FOODS, gorilla_food)
|
||||
|
||||
/mob/living/basic/gorilla/update_overlays()
|
||||
. = ..()
|
||||
if (is_holding_items())
|
||||
. += "standing_overlay"
|
||||
|
||||
/mob/living/basic/gorilla/update_icon_state()
|
||||
. = ..()
|
||||
if (stat == DEAD)
|
||||
return
|
||||
icon_state = is_holding_items() ? "standing" : "crawling"
|
||||
|
||||
/mob/living/basic/gorilla/update_held_items()
|
||||
. = ..()
|
||||
update_appearance(UPDATE_ICON)
|
||||
if (is_holding_items())
|
||||
add_movespeed_modifier(/datum/movespeed_modifier/gorilla_standing)
|
||||
else
|
||||
remove_movespeed_modifier(/datum/movespeed_modifier/gorilla_standing)
|
||||
|
||||
/mob/living/basic/gorilla/melee_attack(mob/living/target, list/modifiers, ignore_cooldown)
|
||||
. = ..()
|
||||
if (!. || !isliving(target))
|
||||
return
|
||||
ooga_ooga()
|
||||
if (prob(paralyze_chance))
|
||||
target.Paralyze(2 SECONDS)
|
||||
visible_message(span_danger("[src] knocks [target] down!"))
|
||||
else
|
||||
target.throw_at(get_edge_target_turf(target, dir), range = rand(1, 2), speed = 7, thrower = src)
|
||||
|
||||
/mob/living/basic/gorilla/gib(drop_bitflags = DROP_BRAIN)
|
||||
if(!(drop_bitflags & DROP_BRAIN))
|
||||
return ..()
|
||||
var/mob/living/brain/gorilla_brain = new(drop_location())
|
||||
gorilla_brain.name = real_name
|
||||
gorilla_brain.real_name = real_name
|
||||
mind?.transfer_to(gorilla_brain)
|
||||
return ..()
|
||||
|
||||
/mob/living/basic/gorilla/can_use_guns(obj/item/gun)
|
||||
to_chat(src, span_warning("Your meaty finger is much too large for the trigger guard!"))
|
||||
return FALSE
|
||||
|
||||
/// Assert your dominance with audio cues
|
||||
/mob/living/basic/gorilla/proc/ooga_ooga()
|
||||
if (isnull(client))
|
||||
return // Sorry NPCs
|
||||
oogas -= 1
|
||||
if(oogas > 0)
|
||||
return
|
||||
oogas = rand(2,6)
|
||||
emote("ooga")
|
||||
|
||||
/// Gorillas are slower when carrying something
|
||||
/datum/movespeed_modifier/gorilla_standing
|
||||
blacklisted_movetypes = (FLYING|FLOATING)
|
||||
multiplicative_slowdown = 0.5
|
||||
|
||||
/// A smaller gorilla summoned via magic
|
||||
/mob/living/basic/gorilla/lesser
|
||||
name = "lesser Gorilla"
|
||||
desc = "An adolescent Gorilla. It may not be fully grown but, much like a banana, that just means it's sturdier and harder to chew!"
|
||||
maxHealth = 120
|
||||
health = 120
|
||||
speed = 0.35
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 15
|
||||
obj_damage = 15
|
||||
ai_controller = /datum/ai_controller/basic_controller/gorilla/lesser
|
||||
butcher_results = list(/obj/item/food/meat/slab/gorilla = 2)
|
||||
|
||||
/mob/living/basic/gorilla/lesser/Initialize(mapload)
|
||||
. = ..()
|
||||
transform *= 0.75
|
||||
|
||||
/// Cargo's wonderful mascot, the tranquil box-carrying ape
|
||||
/mob/living/basic/gorilla/cargorilla
|
||||
name = "Cargorilla" // Overriden, normally
|
||||
icon = 'icons/mob/simple/cargorillia.dmi'
|
||||
desc = "Cargo's pet gorilla. They seem to have an 'I love Mom' tattoo."
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
faction = list(FACTION_NEUTRAL, FACTION_MONKEY, FACTION_JUNGLE)
|
||||
unique_name = FALSE
|
||||
ai_controller = null
|
||||
|
||||
/mob/living/basic/gorilla/cargorilla/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_PACIFISM, INNATE_TRAIT)
|
||||
AddComponent(/datum/component/crate_carrier)
|
||||
|
||||
/**
|
||||
* Poll ghosts for control of the gorilla. Not added in init because we only want to poll when the round starts.
|
||||
* Preferably in future we can replace this with a popup on the lobby to queue to become a gorilla.
|
||||
*/
|
||||
/mob/living/basic/gorilla/cargorilla/proc/poll_for_gorilla()
|
||||
AddComponent(\
|
||||
/datum/component/ghost_direct_control,\
|
||||
poll_candidates = TRUE,\
|
||||
poll_length = 30 SECONDS,\
|
||||
role_name = "Cargorilla",\
|
||||
assumed_control_message = "You are Cargorilla, a pacifist friend of the station and carrier of freight.",\
|
||||
poll_ignore_key = POLL_IGNORE_CARGORILLA,\
|
||||
after_assumed_control = CALLBACK(src, PROC_REF(became_player_controlled)),\
|
||||
)
|
||||
|
||||
/// Called once a ghost assumes control
|
||||
/mob/living/basic/gorilla/cargorilla/proc/became_player_controlled()
|
||||
mind.set_assigned_role(SSjob.GetJobType(/datum/job/cargo_technician))
|
||||
mind.special_role = "Cargorilla"
|
||||
to_chat(src, span_notice("You can pick up crates by clicking on them, and drop them by clicking on the ground."))
|
||||
|
||||
#undef GORILLA_HANDS_LAYER
|
||||
@@ -0,0 +1,5 @@
|
||||
/// Cargorilla's ID card
|
||||
/obj/item/card/id/advanced/cargo_gorilla
|
||||
name = "cargorilla ID"
|
||||
desc = "A card used to provide ID and determine access across the station. A gorilla-sized ID for a gorilla-sized cargo technician."
|
||||
trim = /datum/id_trim/job/cargo_technician
|
||||
@@ -0,0 +1,35 @@
|
||||
/// Pretty basic, just click people to death. Also hunt and eat bananas.
|
||||
/datum/ai_controller/basic_controller/gorilla
|
||||
blackboard = list(
|
||||
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items/gorilla,
|
||||
BB_EMOTE_KEY = "ooga",
|
||||
BB_EMOTE_CHANCE = 40,
|
||||
)
|
||||
|
||||
ai_traits = STOP_MOVING_WHEN_PULLED
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/run_emote,
|
||||
/datum/ai_planning_subtree/find_food,
|
||||
/datum/ai_planning_subtree/simple_find_target,
|
||||
/datum/ai_planning_subtree/attack_obstacle_in_path/gorilla,
|
||||
/datum/ai_planning_subtree/basic_melee_attack_subtree,
|
||||
)
|
||||
|
||||
/datum/targetting_datum/basic/allow_items/gorilla
|
||||
stat_attack = UNCONSCIOUS
|
||||
|
||||
/datum/ai_planning_subtree/attack_obstacle_in_path/gorilla
|
||||
attack_behaviour = /datum/ai_behavior/attack_obstructions/gorilla
|
||||
|
||||
/datum/ai_behavior/attack_obstructions/gorilla
|
||||
can_attack_turfs = TRUE
|
||||
|
||||
/datum/ai_controller/basic_controller/gorilla/lesser
|
||||
blackboard = list(
|
||||
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items,
|
||||
BB_EMOTE_KEY = "ooga",
|
||||
BB_EMOTE_CHANCE = 60,
|
||||
)
|
||||
@@ -1,5 +1,5 @@
|
||||
/datum/emote/gorilla
|
||||
mob_type_allowed_typecache = /mob/living/simple_animal/hostile/gorilla
|
||||
mob_type_allowed_typecache = /mob/living/basic/gorilla
|
||||
mob_type_blacklist_typecache = list()
|
||||
|
||||
/datum/emote/gorilla/ooga
|
||||
@@ -9,4 +9,3 @@
|
||||
message_param = "oogas at %t."
|
||||
emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE
|
||||
sound = 'sound/creatures/gorilla.ogg'
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
AddElement(\
|
||||
/datum/element/amputating_limbs,\
|
||||
surgery_time = 0 SECONDS,\
|
||||
surgery_verb = "tearing",\
|
||||
surgery_verb = "tears",\
|
||||
minimum_stat = CONSCIOUS,\
|
||||
snip_chance = 10,\
|
||||
target_zones = GLOB.arm_zones,\
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
AddElement(/datum/element/basic_eating, food_types = target_foods)
|
||||
AddElement(\
|
||||
/datum/element/amputating_limbs,\
|
||||
surgery_verb = "snipping",\
|
||||
surgery_verb = "begins snipping",\
|
||||
target_zones = GLOB.arm_zones,\
|
||||
)
|
||||
charge = new(src)
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
//Royals have bigger sprites, so inhand things must be handled differently.
|
||||
/mob/living/carbon/alien/adult/royal/update_held_items()
|
||||
..()
|
||||
. = ..()
|
||||
remove_overlay(HANDS_LAYER)
|
||||
var/list/hands = list()
|
||||
|
||||
|
||||
@@ -282,11 +282,17 @@
|
||||
update_body()
|
||||
|
||||
/mob/living/carbon/update_held_items()
|
||||
. = ..()
|
||||
remove_overlay(HANDS_LAYER)
|
||||
if (handcuffed)
|
||||
drop_all_held_items()
|
||||
return
|
||||
|
||||
overlays_standing[HANDS_LAYER] = get_held_overlays()
|
||||
apply_overlay(HANDS_LAYER)
|
||||
|
||||
/// Generate held item overlays
|
||||
/mob/living/carbon/proc/get_held_overlays()
|
||||
var/list/hands = list()
|
||||
for(var/obj/item/I in held_items)
|
||||
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
|
||||
@@ -307,9 +313,7 @@
|
||||
icon_file = I.righthand_file
|
||||
|
||||
hands += I.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE)
|
||||
|
||||
overlays_standing[HANDS_LAYER] = hands
|
||||
apply_overlay(HANDS_LAYER)
|
||||
return hands
|
||||
|
||||
/mob/living/carbon/update_fire_overlay(stacks, on_fire, last_icon_state, suffix = "")
|
||||
var/fire_icon = "[dna?.species.fire_overlay || "human"]_[stacks > MOB_BIG_FIRE_STACK_THRESHOLD ? "big_fire" : "small_fire"][suffix]"
|
||||
|
||||
@@ -481,12 +481,7 @@ There are several things that need to be remembered:
|
||||
apply_overlay(LEGCUFF_LAYER)
|
||||
throw_alert("legcuffed", /atom/movable/screen/alert/restrained/legcuffed, new_master = src.legcuffed)
|
||||
|
||||
/mob/living/carbon/human/update_held_items()
|
||||
remove_overlay(HANDS_LAYER)
|
||||
if (handcuffed)
|
||||
drop_all_held_items()
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/get_held_overlays()
|
||||
var/list/hands = list()
|
||||
for(var/obj/item/worn_item in held_items)
|
||||
var/held_index = get_held_index_of_item(worn_item)
|
||||
@@ -515,8 +510,7 @@ There are several things that need to be remembered:
|
||||
held_in_hand?.held_hand_offset?.apply_offset(hand_overlay)
|
||||
|
||||
hands += hand_overlay
|
||||
overlays_standing[HANDS_LAYER] = hands
|
||||
apply_overlay(HANDS_LAYER)
|
||||
return hands
|
||||
|
||||
/proc/wear_female_version(t_color, icon, layer, type, greyscale_colors)
|
||||
var/index = "[t_color]-[greyscale_colors]"
|
||||
|
||||
@@ -1414,6 +1414,7 @@
|
||||
/mob/living/basic/cow,
|
||||
/mob/living/basic/crab,
|
||||
/mob/living/basic/goat,
|
||||
/mob/living/basic/gorilla,
|
||||
/mob/living/basic/headslug,
|
||||
/mob/living/basic/killer_tomato,
|
||||
/mob/living/basic/lizard,
|
||||
@@ -1431,7 +1432,6 @@
|
||||
/mob/living/basic/statue,
|
||||
/mob/living/basic/stickman,
|
||||
/mob/living/basic/stickman/dog,
|
||||
/mob/living/simple_animal/hostile/gorilla,
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/lesser,
|
||||
/mob/living/simple_animal/parrot,
|
||||
/mob/living/simple_animal/pet/cat,
|
||||
|
||||
@@ -173,6 +173,7 @@
|
||||
. = ..()
|
||||
GLOB.drones_list += src
|
||||
access_card = new /obj/item/card/id/advanced/simple_bot(src)
|
||||
AddComponent(/datum/component/basic_inhands, y_offset = getItemPixelShiftY())
|
||||
|
||||
// Doing this hurts my soul, but simple_animal access reworks are for another day.
|
||||
var/datum/id_trim/job/cap_trim = SSid_access.trim_singletons_by_path[/datum/id_trim/job/captain]
|
||||
|
||||
@@ -27,45 +27,6 @@
|
||||
if(slot_flags & (ITEM_SLOT_HANDS|ITEM_SLOT_BACKPACK|ITEM_SLOT_DEX_STORAGE))
|
||||
update_inv_internal_storage()
|
||||
|
||||
/mob/living/simple_animal/drone/update_held_items()
|
||||
remove_overlay(DRONE_HANDS_LAYER)
|
||||
var/list/hands_overlays = list()
|
||||
|
||||
var/obj/item/l_hand = get_item_for_held_index(1)
|
||||
var/obj/item/r_hand = get_item_for_held_index(2)
|
||||
|
||||
var/y_shift = getItemPixelShiftY()
|
||||
|
||||
if(r_hand)
|
||||
var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(default_layer = DRONE_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
|
||||
if(y_shift)
|
||||
r_hand_overlay.pixel_y += y_shift
|
||||
|
||||
hands_overlays += r_hand_overlay
|
||||
|
||||
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
|
||||
SET_PLANE_EXPLICIT(r_hand, ABOVE_HUD_PLANE, src)
|
||||
r_hand.screen_loc = ui_hand_position(get_held_index_of_item(r_hand))
|
||||
client.screen |= r_hand
|
||||
|
||||
if(l_hand)
|
||||
var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(default_layer = DRONE_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
|
||||
if(y_shift)
|
||||
l_hand_overlay.pixel_y += y_shift
|
||||
|
||||
hands_overlays += l_hand_overlay
|
||||
|
||||
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
|
||||
SET_PLANE_EXPLICIT(l_hand, ABOVE_HUD_PLANE, src)
|
||||
l_hand.screen_loc = ui_hand_position(get_held_index_of_item(l_hand))
|
||||
client.screen |= l_hand
|
||||
|
||||
|
||||
if(hands_overlays.len)
|
||||
drone_overlays[DRONE_HANDS_LAYER] = hands_overlays
|
||||
apply_overlay(DRONE_HANDS_LAYER)
|
||||
|
||||
|
||||
/mob/living/simple_animal/drone/proc/update_inv_internal_storage()
|
||||
if(internal_storage && client && hud_used?.hud_shown)
|
||||
internal_storage.screen_loc = ui_drone_storage
|
||||
|
||||
@@ -90,6 +90,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
GLOB.parasites += src
|
||||
update_theme(theme)
|
||||
AddElement(/datum/element/simple_flying)
|
||||
AddComponent(/datum/component/basic_inhands)
|
||||
manifest_effects()
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/Destroy() //if deleted by admins or something random, cut from the summoner
|
||||
@@ -462,32 +463,6 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
cut_overlay(overlay)
|
||||
guardian_overlays[cache_index] = null
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/update_held_items()
|
||||
remove_overlay(GUARDIAN_HANDS_LAYER)
|
||||
var/list/hands_overlays = list()
|
||||
var/obj/item/l_hand = get_item_for_held_index(1)
|
||||
var/obj/item/r_hand = get_item_for_held_index(2)
|
||||
|
||||
if(r_hand)
|
||||
hands_overlays += r_hand.build_worn_icon(default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
|
||||
|
||||
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
|
||||
SET_PLANE_EXPLICIT(r_hand, ABOVE_HUD_PLANE, src)
|
||||
r_hand.screen_loc = ui_hand_position(get_held_index_of_item(r_hand))
|
||||
client.screen |= r_hand
|
||||
|
||||
if(l_hand)
|
||||
hands_overlays += l_hand.build_worn_icon(default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
|
||||
|
||||
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
|
||||
SET_PLANE_EXPLICIT(l_hand, ABOVE_HUD_PLANE, src)
|
||||
l_hand.screen_loc = ui_hand_position(get_held_index_of_item(l_hand))
|
||||
client.screen |= l_hand
|
||||
|
||||
if(length(hands_overlays))
|
||||
guardian_overlays[GUARDIAN_HANDS_LAYER] = hands_overlays
|
||||
apply_overlay(GUARDIAN_HANDS_LAYER)
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/regenerate_icons()
|
||||
update_held_items()
|
||||
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
#define GORILLA_TOTAL_LAYERS 1
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla
|
||||
name = "Gorilla"
|
||||
desc = "A ground-dwelling, predominantly herbivorous ape that inhabits the forests of central Africa."
|
||||
icon = 'icons/mob/simple/gorilla.dmi'
|
||||
icon_state = "crawling"
|
||||
icon_living = "crawling"
|
||||
icon_dead = "dead"
|
||||
health_doll_icon = "crawling"
|
||||
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
speak_chance = 80
|
||||
maxHealth = 220
|
||||
health = 220
|
||||
loot = list(/obj/effect/gibspawner/generic/animal)
|
||||
butcher_results = list(/obj/item/food/meat/slab/gorilla = 4)
|
||||
response_help_continuous = "prods"
|
||||
response_help_simple = "prod"
|
||||
response_disarm_continuous = "challenges"
|
||||
response_disarm_simple = "challenge"
|
||||
response_harm_continuous = "thumps"
|
||||
response_harm_simple = "thump"
|
||||
speed = 0.5
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 18
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1.5, TOX = 1.5, CLONE = 0, STAMINA = 0, OXY = 1.5)
|
||||
obj_damage = 20
|
||||
environment_smash = ENVIRONMENT_SMASH_WALLS
|
||||
attack_verb_continuous = "pummels"
|
||||
attack_verb_simple = "pummel"
|
||||
attack_sound = 'sound/weapons/punch1.ogg'
|
||||
dextrous = TRUE
|
||||
hud_type = /datum/hud/dextrous
|
||||
held_items = list(null, null)
|
||||
faction = list(FACTION_MONKEY, FACTION_JUNGLE)
|
||||
robust_searching = TRUE
|
||||
stat_attack = HARD_CRIT
|
||||
minbodytemp = 270
|
||||
maxbodytemp = 350
|
||||
unique_name = TRUE
|
||||
footstep_type = FOOTSTEP_MOB_BAREFOOT
|
||||
|
||||
var/list/gorilla_overlays[GORILLA_TOTAL_LAYERS]
|
||||
var/oogas = 0
|
||||
|
||||
// Gorillas like to dismember limbs from unconscious mobs.
|
||||
// Returns null when the target is not an unconscious carbon mob; a list of limbs (possibly empty) otherwise.
|
||||
/mob/living/simple_animal/hostile/gorilla/proc/get_target_bodyparts(atom/hit_target)
|
||||
if(!iscarbon(hit_target))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/carbon_target = hit_target
|
||||
if(carbon_target.stat < UNCONSCIOUS)
|
||||
return
|
||||
|
||||
var/list/parts = list()
|
||||
for(var/obj/item/bodypart/part as anything in carbon_target.bodyparts)
|
||||
if(part.body_part == HEAD || part.body_part == CHEST)
|
||||
continue
|
||||
if(part.bodypart_flags & BODYPART_UNREMOVABLE)
|
||||
continue
|
||||
parts += part
|
||||
return parts
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/AttackingTarget(atom/attacked_target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
if(client)
|
||||
oogaooga()
|
||||
|
||||
var/list/parts = get_target_bodyparts(target)
|
||||
if(length(parts))
|
||||
var/obj/item/bodypart/to_dismember = pick(parts)
|
||||
to_dismember.dismember()
|
||||
return
|
||||
|
||||
if(isliving(target))
|
||||
var/mob/living/living_target = target
|
||||
if(prob(80))
|
||||
living_target.throw_at(get_edge_target_turf(living_target, dir), rand(1, 2), 7, src)
|
||||
|
||||
else
|
||||
living_target.Paralyze(2 SECONDS)
|
||||
visible_message(span_danger("[src] knocks [living_target] down!"))
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/CanAttack(atom/the_target)
|
||||
var/list/parts = get_target_bodyparts(target)
|
||||
return ..() && !ismonkey(the_target) && (!parts || length(parts) > 3)
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/CanSmashTurfs(turf/T)
|
||||
return iswallturf(T)
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/gib(drop_bitflags=DROP_BRAIN)
|
||||
if(drop_bitflags & DROP_BRAIN)
|
||||
var/mob/living/brain/gorilla_brain = new(drop_location())
|
||||
gorilla_brain.name = real_name
|
||||
gorilla_brain.real_name = real_name
|
||||
mind?.transfer_to(gorilla_brain)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/handle_automated_speech(override)
|
||||
if(speak_chance && (override || prob(speak_chance)))
|
||||
playsound(src, 'sound/creatures/gorilla.ogg', 50)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/can_use_guns(obj/item/G)
|
||||
to_chat(src, span_warning("Your meaty finger is much too large for the trigger guard!"))
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/proc/oogaooga()
|
||||
oogas -= 1
|
||||
if(oogas <= 0)
|
||||
oogas = rand(2,6)
|
||||
playsound(src, 'sound/creatures/gorilla.ogg', 50)
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/lesser
|
||||
name = "lesser Gorilla"
|
||||
desc = "An adolescent Gorilla. It may not be fully grown but, much like a banana, that just means it's sturdier and harder to chew!"
|
||||
speak_chance = 100 // compensating for something
|
||||
maxHealth = 120
|
||||
health = 120
|
||||
butcher_results = list(/obj/item/food/meat/slab/gorilla = 2)
|
||||
speed = 0.35
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 15
|
||||
obj_damage = 15
|
||||
stat_attack = SOFT_CRIT
|
||||
unique_name = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/lesser/Initialize(mapload)
|
||||
. = ..()
|
||||
transform *= 0.75 // smolrilla
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/cargo_domestic
|
||||
name = "Cargorilla" // Overriden, normally
|
||||
icon = 'icons/mob/simple/cargorillia.dmi'
|
||||
desc = "Cargo's pet gorilla. They seem to have an 'I love Mom' tattoo."
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
faction = list(FACTION_NEUTRAL, FACTION_MONKEY, FACTION_JUNGLE)
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
unique_name = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/cargo_domestic/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_PACIFISM, INNATE_TRAIT)
|
||||
AddComponent(/datum/component/crate_carrier)
|
||||
|
||||
/// Poll ghosts for control of the gorilla.
|
||||
/mob/living/simple_animal/hostile/gorilla/cargo_domestic/proc/poll_for_gorilla()
|
||||
AddComponent(\
|
||||
/datum/component/ghost_direct_control,\
|
||||
poll_candidates = TRUE,\
|
||||
poll_length = 30 SECONDS,\
|
||||
role_name = "Cargorilla",\
|
||||
assumed_control_message = "You are Cargorilla, a pacifistic friend of the station and carrier of freight.",\
|
||||
poll_ignore_key = POLL_IGNORE_CARGORILLA,\
|
||||
after_assumed_control = CALLBACK(src, PROC_REF(became_player_controlled)),\
|
||||
)
|
||||
|
||||
/// Called once a ghost assumes control
|
||||
/mob/living/simple_animal/hostile/gorilla/cargo_domestic/proc/became_player_controlled()
|
||||
mind.set_assigned_role(SSjob.GetJobType(/datum/job/cargo_technician))
|
||||
mind.special_role = "Cargorilla"
|
||||
to_chat(src, span_notice("You can pick up crates by clicking on them, and drop them by clicking on the ground."))
|
||||
|
||||
/obj/item/card/id/advanced/cargo_gorilla
|
||||
name = "cargorilla ID"
|
||||
desc = "A card used to provide ID and determine access across the station. A gorilla-sized ID for a gorilla-sized cargo technician."
|
||||
trim = /datum/id_trim/job/cargo_technician
|
||||
|
||||
#undef GORILLA_TOTAL_LAYERS
|
||||
@@ -1,56 +0,0 @@
|
||||
#define GORILLA_HANDS_LAYER 1
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/proc/apply_overlay(cache_index)
|
||||
. = gorilla_overlays[cache_index]
|
||||
if(.)
|
||||
add_overlay(.)
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/proc/remove_overlay(cache_index)
|
||||
var/I = gorilla_overlays[cache_index]
|
||||
if(I)
|
||||
cut_overlay(I)
|
||||
gorilla_overlays[cache_index] = null
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/update_held_items()
|
||||
cut_overlays("standing_overlay")
|
||||
remove_overlay(GORILLA_HANDS_LAYER)
|
||||
|
||||
var/standing = FALSE
|
||||
for(var/I in held_items)
|
||||
if(I)
|
||||
standing = TRUE
|
||||
break
|
||||
if(!standing)
|
||||
if(stat != DEAD)
|
||||
icon_state = "crawling"
|
||||
set_varspeed(0.5)
|
||||
return ..()
|
||||
if(stat != DEAD)
|
||||
icon_state = "standing"
|
||||
set_varspeed(1) // Gorillas are slow when standing up.
|
||||
|
||||
var/list/hands_overlays = list()
|
||||
|
||||
var/obj/item/l_hand = get_item_for_held_index(1)
|
||||
var/obj/item/r_hand = get_item_for_held_index(2)
|
||||
|
||||
if(r_hand)
|
||||
var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(default_layer = GORILLA_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
|
||||
r_hand_overlay.pixel_y -= 1
|
||||
hands_overlays += r_hand_overlay
|
||||
|
||||
if(l_hand)
|
||||
var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(default_layer = GORILLA_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
|
||||
l_hand_overlay.pixel_y -= 1
|
||||
hands_overlays += l_hand_overlay
|
||||
|
||||
if(hands_overlays.len)
|
||||
gorilla_overlays[GORILLA_HANDS_LAYER] = hands_overlays
|
||||
apply_overlay(GORILLA_HANDS_LAYER)
|
||||
add_overlay("standing_overlay")
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/gorilla/regenerate_icons()
|
||||
update_held_items()
|
||||
|
||||
#undef GORILLA_HANDS_LAYER
|
||||
@@ -563,6 +563,7 @@
|
||||
update_held_items()
|
||||
|
||||
/mob/living/simple_animal/update_held_items()
|
||||
. = ..()
|
||||
if(!client || !hud_used || hud_used.hud_version == HUD_STYLE_NOHUD)
|
||||
return
|
||||
var/turf/our_turf = get_turf(src)
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
|
||||
///Updates the held items overlay(s) & HUD element.
|
||||
/mob/proc/update_held_items()
|
||||
return
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_HELD_ITEMS)
|
||||
|
||||
///Updates the mask overlay & HUD element.
|
||||
/mob/proc/update_worn_mask()
|
||||
|
||||
@@ -298,7 +298,7 @@
|
||||
regenerate_icons()
|
||||
icon = null
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
var/mob/living/simple_animal/hostile/gorilla/new_gorilla = new (get_turf(src))
|
||||
var/mob/living/basic/gorilla/new_gorilla = new (get_turf(src))
|
||||
new_gorilla.set_combat_mode(TRUE)
|
||||
if(mind)
|
||||
mind.transfer_to(new_gorilla)
|
||||
|
||||
@@ -14,14 +14,18 @@
|
||||
invocation_type = INVOCATION_SHOUT
|
||||
|
||||
summon_radius = 2
|
||||
summon_type = list(/mob/living/carbon/human/species/monkey/angry, /mob/living/carbon/human/species/monkey/angry, /mob/living/simple_animal/hostile/gorilla/lesser)
|
||||
summon_type = list(
|
||||
/mob/living/basic/gorilla/lesser,
|
||||
/mob/living/carbon/human/species/monkey/angry,
|
||||
/mob/living/carbon/human/species/monkey/angry, // Listed twice so it's twice as likely, this class doesn't use pick weight
|
||||
)
|
||||
summon_amount = 4
|
||||
|
||||
/datum/action/cooldown/spell/conjure/simian/level_spell(bypass_cap)
|
||||
. = ..()
|
||||
summon_amount++ // MORE, MOOOOORE
|
||||
if(spell_level == spell_max_level) // We reward the faithful.
|
||||
summon_type = list(/mob/living/carbon/human/species/monkey/angry, /mob/living/simple_animal/hostile/gorilla)
|
||||
summon_type = list(/mob/living/carbon/human/species/monkey/angry, /mob/living/basic/gorilla)
|
||||
spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC // Max level lets you cast it naked, for monkey larp.
|
||||
to_chat(owner, span_notice("Your simian power has reached maximum capacity! You can now cast this spell naked, and you will create adult Gorillas with each cast."))
|
||||
|
||||
|
||||
@@ -86,9 +86,6 @@
|
||||
/mob/living/simple_animal/hostile/construct/wraith/mystic,
|
||||
/mob/living/simple_animal/hostile/construct/wraith/noncult,
|
||||
/mob/living/simple_animal/hostile/dark_wizard,
|
||||
/mob/living/simple_animal/hostile/gorilla,
|
||||
/mob/living/simple_animal/hostile/gorilla/lesser,
|
||||
/mob/living/simple_animal/hostile/gorilla/cargo_domestic,
|
||||
/mob/living/simple_animal/hostile/guardian,
|
||||
/mob/living/simple_animal/hostile/guardian/assassin,
|
||||
/mob/living/simple_animal/hostile/guardian/charger,
|
||||
|
||||
@@ -37,3 +37,4 @@ To defeat the slaughter demon, shoot at it until it dies.
|
||||
When a round ends nearly everything about it is lost forever, leave your salt behind with it.
|
||||
You can win a pulse rifle from the arcade machine. Honest.
|
||||
Your sprite represents your hitbox, so that afro makes you easier to kill. The sacrifices we make for style.
|
||||
Gorillas can be killed by land mines placed along forest paths.
|
||||
|
||||
@@ -828,6 +828,7 @@
|
||||
#include "code\datums\ai\basic_mobs\basic_subtrees\move_to_cardinal.dm"
|
||||
#include "code\datums\ai\basic_mobs\basic_subtrees\opportunistic_ventcrawler.dm"
|
||||
#include "code\datums\ai\basic_mobs\basic_subtrees\ranged_skirmish.dm"
|
||||
#include "code\datums\ai\basic_mobs\basic_subtrees\run_emote.dm"
|
||||
#include "code\datums\ai\basic_mobs\basic_subtrees\shapechange_ambush.dm"
|
||||
#include "code\datums\ai\basic_mobs\basic_subtrees\simple_attack_target.dm"
|
||||
#include "code\datums\ai\basic_mobs\basic_subtrees\simple_find_nearest_target_to_flee.dm"
|
||||
@@ -936,6 +937,7 @@
|
||||
#include "code\datums\components\attached_sticker.dm"
|
||||
#include "code\datums\components\aura_healing.dm"
|
||||
#include "code\datums\components\bakeable.dm"
|
||||
#include "code\datums\components\basic_inhands.dm"
|
||||
#include "code\datums\components\basic_mob_attack_telegraph.dm"
|
||||
#include "code\datums\components\basic_ranged_ready_overlay.dm"
|
||||
#include "code\datums\components\beetlejuice.dm"
|
||||
@@ -4381,6 +4383,10 @@
|
||||
#include "code\modules\mob\living\basic\farm_animals\goat\_goat.dm"
|
||||
#include "code\modules\mob\living\basic\farm_animals\goat\goat_ai.dm"
|
||||
#include "code\modules\mob\living\basic\farm_animals\goat\goat_subtypes.dm"
|
||||
#include "code\modules\mob\living\basic\farm_animals\gorilla\gorilla.dm"
|
||||
#include "code\modules\mob\living\basic\farm_animals\gorilla\gorilla_accessories.dm"
|
||||
#include "code\modules\mob\living\basic\farm_animals\gorilla\gorilla_ai.dm"
|
||||
#include "code\modules\mob\living\basic\farm_animals\gorilla\gorilla_emotes.dm"
|
||||
#include "code\modules\mob\living\basic\heretic\ash_spirit.dm"
|
||||
#include "code\modules\mob\living\basic\heretic\fire_shark.dm"
|
||||
#include "code\modules\mob\living\basic\heretic\flesh_stalker.dm"
|
||||
@@ -4747,9 +4753,6 @@
|
||||
#include "code\modules\mob\living\simple_animal\hostile\constructs\constructs.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\constructs\juggernaut.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\constructs\wraith.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\gorilla\emotes.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\gorilla\gorilla.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\gorilla\visuals_icons.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\jungle\_jungle_mobs.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\jungle\leaper.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\megafauna\_megafauna.dm"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/mob/living/simple_animal/hostile/gorilla/cargo_domestic : /mob/living/basic/gorilla/cargorilla{@OLD}
|
||||
/mob/living/simple_animal/hostile/gorilla : /mob/living/basic/gorilla/@SUBTYPES{@OLD}
|
||||
Reference in New Issue
Block a user