News:

One Minute Game Review by The Happy Friar: https://ugetube.com/@OneMinteGameReviews
Also on Rumble: https://rumble.com/c/c-1115371

idTech 4 (aka Doom 3 tech) Discord Server! https://discord.gg/9wtCGHa

Main Menu

Random non-encounters?

Started by calan, October 29, 2014, 08:51:26 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

calan

I'm amazed that I can't find a mod to truly randomize the appearance of monsters in D3. I've played around with the settings in sikkmod, and it works well for cramming more monsters into the game. But...  in order to be truly random, the canned/scripted monsters that jump out from their cubby holes need to be randomized as well.

Is there ANYTHING out there that will cause the scripted AI to simply not appear sometimes (most of the times?), and cause random monsters to appear in different places? To me this would be the number one enhancement to extend gameplay.

I have a mod compilation as well as a lot of my own stuff all playing nice together. I just need some maps/scripts/ whatever, without a bunch of other fluff like pink weapons, atomic grenades, etc.  :)

- Craig

P.S. Still loving D3 even after 10 years. I'm amazed at how well it holds up and am thankful for the continuing community!
Old bastard but kid at heart...

The Happy Friar

Not for the stock game, that I'm aware of.

I've done it before with custom maps/mods.

calan

Got any that you'd like to share?  :)

BTW - Thanks for setting up this site!
Old bastard but kid at heart...

The Happy Friar

Don't have much time right now (common theme this month :/ ) but my mod has randomized zombies: http://www.moddb.com/mods/the-happy-friars-last-stand

calan

Is there an easy way to edit a map file, find the monsters, and enter some code that will only let them spawn randomly?
Old bastard but kid at heart...

BielBdeLuna

map files are text files, I guess you can always find and replace.

BloodRayne

Quote from: calan on November 03, 2014, 03:18:02 PM
Is there an easy way to edit a map file, find the monsters, and enter some code that will only let them spawn randomly?

You need to define randomly spawning enemies more clearly.

Most enemies in Doom3 work by using predetermined pathing (AAS pathing) which follows hints for the monsters to follow and make their way through the map. You can't really spawn an enemy randomly without first defining a position where it can do so cleanly, without sticking half inside a wall, or in a place where it can't navigate.

So there needs to be logic in the placement of the monsters. When I made the now unavailable 'Ultimate Mod' for Doom 3, it included a randomized spawn system. But what that did was spawn new monsters in the place where old ones had died after a random amount of time, creating the illusion where they're sort of following you.

The best way to do real random monsters is create custom spawnpoints. Add a script with a random timer and spawn a monster, when the monster dies have it trigger the random spawner again so it spawns another one. Then replace all monster entities that don't have special spawnargs or animations in with this monster spawner, and using the editor, place extra random spawn points by hand.

Grimm has all this logic, you might want to check out how that was implemented here: http://www.moddb.com/mods/grimm-quest-for-the-gatherers-key

calan

#7
Thanks BloodRayne.

What I'm shooting for right now is much simpler.... I just want a way to make existing monsters only appear "sometimes". Some type of script that uses random numbers to control if they can spawn, or if they stay inactive and hidden.

Another thought I had was to use something like that ^ in conjunction with the random encounters code in sikkmod. This is all speculative without any study of the code (I'm still in learning mode), but would it be possible to invisibly spawn a pre-placed monster and then kill it immediately...thus setting up a random respawn? If so, it should be fairly easy to generate a lot of randomness without changing the existing maps...other than adding the script to each existing monster.

My thought experiment is that you add a script to each desired monster (or maybe a global script in the monster ai?) that sometimes lets it function as scripted, sometimes keeps it completely inactive, and sometimes spawns it invisibly and then immediately kills it (thus hopefully triggering a random respawn).

Seems doable, but I don't have the scripting/level knowledge to actually put it in place to test. If someone can help me with the script and process (or just help flesh out the details as I'm learning), I'll go through the maps and set it all up. Could be very interesting.



Old bastard but kid at heart...

calan

#8
someone add this entity/value pair to ai_monster_base, that can be set for each monster in a level:

spawn_control
0 = never
1 = every time (normal)

Between 0 and 1 is a probability of spawning percentage. (I.E. a value of .4 would mean that the monster comes to life and shows up about 40% of the time.)

2 = invisible spawn and quick death, to trigger sikkmod random encounter.


*****

...or if it can be done without recompiling the SDK, teach me.   :D
Old bastard but kid at heart...

solarsplace

Hi

Try adding this code to monster_base::monster_begin as shown below. It should do what you want, or at least give you a head start. As you said, you will need to add a key value pair ( "spawn_control" / float value ) to each AI you want to participate in this functionality.

The code appears to work, but I will leave the in depth testing to you  ;)

