Skip to content

Commit

Permalink
refactors poles and trees into basic mobs (tgstation#74812)
Browse files Browse the repository at this point in the history
## About The Pull Request
refactors poles and trees into basic mobs. If trees now see you holding
a chainsaw, hatchet, or some wood they will get angry and knock you out
for longer. Poles will run around giving some of their charge to APCs
they find along the way. i did them both in this PR coz poles were a
subtype of trees.

## Why It's Good For The Game
refactor

## Changelog
:cl:
refactor: refactors trees into basic mobs
refactor: refactors poles into basic mobs
add: If trees now see you holding a chainsaw, hatchet, or some wood they
will get angry and knock you out for longer
add: Poles will run around giving some of their charge to APCs they find
along the way
fix: cells charged by the pole will now have their icon correctly
updated to reflect their charge
/:cl:

---------

Co-authored-by: Mothblocks <[email protected]>
  • Loading branch information
SMOSMOSMOSMOSMO and Mothblocks authored Apr 19, 2023
1 parent 0aa744c commit f3f274d
Show file tree
Hide file tree
Showing 13 changed files with 272 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
},
/area/ruin/powered/shuttle)
"qd" = (
/mob/living/simple_animal/hostile/tree,
/mob/living/basic/tree,
/turf/open/misc/asteroid/snow/icemoon,
/area/icemoon/surface/outdoors/nospawn)
"sF" = (
Expand Down
5 changes: 2 additions & 3 deletions _maps/RandomZLevels/SnowCabin.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -3793,10 +3793,9 @@
/turf/open/floor/carpet,
/area/awaymission/cabin)
"xs" = (
/mob/living/simple_animal/hostile/tree{
/mob/living/basic/tree{
desc = "I am death. I will have my vengeance upon my enemies.";
melee_damage_upper = 8;
wander = 0
melee_damage_upper = 8
},
/turf/open/misc/asteroid/snow/snow_cabin,
/area/awaymission/cabin/snowforest)
Expand Down
4 changes: 4 additions & 0 deletions code/__DEFINES/ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -275,3 +275,7 @@
// Fugu AI keys
/// Key where we store the inflating ability
#define BB_FUGU_INFLATE "BB_fugu_inflate"

//Festivus AI keys
/// Key where we store the charging apc ability
#define BB_FESTIVE_APC "BB_festive_apc"
19 changes: 19 additions & 0 deletions code/datums/actions/mobs/charge_apc.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/datum/action/cooldown/mob_cooldown/charge_apc
name = "Charge APCs"
button_icon = 'icons/obj/power.dmi'
button_icon_state = "apc0"
desc = "Give off charge to an APC."
cooldown_time = 5 SECONDS
///how much charge are we giving off to an APC?
var/given_charge = 80

/datum/action/cooldown/mob_cooldown/charge_apc/Activate(atom/target_atom)
if(!istype(target_atom,/obj/machinery/power/apc))
return
var/obj/machinery/power/apc/target_apc = target_atom
if(!target_apc.cell)
return
new /obj/effect/particle_effect/sparks(target_apc.loc)
target_apc.cell.give(given_charge)
StartCooldown()
return TRUE
4 changes: 4 additions & 0 deletions code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,7 @@
speak = list("Gnot a gnelf!", "Gnot a gnoblin!", "Howdy chum!")
emote_hear = list("snores.", "burps.")
emote_see = list("blinks.")

/datum/ai_planning_subtree/random_speech/tree
speech_chance = 3
emote_see = list("photosynthesizes angirly.")
4 changes: 2 additions & 2 deletions code/modules/hydroponics/hydroponics.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1130,9 +1130,9 @@
* Upon using strange reagent on a tray, it will spawn a killer tomato or killer tree at random.
*/
/obj/machinery/hydroponics/proc/spawnplant() // why would you put strange reagent in a hydro tray you monster I bet you also feed them blood
var/list/livingplants = list(/mob/living/simple_animal/hostile/tree, /mob/living/simple_animal/hostile/killertomato)
var/list/livingplants = list(/mob/living/basic/tree, /mob/living/simple_animal/hostile/killertomato)
var/chosen = pick(livingplants)
var/mob/living/simple_animal/hostile/C = new chosen(get_turf(src))
var/mob/living/C = new chosen(get_turf(src))
C.faction = list(FACTION_PLANTS)

///////////////////////////////////////////////////////////////////////////////
Expand Down
119 changes: 119 additions & 0 deletions code/modules/mob/living/basic/festivus_pole.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/mob/living/basic/festivus
name = "festivus pole"
desc = "Serenity now... SERENITY NOW!"
icon = 'icons/obj/flora/pinetrees.dmi'
icon_state = "festivus_pole"
icon_living = "festivus_pole"
icon_dead = "festivus_pole"
icon_gib = "festivus_pole"
health_doll_icon = "festivus_pole"
gender = NEUTER
gold_core_spawnable = HOSTILE_SPAWN
basic_mob_flags = DEL_ON_DEATH

response_help_continuous = "rubs"
response_help_simple = "rub"
response_disarm_continuous = "pushes"
response_disarm_simple = "push"

mob_size = MOB_SIZE_LARGE
pixel_x = -16
base_pixel_x = -16

speed = 1
maxHealth = 200
health = 200
melee_damage_lower = 8
melee_damage_upper = 12
attack_verb_continuous = "bites"
attack_verb_simple = "bite"
attack_sound = 'sound/weapons/bite.ogg'
attack_vis_effect = ATTACK_EFFECT_BITE

faction = list(FACTION_HOSTILE)
speak_emote = list("polls")

death_message = "is hacked into pieces!"

ai_controller = /datum/ai_controller/basic_controller/festivus_pole

///how much charge we give off to cells around us when rubbed
var/recharge_value = 75

/mob/living/basic/festivus/Initialize(mapload)
. = ..()
AddElement(/datum/element/death_drops, list(/obj/item/stack/rods))
var/datum/action/cooldown/mob_cooldown/charge_apc/charge_ability = new(src)
charge_ability.Grant(src)
ai_controller.blackboard[BB_FESTIVE_APC] = WEAKREF(charge_ability)

/datum/ai_controller/basic_controller/festivus_pole
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(),
BB_LOW_PRIORITY_HUNTING_TARGET = null, // APCs
)

