VERC: Adding new monster factions Last edited 2 years ago2022-09-29 07:54:02 UTC

Alrighty, this tutorial will show you how to add new factions to monsters. Ex. a human grunt uses a faction type of CLASS_HUMAN_MILITARY. Lets say you added in Black Ops from Op4. If they were CLASS_HUMAN_MILITARY then they would be friends with human grunts, but that isn't the way it worked in Op4, so lets add a CLASS_BLACK_OP. First open up cbase.h, scroll down a little and you should see this:
// For CLASSIFY
#define CLASS_NONE              0
#define CLASS_MACHINE           1
#define CLASS_PLAYER            2
#define CLASS_HUMAN_PASSIVE     3
#define CLASS_HUMAN_MILITARY    4
#define CLASS_ALIEN_MILITARY    5
#define CLASS_ALIEN_PASSIVE     6
#define CLASS_ALIEN_MONSTER     7
#define CLASS_ALIEN_PREY        8
#define CLASS_ALIEN_PREDATOR    9
#define CLASS_INSECT            10
#define CLASS_PLAYER_ALLY       11
#define CLASS_PLAYER_BIOWEAPON  12 // hornets and snarks.launched by players
#define CLASS_ALIEN_BIOWEAPON   13 // hornets and snarks.launched by the alien menace
#define CLASS_BARNACLE          99 // special because no one pays attention to it, and it eats a wide cross-section of creatures.
Now, between CLASS_ALIEN_BIOWEAPON and CLASS_BARNACLE add in this:
#define CLASS_PLAYER_BIOWEAPON  12 // hornets and snarks.launched by players
#define CLASS_BLACK_OP 14 // <-- new Black Op faction!
#define CLASS_BARNACLE          99 // special because no one pays attention to it, and it eats a wide cross-section of creatures.
Now that we have our new class declared, we have to open up monsters.cpp. Find the IRelationship function for the class CBaseMonster. Close to the top of the function you should see a grid of code like this:
static int iEnemy[14][14] =
{            //   NONE   MACH    PLYR    HPASS   HMIL    AMIL    APASS   AMONST APREY    APRED   INSECT PLRALY  PBWPN   ABWPN
/*NONE*/        { R_NO  ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO,  R_NO,   R_NO    },
/*MACHINE*/     { R_NO  ,R_NO   ,R_DL   ,R_DL   ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_DL,  R_DL,   R_DL    },
/*PLAYER*/      { R_NO  ,R_DL   ,R_NO   ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO,  R_DL,   R_DL    },
/*HUMANPASSIVE*/{ R_NO  ,R_NO   ,R_AL   ,R_AL   ,R_HT   ,R_FR   ,R_NO   ,R_HT   ,R_DL   ,R_FR   ,R_NO   ,R_AL,  R_NO,   R_NO    },
/*HUMANMILITAR*/{ R_NO  ,R_NO   ,R_HT   ,R_DL   ,R_NO   ,R_HT   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_HT,  R_NO,   R_NO    },
/*ALIENMILITAR*/{ R_NO  ,R_DL   ,R_HT   ,R_DL   ,R_HT   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_DL,  R_NO,   R_NO    },
/*ALIENPASSIVE*/{ R_NO  ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO,  R_NO,   R_NO    },
/*ALIENMONSTER*/{ R_NO  ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_DL,  R_NO,   R_NO    },
/*ALIENPREY   */{ R_NO  ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_FR   ,R_NO   ,R_DL,  R_NO,   R_NO    },
/*ALIENPREDATO*/{ R_NO  ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO   ,R_NO   ,R_HT   ,R_DL   ,R_NO   ,R_DL,  R_NO,   R_NO    },
/*INSECT*/      { R_FR  ,R_FR   ,R_FR   ,R_FR   ,R_FR   ,R_NO   ,R_FR   ,R_FR   ,R_FR   ,R_FR   ,R_NO   ,R_FR,  R_NO,   R_NO    },
/*PLAYERALLY*/  { R_NO  ,R_DL   ,R_AL   ,R_AL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO,  R_NO,   R_NO    },
/*PBIOWEAPON*/  { R_NO  ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_DL,  R_NO,   R_DL    },
/*ABIOWEAPON*/  { R_NO  ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_AL   ,R_NO   ,R_DL   ,R_DL   ,R_NO   ,R_NO   ,R_DL,  R_DL,   R_NO    }
};
Ok, next is the main part of the tutorial. Examine the grid, first, change the
iEnemy[14][14]
to...
iEnemy[15][15]
Now you need to add one row and one column to the code grid. Just copy and paste the last column and row onto the grid. Change the labels to /*BLACKOP*/ and BLKOP or whatever. Your grid should look like this:
static int iEnemy[15][15] =
{            //   NONE   MACH    PLYR    HPASS   HMIL    AMIL    APASS   AMONST APREY    APRED   INSECT PLRALY  PBWPN   ABWPN  BLKOP
/*NONE*/        { R_NO  ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO,  R_NO   ,R_NO  ,R_NO   },
/*MACHINE*/     { R_NO  ,R_NO   ,R_DL   ,R_DL   ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_DL,  R_DL   ,R_DL  ,R_NO   },
/*PLAYER*/      { R_NO  ,R_DL   ,R_NO   ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO,  R_DL   ,R_DL  ,R_DL   },
/*HUMANPASSIVE*/{ R_NO  ,R_NO   ,R_AL   ,R_AL   ,R_HT   ,R_FR   ,R_NO   ,R_HT   ,R_DL   ,R_FR   ,R_NO   ,R_AL,  R_NO   ,R_NO  ,R_HT   },
/*HUMANMILITAR*/{ R_NO  ,R_NO   ,R_HT   ,R_DL   ,R_NO   ,R_HT   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_HT,  R_NO   ,R_NO  ,R_NM   },
/*ALIENMILITAR*/{ R_NO  ,R_DL   ,R_HT   ,R_DL   ,R_HT   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_DL,  R_NO   ,R_NO  ,R_HT   },
/*ALIENPASSIVE*/{ R_NO  ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO,  R_NO   ,R_NO  ,R_HT   },
/*ALIENMONSTER*/{ R_NO  ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_DL,  R_NO   ,R_NO  ,R_DL   },
/*ALIENPREY   */{ R_NO  ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO   ,R_NO   ,R_NO   ,R_FR   ,R_NO   ,R_DL,  R_NO   ,R_NO  ,R_DL   },
/*ALIENPREDATO*/{ R_NO  ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO   ,R_NO   ,R_HT   ,R_DL   ,R_NO   ,R_DL,  R_NO   ,R_NO  ,R_HT   },
/*INSECT*/      { R_FR  ,R_FR   ,R_FR   ,R_FR   ,R_FR   ,R_NO   ,R_FR   ,R_FR   ,R_FR   ,R_FR   ,R_NO   ,R_FR,  R_NO   ,R_NO  ,R_NO   },
/*PLAYERALLY*/  { R_NO  ,R_DL   ,R_AL   ,R_AL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO,  R_NO   ,R_NO  ,R_HT   },
/*PBIOWEAPON*/  { R_NO  ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_DL,  R_NO   ,R_DL  ,R_DL   },
/*ABIOWEAPON*/  { R_NO  ,R_NO   ,R_DL   ,R_DL   ,R_DL   ,R_AL   ,R_NO   ,R_DL   ,R_DL   ,R_NO   ,R_NO   ,R_DL,  R_DL   ,R_NO  ,R_DL   },
/*BLACKOP*/     { R_NO  ,R_NO   ,R_HT   ,R_DL   ,R_DL   ,R_HT   ,R_DL   ,R_DL   ,R_DL   ,R_NO   ,R_NO   ,R_HT,  R_NO   ,R_NO  ,R_NO   }
};
Now we are almost done. If you look at the grid you see a lot of R_ this and R_ that. In monsters.h take a look at this code:
// monster to monster relationship types
#define R_AL    -2 // (ALLY) pals. Good alternative to R_NO when applicable.
#define R_FR    -1// (FEAR)will run
#define R_NO    0// (NO RELATIONSHIP) disregard
#define R_DL    1// (DISLIKE) will attack
#define R_HT    2// (HATE)will attack this character instead of any visible DISLIKEd characters
#define R_NM    3// (NEMESIS)  A monster Will ALWAYS attack its nemsis, no matter what
Those are the monster relationship types. Using those defines set up your Black Op to have its enemies and friends. It works just like a normal grid, take ALIENMILITAR for example, going across it's grid section, it will dislike machines, hate players, dislike passive humans, etc. Now the only thing you have to do is go into your monster's Classify() function and have it return CLASS_BLACK_OP and you're all set. I hope you learned from the tutorial. Now good luck. :)
This article was originally published on Valve Editing Resource Collective (VERC).
The archived page is available here.
TWHL only publishes archived articles from defunct websites, or with permission. For more information on TWHL's archiving efforts, please visit the TWHL Archiving Project page.

Comments

You must log in to post a comment. You can login or register a new account.