/*
=====================
monster_base::monster_begin
=====================
*/
void monster_base::monster_begin() {

// ***************************************
// ***************************************

float rndChance = 0;
float rndNumber = 0;

rndChance = getFloatKey( "spawn_control" );
if ( rndChance == 0 ) { rndChance = 1.0; } // Need to set a default value of always spawn.
rndNumber = random( 1.0 );

if ( rndChance == 0 ) {
// No chance of spawning, just remove.
self.remove();
return;
}

if ( rndChance == 2 ) {
// Always kill.
self.hide();
self.kill();
return;
}

if ( rndChance > 0 && rndChance < 1 ) { // If rndChance == 1 always spawn.

// If a random number between 0 and 1 is greater than
// the AI chance number then remove the AI.

if ( rndNumber > rndChance ) {
self.remove();
return;
}
}

// ***************************************
// ***************************************


Hope that helps.

Cheers

calan

Awesome, but I have a dumb question.

How do I add the "spawn_control" value to the monster defs? Is it as simple as just putting "spawn_control   1.0" in "monster_default.def", and then over-riding it in whatever monster defs that I want a different value?

Thanks much!
Old bastard but kid at heart...

solarsplace

Hi

The default value is set in the script as a 1.0 meaning the AI will behave as if nothing is different.

rndChance = getFloatKey( "spawn_control" );
if ( rndChance == 0 ) { rndChance = 1.0; } // Need to set a default value of always spawn.


To change the "spawn_control" values for the AI entities you want, you will need to load the Doom 3 Editor (Or DarkRadiant etc) and locate and select the AI you want to change. The in the entity inspector in the editor you will see existing key / value pairs for each AI. Just add a new key value pair such as "spawn_control" / 0.4 etc.

You could also locate the entityDef file for a specific AI and add a new key / val into that meaning all AI of that type get that key / val setting.

There is a concern that if you blanket apply this to the AI, you are probably going to get issues with some of the standard game maps if they rely on an AI being there for some script event. You could possibly break parts of the game with some existing script threads crashing and halting execution because the IA they were manipulating was removed or killed off already.

Cheers

calan

That's what I thought on defining the spawn_control values... tried it both ways and not having luck yet, but still working on it. Probably just operator error.  :)

Interesting thought on the scripting errors. Is there an easy way to see which monsters in a level are "needed" and should be left alone?
Old bastard but kid at heart...

The Happy Friar

the easiest way may be to play through the game with a key bound to "toggle g_stoptime".  Then (I forget the console command) find the entity name (when time is stopped) & load up the map script & do a search for that entity.  Also do a search of the map (in a text editor should be fine).  If you find a script that references that monster, or the map has entities that call to or from that monster, it might not be wise to change it.

calan

#14
Still no luck. Here is what I have:

monster_default.def

entityDef monster_default {
"editor_color" "1 .5 0"
        ...
        ...
        ...

// ***** CAS random non-encounters *****
"spawn_control"    "1.0"
"editor_var spawn_control"    "Controls how often monster spawns. 0 = never, 1 = always. Values between 0 and 1 cause monster to spawn x% of the time. A value of 2 causes the monster to spawn and then be killed immediately, to trigger a random encounter."

}


ai_monster_base.script

void monster_base::monster_begin() {

// ***************************************  CAS random non-encounters begin  **********************************

float rndChance = 0;
float rndNumber = 0;

rndChance = getFloatKey( "spawn_control" );
if ( rndChance == 0 ) { rndChance = 1.0; } // Need to set a default value of always spawn.
rndNumber = random( 1.0 );

if ( rndChance == 0 ) {
// No chance of spawning, just remove.
self.remove();
return;
}

if ( rndChance == 2 ) {
// Always kill.
self.hide();
self.kill();
return;
}

if ( rndChance > 0 && rndChance < 1 ) { // If rndChance == 1 always spawn.

// If a random number between 0 and 1 is greater than
// the AI chance number then remove the AI.

if ( rndNumber > rndChance ) {
self.remove();
return;
}
}

// ***************************************  CAS random non-encounters  end  ***********************************


float teleportType;
string triggerAnim;
float waittime;
        ...
        ...
        ...
        ...
}



big_map.map

...
...
...
// entity 1
{
"anim" "idle"
"classname" "monster_zombie_boney"
"name" "monster_zombie_boney_1"
"origin" "272 168 0"
"angle" "180"
"trigger" "1"
"spawn_control" "0.5"
}
...
...



I know the script is reading the spawn_control value from the map, because I can change it from 0 to 1 in the map entity def and it responds as it should. But, the script isn't working as I expect it to.

rndChance = 0, no monsters (as expected)
rndChance = 1, monsters always spawn (as expected)
rndChance = anything between 0 and 1, monsters always spawn
rndChance = 2, monsters never spawn and nothing ever happens. Random encounters is working though, because if I spawn a monster and then kill it, another one will spawn.

Still investigating....

EDIT:

Ok, it looks like the random encounters is working when rndChance = 2. The RE monsters weren't spawning because I'm in the corner of a test room, and they won't appear until I look away. I thought if I set the teleport value, they would spawn no matter if I was looking or not, but that doesn't seem to be the case. I still have to look away, and then POOF!...  there they are.

Still can't get the random appearance to work though.
Old bastard but kid at heart...