Section 2: idAI2s and spawns
Before we edit an encounter, we need to know about the behind-the-scenes elements going on.
Specifically, this section will cover idAI2s and spawns.
idAI2s
Earlier, I said that:
An .entities file purely consists of defined entities, or entitydefs. Entitydefs can be quite literally anything from triggers to encounter managers to pickups.
An idAI2 is an entity for a specific demon.
What do I mean by that? Let's take a look at an idAI2 for an Imp.
entity {
layers {
"spawn_target_layer"
}
entityDef ai_custom_imp {
inherit = "ai/fodder/imp";
class = "idAI2";
expandInheritance = false;
poolCount = 0;
poolGranularity = 2;
networkReplicated = true;
disableAIPooling = false;
edit = {
[ The stuff that usually goes here ]
}
}
}
You can CTRL + F "ai/fodder/imp" to see what's usually in the edit section. It consists of important but irrelevant settings so I will not be including it here.
Think of idAI2s as the demon itself. These entities, however, will not do anything if you were to copy + paste a new one into your file. They need to be spawned in order to exist as you typically see them in-game.
How can we spawn them? We will get to that in this next section:
idTarget_Spawn(s)
idTarget_Spawn(s) are exactly what you think they are: they're spawn points for demons.
The catch is though: they must reference an idAI2 in some way.
I cannot stress this enough, a target spawn must reference an idAI2 in some form.
Making a spawn point is easy: copy + paste an existing one and edit the four important things:
- entitydefs
- aistateoverride
- spawnOrientation
- spawnPosition
It is these four, and only these four, that matter.
Here is an example of a custom spawn point, notice how it references our Imp idAI2 from earlier. I have also marked the other important things to edit with comments.
entity {
entityDef custom_imp_spawn_1 {
inherit = "target/spawn";
class = "idTarget_Spawn";
expandInheritance = false;
poolCount = 0;
poolGranularity = 2;
networkReplicated = false;
disableAIPooling = false;
edit = {
flags = {
noFlood = true;
}
spawnConditions = {
maxCount = 0;
reuseDelaySec = 0;
doBoundsTest = false;
boundsTestType = "BOUNDSTEST_NONE";
fovCheck = 0;
minDistance = 0;
maxDistance = 0;
neighborSpawnerDistance = -1;
LOS_Test = "LOS_NONE";
playerToTest = "PLAYER_SP";
conditionProxy = "";
}
spawnEditableShared = {
groupName = "";
deathTrigger = "";
coverRadius = 0;
maxEnemyCoverDistance = 0;
}
entityDefs = {
num = 1;
item[0] = {
name = "ai_custom_imp"; // the idAI2 is referenced in here
}
}
conductorEntityAIType = "SPAWN_AI_TYPE_ANY";
initialEntityDefs = {
num = 0;
}
spawnEditable = {
spawnAt = "";
copyTargets = false;
additionalTargets = {
num = 0;
}
overwriteTraversalFlags = true;
traversalClassFlags = "CLASS_A";
combatHintClass = "CLASS_ALL";
spawnAnim = "";
aiStateOverride = "AIOVERRIDE_TELEPORT"; // this specifies that this ai will spawn in alongside the red teleport FX you see
initialTargetOverride = "";
}
portal = "";
targetSpawnParent = "";
disablePooling = false;
spawnOrientation = { // this is where the ai will face when it's spawned. it is ignored if the ai is teleported in.
mat = {
mat[0] = {
x = -1.000000;
y = -0.000000;
z = -0.000000;
}
mat[1] = {
x = 0.000000;
y = -1.000000;
z=0.000000;
}
mat[2] = {
x = -0.000000;
y = 0.000000;
z = 1.000000;
}
}
}
spawnPosition = { // this is the spawn position of the ai
x = -30.209999;
y = -11.000000;
z = -10;
}
}
}
}
Everything else in the target spawn can, and should, be ignored.
You can use the same idAI2 for as many target spawns as you want. For example I can very much have every single new spawn point I make that I want to support an imp all use "ai_custom_imp".
This is how idAI2s and idTarget_Spawn(s) work with each other. The idAI2 is just an entity for a specific demon that target spawns will take and place wherever you want, however many times you want.
Before going into encounter editing, we ought to go over two more entities that use idTarget_Spawn(s), idTargetSpawnGroup(s) and idTarget_Spawn_Parent, and how they are used in an encounter as well.
idTargetSpawnGroup(s)
todo: go over spawn group example,