ai_movement = /datum/ai_movement/basic_avoidance
idle_behavior = /datum/idle_behavior/idle_random_walk/less_walking
planning_subtrees = list(
/datum/ai_planning_subtree/find_and_hunt_target/look_for_apcs,
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/basic_melee_attack_subtree,
)

/mob/living/basic/festivus/attack_hand(mob/living/carbon/human/user, list/modifiers)
. = ..()
if(user.combat_mode)
return
visible_message(span_warning("[src] crackles with static electricity!"))
for(var/atom/affected in range(2, get_turf(src)))
if(istype(affected, /obj/item/stock_parts/cell))
var/obj/item/stock_parts/cell/cell = affected
cell.give(recharge_value)
cell.update_appearance()
if(istype(affected, /mob/living/silicon/robot))
var/mob/living/silicon/robot/robot = affected
if(robot.cell)
robot.cell.give(recharge_value)
if(istype(affected, /obj/machinery/power/apc))
var/obj/machinery/power/apc/apc_target = affected
if(apc_target.cell)
apc_target.cell.give(recharge_value)

/datum/ai_planning_subtree/find_and_hunt_target/look_for_apcs
hunting_behavior = /datum/ai_behavior/hunt_target/apcs
hunt_targets = list(/obj/machinery/power/apc)
hunt_range = 6


/datum/ai_planning_subtree/find_and_hunt_target/look_for_apcs
target_key = BB_LOW_PRIORITY_HUNTING_TARGET
finding_behavior = /datum/ai_behavior/find_hunt_target/apcs
hunting_behavior = /datum/ai_behavior/hunt_target/apcs
hunt_targets = list(/obj/machinery/power/apc)
hunt_range = 6

/datum/ai_behavior/hunt_target/apcs
hunt_cooldown = 15 SECONDS
always_reset_target = TRUE

/datum/ai_behavior/hunt_target/apcs/target_caught(mob/living/basic/hunter, obj/machinery/power/apc/hunted)
var/datum/weakref/ability_weakref = hunter.ai_controller.blackboard[BB_FESTIVE_APC]
var/datum/action/cooldown/mob_cooldown/charge_ability = ability_weakref?.resolve()
if(isnull(charge_ability))
return
charge_ability.Activate(hunted)


/datum/ai_behavior/find_hunt_target/apcs

