mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-29 02:21:44 +00:00
* Goliath basic mob (#76754) ## About The Pull Request Converts Goliaths to the basic mob framework and gives them some new moves because I can't leave things well enough alone. I am planning on touching all the lavaland fauna and then maybe even the icebox ones if I haven't got bored. The Golaith is the first because it is iconic. https://www.youtube.com/watch?v=JNcKvMwT4-Q Here's me getting killed by one as a demonstration. Despite my poor performance I would contend that they aren't a _lot_ more dangerous, but they are a little more dangerous. The chief difference here is that they have two new attacks which they will only use in response to being attacked. If fired at from range, they will target the attacker with a line of tentacles (it doesn't track you, so is easily sidestepped). If attacked in melee, they will surround _themselves_ with tentacles, on a longer cooldown. Something else you may notice in this video: I discovered that basic mobs are actually _too smart_ to be Lavaland fauna. Typically (unlike their old form) a mob on our new AI system is smart enough to attack someone _the moment they come into range_ rather than only checking on predictable ticks, which would make using the Crusher an essentially unviable prospect. To counteract this, Goliaths now have a delayed attack component which gives you a visual warning and short duration to get out of range before they swing at you. I will probably put this on all mining fauna that get reworked, it wouldn't be a terrible thing to put on other mobs to be honest. Other changes: The goliath stun is now a status effect with _buckles_ you to the tentacle as if grabbed, as well as its previous effects. While this seems purely worse, any nearby helpers can now help-click on you to instantly remove the debuff. Experiencing the effect of a Lobstrosity Rush Gland makes you immune to being grabbed by tentacles and an implanted one will automatically trigger and free you if you are hit, and the explosive effect of Brimdust also causes the tentacle to retract (although you'd need to take damage for this to happen). Using the tools of the land, you can make these creatures less threatening. The ability for a Goliath to chain-apply the ability has now also been reduced, it won't refresh its duration if you are hit when already buckled. When not occupied hounding miners, Goliaths will intermittently dig up the asteroid sand and eat any worms that this produces. I also made some new sprites for riding a Goliath because they've been broken since the Lavaland mob update and also kind of were ugly before then anyway:  Other code changes: - I made an element which only lets an attached object move every x seconds. This is because Goliaths are far too slow to use the speed system (the glide just looks bugged as hell) but one thing I am invested in when converting these is to make sure that they share the same behaviour when player or AI controlled. This is disabled while you're riding them because it was interminably slow. - The Goliath tentacle trail uses a supertype object now shared with the Meteor Heart which did something kind of similar. ## Why It's Good For The Game It begins the process of moving one of our larger subsets of NPCs onto the newer framework for NPC behaviour. It adds a little bit more life to an iconic but slightly uninteresting foe which mostly just walked at you slowly. This PR contains a few components I expect to apply more widely to other mobs in the future. ## Changelog 🆑 refactor: Goliaths now use the Basic Mob framework, please report any unusual behaviour. add: Goliaths learned a couple of new attacks which they will use in self-defence. balance: Help-clicking a miner grabbed by Goliath tentacles will immediately free them, as will the effect of several items you can scavenge from around Lavaland. image: New sprites for the Goliath saddle. /🆑 * Goliath basic mob * Update ash_rituals.dm * fixes icon diff --------- Co-authored-by: Jacquerel <hnevard@gmail.com> Co-authored-by: Pinta <68373373+softcerv@users.noreply.github.com> Co-authored-by: Giz <vinylspiders@gmail.com>
183 lines
7.3 KiB
Plaintext
183 lines
7.3 KiB
Plaintext
/datum/map_generator/cave_generator
|
|
var/name = "Cave Generator"
|
|
///Weighted list of the types that spawns if the turf is open
|
|
var/weighted_open_turf_types = list(/turf/open/misc/asteroid/airless = 1)
|
|
///Expanded list of the types that spawns if the turf is open
|
|
var/open_turf_types
|
|
///Weighted list of the types that spawns if the turf is closed
|
|
var/weighted_closed_turf_types = list(/turf/closed/mineral/random = 1)
|
|
///Expanded list of the types that spawns if the turf is closed
|
|
var/closed_turf_types
|
|
|
|
|
|
///Weighted list of mobs that can spawn in the area.
|
|
var/list/weighted_mob_spawn_list
|
|
///Expanded list of mobs that can spawn in the area. Reads from the weighted list
|
|
var/list/mob_spawn_list
|
|
///The mob spawn list but with no megafauna markers. autogenerated
|
|
var/list/mob_spawn_no_mega_list
|
|
// Weighted list of Megafauna that can spawn in the area
|
|
var/list/weighted_megafauna_spawn_list
|
|
///Expanded list of Megafauna that can spawn in the area. Reads from the weighted list
|
|
var/list/megafauna_spawn_list
|
|
///Weighted list of flora that can spawn in the area.
|
|
var/list/weighted_flora_spawn_list
|
|
///Expanded list of flora that can spawn in the area. Reads from the weighted list
|
|
var/list/flora_spawn_list
|
|
///Weighted list of extra features that can spawn in the area, such as geysers.
|
|
var/list/weighted_feature_spawn_list
|
|
///Expanded list of extra features that can spawn in the area. Reads from the weighted list
|
|
var/list/feature_spawn_list
|
|
|
|
|
|
///Base chance of spawning a mob
|
|
var/mob_spawn_chance = 6
|
|
///Base chance of spawning flora
|
|
var/flora_spawn_chance = 2
|
|
///Base chance of spawning features
|
|
var/feature_spawn_chance = 0.15
|
|
///Unique ID for this spawner
|
|
var/string_gen
|
|
|
|
///Chance of cells starting closed
|
|
var/initial_closed_chance = 45
|
|
///Amount of smoothing iterations
|
|
var/smoothing_iterations = 20
|
|
///How much neighbours does a dead cell need to become alive
|
|
var/birth_limit = 4
|
|
///How little neighbours does a alive cell need to die
|
|
var/death_limit = 3
|
|
|
|
/datum/map_generator/cave_generator/New()
|
|
. = ..()
|
|
if(!weighted_mob_spawn_list)
|
|
weighted_mob_spawn_list = list(
|
|
/mob/living/basic/mining/goliath/ancient = 5,
|
|
/mob/living/simple_animal/hostile/asteroid/basilisk = 4,
|
|
/mob/living/simple_animal/hostile/asteroid/hivelord = 3,
|
|
/mob/living/simple_animal/hostile/asteroid/goldgrub = 1,
|
|
)
|
|
mob_spawn_list = expand_weights(weighted_mob_spawn_list)
|
|
mob_spawn_no_mega_list = expand_weights(weighted_mob_spawn_list - SPAWN_MEGAFAUNA)
|
|
if(!weighted_megafauna_spawn_list)
|
|
weighted_megafauna_spawn_list = GLOB.megafauna_spawn_list
|
|
megafauna_spawn_list = expand_weights(weighted_megafauna_spawn_list)
|
|
if(!weighted_flora_spawn_list)
|
|
weighted_flora_spawn_list = list(
|
|
/obj/structure/flora/ash/leaf_shroom = 2,
|
|
/obj/structure/flora/ash/cap_shroom = 2,
|
|
/obj/structure/flora/ash/stem_shroom = 2,
|
|
/obj/structure/flora/ash/cacti = 1,
|
|
/obj/structure/flora/ash/tall_shroom = 2,
|
|
/obj/structure/flora/ash/seraka = 2,
|
|
)
|
|
flora_spawn_list = expand_weights(weighted_flora_spawn_list)
|
|
if(!weighted_feature_spawn_list)
|
|
weighted_feature_spawn_list = list(/obj/structure/geyser/random = 1)
|
|
feature_spawn_list = expand_weights(weighted_feature_spawn_list)
|
|
open_turf_types = expand_weights(weighted_open_turf_types)
|
|
closed_turf_types = expand_weights(weighted_closed_turf_types)
|
|
|
|
|
|
/datum/map_generator/cave_generator/generate_terrain(list/turfs, area/generate_in)
|
|
. = ..()
|
|
if(!(generate_in.area_flags & CAVES_ALLOWED))
|
|
return
|
|
|
|
var/start_time = REALTIMEOFDAY
|
|
string_gen = rustg_cnoise_generate("[initial_closed_chance]", "[smoothing_iterations]", "[birth_limit]", "[death_limit]", "[world.maxx]", "[world.maxy]") //Generate the raw CA data
|
|
|
|
// Area var pullouts to make accessing in the loop faster
|
|
var/flora_allowed = (generate_in.area_flags & FLORA_ALLOWED) && length(flora_spawn_list)
|
|
var/feature_allowed = (generate_in.area_flags & FLORA_ALLOWED) && length(feature_spawn_list)
|
|
var/mobs_allowed = (generate_in.area_flags & MOB_SPAWN_ALLOWED) && length(mob_spawn_list)
|
|
var/megas_allowed = (generate_in.area_flags & MEGAFAUNA_SPAWN_ALLOWED) && length(megafauna_spawn_list)
|
|
|
|
for(var/i in turfs) //Go through all the turfs and generate them
|
|
var/turf/gen_turf = i
|
|
//SKYRAT EDIT ADDITION
|
|
if(istype(gen_turf, /turf/open/space/mirage))
|
|
continue
|
|
//SKYRAT EDIT END
|
|
|
|
var/closed = string_gen[world.maxx * (gen_turf.y - 1) + gen_turf.x] != "0"
|
|
var/turf/new_turf = pick(closed ? closed_turf_types : open_turf_types)
|
|
|
|
// The assumption is this will be faster then changeturf, and changeturf isn't required since by this point
|
|
// The old tile hasn't got the chance to init yet
|
|
new_turf = new new_turf(gen_turf)
|
|
|
|
if(gen_turf.turf_flags & NO_RUINS)
|
|
new_turf.turf_flags |= NO_RUINS
|
|
|
|
if(closed)//Open turfs have some special behavior related to spawning flora and mobs.
|
|
CHECK_TICK
|
|
continue
|
|
|
|
// If we've spawned something yet
|
|
var/spawned_something = FALSE
|
|
|
|
///Spawning isn't done in procs to save on overhead on the 60k turfs we're going through.
|
|
//FLORA SPAWNING HERE
|
|
if(flora_allowed && prob(flora_spawn_chance))
|
|
var/flora_type = pick(flora_spawn_list)
|
|
new flora_type(new_turf)
|
|
spawned_something = TRUE
|
|
|
|
//FEATURE SPAWNING HERE
|
|
if(feature_allowed && prob(feature_spawn_chance))
|
|
var/can_spawn = TRUE
|
|
|
|
var/atom/picked_feature = pick(feature_spawn_list)
|
|
|
|
for(var/obj/structure/existing_feature in range(7, new_turf))
|
|
if(istype(existing_feature, picked_feature))
|
|
can_spawn = FALSE
|
|
break
|
|
|
|
if(can_spawn)
|
|
new picked_feature(new_turf)
|
|
spawned_something = TRUE
|
|
|
|
//MOB SPAWNING HERE
|
|
if(mobs_allowed && !spawned_something && prob(mob_spawn_chance))
|
|
var/atom/picked_mob = pick(mob_spawn_list)
|
|
|
|
if(picked_mob == SPAWN_MEGAFAUNA)
|
|
if(megas_allowed) //this is danger. it's boss time.
|
|
picked_mob = pick(megafauna_spawn_list)
|
|
else //this is not danger, don't spawn a boss, spawn something else
|
|
picked_mob = pick(mob_spawn_no_mega_list) //What if we used 100% of the brain...and did something (slightly) less shit than a while loop?
|
|
|
|
var/can_spawn = TRUE
|
|
|
|
// prevents tendrils spawning in each other's collapse range
|
|
if(ispath(picked_mob, /obj/structure/spawner/lavaland))
|
|
for(var/obj/structure/spawner/lavaland/spawn_blocker in range(2, new_turf))
|
|
can_spawn = FALSE
|
|
break
|
|
//if the random is a standard mob, avoid spawning if there's another one within 12 tiles
|
|
else if(isminingpath(picked_mob))
|
|
for(var/mob/living/mob_blocker in range(12, new_turf))
|
|
if(ismining(mob_blocker))
|
|
can_spawn = FALSE
|
|
break
|
|
//if there's a megafauna within standard view don't spawn anything at all (This isn't really consistent, I don't know why we do this. you do you tho)
|
|
if(can_spawn)
|
|
for(var/mob/living/simple_animal/hostile/megafauna/found_fauna in range(7, new_turf))
|
|
can_spawn = FALSE
|
|
break
|
|
|
|
if(can_spawn)
|
|
if(ispath(picked_mob, /mob/living/simple_animal/hostile/megafauna/bubblegum)) //there can be only one bubblegum, so don't waste spawns on it
|
|
weighted_megafauna_spawn_list.Remove(picked_mob)
|
|
megafauna_spawn_list = expand_weights(weighted_megafauna_spawn_list)
|
|
megas_allowed = megas_allowed && length(megafauna_spawn_list)
|
|
new picked_mob(new_turf)
|
|
spawned_something = TRUE
|
|
CHECK_TICK
|
|
|
|
var/message = "[name] finished in [(REALTIMEOFDAY - start_time)/10]s!"
|
|
add_startup_message(message) //SKYRAT EDIT CHANGE
|
|
log_world(message)
|