Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DONE] Carrion monster spawning #23774

Merged
merged 21 commits into from Jun 13, 2018

Conversation

8 participants
@acidia
Copy link
Contributor

commented May 19, 2018

Fairly straightforward, when a comestible rots away it has a small chance of spawning a creature.
Food (currently just meat, tainted meat, wild vegetables, eggs, and a couple others) has two new stats:
"rot_spawn": "GROUP_CARRION_INFECTED",
"rot_spawn_chance": 15,
Name the monster group that is spawning and set the spawn rate (default to 10% if not listed). There is also a world spawn chance that is defaulted to 100%. The two numbers are multiplied to generate the overall chance that a monster will spawn. So if there is a monster that has a 200% spawning rate it will still spawn 100% of the time at 50% global carrion spawns.

The issue emerged with the factories in #23748, where a giant factory full of rotting food was still a nice place to visit a week into the cataclysm. The monsters spawning are generally vermin that don't pose a threat but I'll see about getting a more general maturation than what we currently have so plague nymphs (infected meat eating roaches)->plague vectors/giant roaches which we can make damage food items they step on.

For wilderness runs, this gives static bases something to manage. Bird eggs can be let to rot to try your chances of spawning a chick (takes a year currently and runs ~60% chance) or triffid farming if you figure out what triffid sprigs like spawning on.

acidia added some commits May 17, 2018

Added CARRION spawn to most common rotten items
+eggs to demonstrate chicks ~1yr later
+triffid favorite food, for eventual triffid farming
src/map.cpp Outdated
it = i_rem( pnt, it );
} else {
++it;
}
}
}

template <typename Item>
void map::rotten_item_spawn( Item &item, const tripoint &pnt )

This comment has been minimized.

Copy link
@BevapDin

BevapDin May 19, 2018

Contributor

Why is this a function template? I guess it's because item is not really an item, but an iterator into a std::list<item> (which explains why it's dereferenced on every access even through it is a reference).

Change the function to take an actual item reference (and make it a reference to a const item as the function does not modify the item) and call it as rotten_item_spawn( *it, ... ).