/datum/ai_behavior/find_hunt_target/apcs/valid_dinner(mob/living/source, obj/machinery/power/apc/dinner, radius)
if(istype(dinner, /obj/machinery/power/apc))
var/obj/machinery/power/apc/apc_target = dinner
if(!apc_target.cell)
return FALSE
var/obj/item/stock_parts/cell/apc_cell = apc_target.cell
if(apc_cell.charge == apc_cell.maxcharge) //if its full charge we no longer feed it
return FALSE

return can_see(source, dinner, radius)
115 changes: 115 additions & 0 deletions code/modules/mob/living/basic/tree.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/mob/living/basic/tree
name = "pine tree"
desc = "A pissed off tree-like alien. It seems annoyed with the festivities..."
icon = 'icons/obj/flora/pinetrees.dmi'
icon_state = "pine_1"
icon_living = "pine_1"
icon_dead = "pine_1"
icon_gib = "pine_1"
health_doll_icon = "pine_1"
mob_biotypes = MOB_ORGANIC | MOB_PLANT
gender = NEUTER
gold_core_spawnable = HOSTILE_SPAWN
basic_mob_flags = DEL_ON_DEATH

response_help_continuous = "brushes"
response_help_simple = "brush"
response_disarm_continuous = "pushes"
response_disarm_simple = "push"

mob_size = MOB_SIZE_LARGE
pixel_x = -16
base_pixel_x = -16

speed = 1
maxHealth = 250
health = 250
melee_damage_lower = 8
melee_damage_upper = 12
attack_verb_continuous = "bites"
attack_verb_simple = "bite"
attack_sound = 'sound/weapons/bite.ogg'
attack_vis_effect = ATTACK_EFFECT_BITE

faction = list(FACTION_HOSTILE)
speak_emote = list("pines")

habitable_atmos = list("min_oxy" = 2, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 2.5
minimum_survivable_temperature = 0
maximum_survivable_temperature = 1200

death_message = "is hacked into pieces!"

ai_controller = /datum/ai_controller/basic_controller/tree

///items that make us angry
var/list/infuriating_objects = list(/obj/item/chainsaw, /obj/item/hatchet, /obj/item/stack/sheet/mineral/wood)
///chance of target getting paralyzed
var/paralyze_prob = 15
///for how the target is paralyzed
var/paralyze_value = 5 SECONDS
///Additional paralyze chance
var/anger_boost = 50

/mob/living/basic/tree/Initialize(mapload)
. = ..()
AddElement(/datum/element/swabable, CELL_LINE_TABLE_PINE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5)
AddElement(/datum/element/death_drops, list(/obj/item/stack/sheet/mineral/wood))

/mob/living/basic/tree/Life(seconds_per_tick = SSMOBS_DT, times_fired)
..()
if(!isopenturf(loc))
return
var/turf/open/our_turf = src.loc
if(!our_turf.air || !our_turf.air.gases[/datum/gas/carbon_dioxide])
return

var/co2 = our_turf.air.gases[/datum/gas/carbon_dioxide][MOLES]
if(co2 > 0 && SPT_PROB(13, seconds_per_tick))
var/amt = min(co2, 9)
our_turf.air.gases[/datum/gas/carbon_dioxide][MOLES] -= amt
our_turf.atmos_spawn_air("o2=[amt]")

/mob/living/basic/tree/melee_attack(atom/target, list/modifiers)
. = ..()

if(!.)
return

if(!isliving(target))
return

var/mob/living/victim = target
var/boost = 0
if(iscarbon(victim))
for(var/item_path in infuriating_objects)
if(locate(item_path) in victim.held_items)
boost = anger_boost
break

if(prob(paralyze_prob + boost))
victim.Paralyze(paralyze_value + boost)
victim.visible_message(
span_danger("[src] knocks down [victim]!"),
span_userdanger("[src] knocks you down!"),
)

/datum/ai_controller/basic_controller/tree
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(),
)

ai_movement = /datum/ai_movement/basic_avoidance
idle_behavior = /datum/idle_behavior/idle_random_walk/less_walking
planning_subtrees = list(
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/basic_melee_attack_subtree/tree,
/datum/ai_planning_subtree/random_speech/tree,
)

/datum/ai_planning_subtree/basic_melee_attack_subtree/tree
melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/tree

/datum/ai_behavior/basic_melee_attack/tree
action_cooldown = 2 SECONDS
Loading

0 comments on commit f3f274d

Please sign in to comment.