src/map.cpp Outdated
@@ -6726,13 +6727,38 @@ void map::remove_rotten_items( Container &items, const tripoint &pnt )
const tripoint abs_pnt = getabs( pnt );
for( auto it = items.begin(); it != items.end(); ) {
if( has_rotten_away( *it, abs_pnt ) ) {
//If the item that is rotting is a food item, see if we can spawn a monster

This comment has been minimized.

Copy link
@BevapDin

BevapDin May 19, 2018

Contributor

Why do you feel the need to repeat the code as comment. "if the item ... is a food item" is the same as if(it->is_comestible()) {.

src/itype.h Outdated
@@ -166,6 +166,11 @@ struct islot_comestible
int get_calories() const {
return nutr * kcal_per_nutr;
}
/** The monster group that is drawn from when the item rots away */
std::string rot_spawn = "null";

This comment has been minimized.

Copy link
@BevapDin

BevapDin May 19, 2018

Contributor

Please change this to be of mongroup_id type. It's not a simple string, it's the id of an monster group. Don't create the mongroup_id when calling MonsterGroupManager::GetResultFromGroup because the compiler complains there. Create it as soon as possible.

Also would be nice to add a consitency check for this id in "item_factory.cpp" (so an invalid id is reported when the game loads, not when the id is actually used). For this it would be nice to use mongroup_id::NULL_ID() instead of "null" as the default value (which is "GROUP_NULL"), also for consistency with other monster group related code.

src/map.cpp Outdated
chance *= get_option<int>( "CARRION_SPAWNRATE" )/100;
if (rng(0, 100) < chance){
MonsterGroupResult spawn_details = MonsterGroupManager::GetResultFromGroup(mongroup_id(mgroup));
if( g->critter_at( pnt ) == nullptr ) {

This comment has been minimized.

Copy link
@BevapDin

BevapDin May 19, 2018

Contributor

This should probably be checked first as all the other stuff is pointless when this turns out to be false.

Also consider using early returns instead of that many levels of intendation,e g.

if( some_is_wrong ) {
    return;
}
do_something();
if( some_else_is_wrong ) {
    return;
}
do_something_more();

Instead of

if( !some_is_wrong ) {
    do_something();
    if( !some_else_is_wrong ) {
        do_something_more();
    }
}
src/map.cpp Outdated
std::string mgroup = comest->rot_spawn;
if ( mgroup != "null" ) {
int chance = comest->rot_spawn_chance;
chance *= get_option<int>( "CARRION_SPAWNRATE" )/100;

This comment has been minimized.

Copy link
@BevapDin

BevapDin May 19, 2018

Contributor

Those two lines can be combined into one. In fact, they should be because currently any value of "CARRION_SPAWNRATE" below 100 will set the chance to 0: get_option<int> returns an int and 100 is an int as well, so the division is done as integer division (e.g. 80/100 == 0) and the multiplication is only done after that.

I suggest this: const int chance = ( rot_spawn_chance * get_option ) / 100;

if( jo.has_string( "rot_spawn" ) ) {
slot.rot_spawn = jo.get_string( "rot_spawn" );
}
if( jo.has_string( "rot_spawn_chance" ) ) {

This comment has been minimized.

Copy link
@BevapDin

BevapDin May 19, 2018

Contributor

If you use assign to load the value, you don't need to check for existance of that member. assign will handle that case on its own (and do nothing).

This comment has been minimized.

Copy link
@acidia

acidia May 19, 2018

Author Contributor

Thanks! I think I got all of your changes.

@BorkBorkGoesTheCode

This comment has been minimized.

Copy link
Contributor

commented May 19, 2018

Have you considered extending it to make human meat resurrect into zombies?

acidia added some commits May 19, 2018

@acidia

This comment has been minimized.

Copy link
Contributor Author

commented May 19, 2018

I figured human meat wouldn't become zombies but making human corpses rot into zombies makes sense. Corpses are handled differently from comestibles, I think all corpses inherit from a single json item, so you'd be changing the creature entry instead of the item. Certainly possible but isn't worth the work with so few NPCs generally.

@Night-Pryanik

This comment has been minimized.

Copy link
Member

commented May 20, 2018

Could you please describe what monsters you've added, what features they have etc?

@FulcrumA

This comment has been minimized.

Copy link
Contributor

commented May 20, 2018

@acidia
Lore-wise it's be probably even preferable for fresh corpses to become zombies, but [redacted] takes what it can and tries to make it work as soon as possible - it just still takes time.

Other than that I really like this idea, even as actual way to hunt - drawing carrion beasts to prepared corpse, hiding and then, for example, shooting down vultures for their own meat, bones and feathers.

@acidia

This comment has been minimized.

Copy link
Contributor Author

commented May 20, 2018

Sure, general thoughts on monsters:

Roaches are already in and they aren't that bad., They typically allow combat with the player immediately so a roach infestation isn't something a brave melee survivor can't deal with in an hour. I'm thinking about giving these guys a food damaging attack so if you trow all of your perishable and non-perishable food in a shed you might find it all gone if you let things rot. The main spawn for clean rotting meat/veg.

Plague nymph/skittering/vector animals nasty enough to think it was a good idea to start eating zombie meat. Think of them as post threshold mutants since they are still kinda roaches. These guys are bad because they avoid combat with the player until you are either too weak to fight or they grow to become vectors and can bring the fight to you. In combat they are faster than normal roach and will have an extremely infectious bite but have about half the HP. Game play wise, see about these guys eating grass/trees/crops with their special to turn infested areas into wasteland. If infestations truly become something the player can't deal with, in a bad way, we can always make temps below 0 drop their move to 1/4. Main spawn for tainted meat.

Triffid Sprig, the "favorable" spawn for intentional carrion farming. Little guys that obviously turn into triffids eventually. My thoughts were setting them on roughly a 1yr life cycle from sprouting->young triffid->triffid. Goal would be to not have adult triffids reproduce but instead have their seeds dispersed into the wind... making favorable "planting"/carrion conditions the best way to get them. Easy for you to kill, or the other carrion spawns. You might have to use small batches of carrion or their preferred carrion to ensure you actual keep them. Minor spawn for clean meat.

Chicken chick, like chicken but smaller and less capable. Currently it takes a year (2x rot time) for bird eggs to start hatching but that should probably be halved. Spawns from wild eggs at the moment because I didn't want to make a shit ton of baby animals in the engine change PR.

src/itype.h Outdated
@@ -14,6 +14,7 @@
#include "damage.h"
#include "translations.h"
#include "calendar.h"
#include "mongroup.h"

This comment has been minimized.

Copy link
@BevapDin

BevapDin May 20, 2018

Contributor

This is not needed. A forward declaration of MonsterGroup and the typedef of mongroup_id is enough (see "map.h" for how it's done).

@FulcrumA

This comment has been minimized.

Copy link
Contributor

commented May 21, 2018

I was thinking about it and would like to ask - shouldn't spawn of such scavengers be limited by certain storage methods? I'd reckon spawning of such things in buildings should be considerably smaller in comaprison with the chance of some scavenger being drawn to food rotting outside. Also, if the food is stored somewhere (locker, crate, other furniture or containers) it should prevent spawn of such creatures in general.

@Zireael07

This comment has been minimized.

Copy link
Contributor

commented May 21, 2018

Rotting stuff in container will bring roaches regardless of the fact that it's in a container.

@acidia

This comment has been minimized.

Copy link
Contributor Author

commented May 21, 2018

It was already handled well enough for me (I don't know how to quote code) but starting at line 6704 of map.cpp has

else if( itm.type->container && itm.type->container->seals ) {
         // Items inside rot but do not vanish as the container seals them in.
        for( auto &c : itm.contents ) {
            c.calc_rot( pnt );
        }
        return false;

So if the container is airtight you won't have to worry about monster spawning because items won't rot away (the stank doesn't escape). Setting it per location would be a bit of a nightmare given how many different overmap and terrain tiles we have. It would be possible to add a multiplier on say t_grass then x2 as likely to spawn carrion but defining all of those is way more than what I need at the moment.
`

@acidia acidia changed the title [TESTING] Carrion monster spawning [DONE] Carrion monster spawning May 24, 2018

@acidia

This comment has been minimized.

Copy link
Contributor Author

commented May 24, 2018

I'm happy enough after a few hours of wilderness play. I'll push a different PR json update for wild eggs shortly, just so things make sense. Chickens will always produce chicken eggs, but a white/brown wild bird egg could be a chicken egg or it could be a turkey/pheasant/duck egg. Eggs shouldn't be immediately obvious who they belong to nor should some chicks... a wild brown chick could be a quail/pheasant, a duckling could be a duck/goose/swan. It'll add some mystery till it grows up.

Balance wise, butchering large numbers of enemies will leave enough tainted meat that carrion spawns are noticeable without altering game-play much yet. It leaves the question of what should be done with pulped corpses, which will never re-spawn into the same creature but should be huge attractions for carrion feeders? I don't want to define a specific carrion spawn group for each monster but zombie dogs spawning on a dead squirrel makes sense while deep in a lab on a pulped zombie corpse doesn't make sense, dogs aren't "vermin" at any point so they shouldn't be everywhere. Should all pulped corpses spawn from a minor to greater jabberwock type corpse amalgamation group?

@FulcrumA

This comment has been minimized.

Copy link
Contributor

commented May 27, 2018

Probably some sort of checks and limits should be introduced, since as things are it seems they may easily spiral out of control. Kill a bunch of things -> lots of scavengers appear -> kill them -> even more things are now dead drawing in even more scavengers.

At some point scavengers may become bigger threat than whatever they were scavenging on. Possibly some way of flagging the overmap tile when scavengers are called in once so it will not call in further attention till a few days pass could help here.

Also, a thing for further consideration - we certainly require more non-hostile scavengers. Black or even more regular rats, vultures etc rather than hordes of dogs and oversized roaches.

@acidia

This comment has been minimized.

Copy link
Contributor Author

commented May 27, 2018

I don't think we'll need any checks until we get a bit more play testing, rotting meat is running about a 15% chance of spawning a tiny vermin (~1 meat) creature so we do have decreasing total biomass in the short term. Vermin will of course grow and breed quickly so you might see total biomass size repopulate in 1-2 seasons, if you visit occasionally, don't clean house, and monster infighting doesn't purge populations. Of course, leaving a giant trail of rotten mutating corpses behind you can and should create a bigger problem than you originally had if you don't deal with it. Fire is the simplest way of cleansing your battle ground.

Certainly going to add more scavengers, I think I had crows spawn on low chances on clean vegetables rotting in the demo jsons. I didn't add rats simply because I didn't think they would utilize the breeding mechanics. Not that they don't breed but I think anything other than an adult rat would be too small to notice. Been trying to keep the carrion spawn group distribution in favor of once species otherwise they will immediately kill each other when they spawn. 5 baby roaches vs 5 young triffids might mean you only see 2 wounded young triffids when you approach. Instead of 3 baby roaches vs 7 young triffids where you find 6 wounded young triffids when you approach. I'd say increasing variety should follow a diversity of different spawn groups instead of diluting spawning in one group.

@acidia

This comment has been minimized.

Copy link
Contributor Author

commented May 27, 2018

Not my call, that is the linter reformatting everything...

@Clyybber
Copy link
Contributor

left a comment

This is great! I would only keep those json entries multiline.
EDIT: Hmmm. Nevermind then if the linter formats it that way. Maybe we should rework the linter.
EDIT2: Somehow I messed up with the github ui and spammed reviews, sorry O_O

"price": 20,
"calories": 0.95
},
"proportional": { "price": 20, "calories": 0.95 },

This comment has been minimized.

Copy link
@Clyybber

Clyybber May 27, 2018

Contributor

I guess its a bit more readable if ywe would keep all these entries multiline.

This comment has been minimized.

Copy link
@acidia

acidia May 27, 2018

Author Contributor

I agree but I'm not sure how to go about changing the linter.

This comment has been minimized.

Copy link
@Clyybber

Clyybber May 27, 2018

Contributor

Yeah, thats a thing for a different PR. I will try to look into it.

@Clyybber Clyybber referenced this pull request May 27, 2018

Closed

More readable json #23869

acidia added some commits May 27, 2018

@acidia

This comment has been minimized.

Copy link
Contributor Author

commented Jun 3, 2018

Added a rotting spawn check when plants grow. This lets me use carrion spawns to spawn locusts or other nuisances any time a plant growth check is made. Seeds don't rot normally so it will only occur for plant growth. Spawning monsters doesn't hurt the plant, the monsters should do that themselves. Probably leave all spawn chances at 1% since it makes the check for each growth stage (three times).

@ZhilkinSerg ZhilkinSerg self-assigned this Jun 13, 2018

@ZhilkinSerg ZhilkinSerg merged commit 22bdc45 into CleverRaven:master Jun 13, 2018

3 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
coverage/coveralls Coverage increased (+0.08%) to 23.556%
Details
gorgon-ghprb Build finished.
Details

@ZhilkinSerg ZhilkinSerg removed their assignment Jun 13, 2018

@DracoGriffin DracoGriffin added this to To do in farming improvements via automation Jul 8, 2018

@DracoGriffin DracoGriffin moved this from To do to Done in farming improvements Jul 8, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.