Putting Monsters in your Source

 

 

philip
profile | email

posted 11-21-98 1:42 AM CT (US)
Title: Putting Monsters in your Source
Difficulty: Moderate
By: Philip (aka Maj.Bitch)
Email: peblair@gv.net
Date: 11-19-98
Note: Please give credit where credit is due.
======================================================

I originally put this file together so that I could see what it would take to put a monster in my source. Since this is a Generic Helper' File, I decided to post it so that others can put Detonateable Monsters in their code if they were so inclined. Note: There are other things which you'll have to do to your source to award frags and stuff but this file will allow you to spawn ANY of the Q2 Monsters with the single stroke of your aliased key.

You'll have to use some of my previously posted helper functions too..

Also, You'll have to put a call to the Cmd_Monsters_f() function in your g_cmds.c file to initiate the spawn.. You all should be relatively familiar with that by now, (if you've read any of my previous (tutorials).

Okay, let's get started!

======================================================
Create a new file, g_monster2.c and cut and paste all of the following code into this new file.

----------------- START HERE -------------------

#include "g_local.h"
#include "m_player.h"

#define POWER1_SOUND gi.soundindex("misc/power1.wav")
#define POWER2_SOUND gi.soundindex("misc/power2.wav")

// TYPE OF MONSTER ---- HEALTH
#define M_SOLDIERLT 0 // 20
#define M_SOLDIER 1 // 30
#define M_SOLDIERSS 2 // 40
#define M_FLIPPER 3 // 50
#define M_FLYER 4 // 50
#define M_INFANTRY 5 // 100
#define M_INSANE 6 // 100 - Crazy Marine
#define M_GUNNER 7 // 175
#define M_CHICK 8 // 175
#define M_PARASITE 9 // 175
#define M_FLOATER 10 // 200
#define M_HOVER 11 // 240
#define M_BERSERK 12 // 240
#define M_MEDIC 13 // 300
#define M_MUTANT 14 // 300
#define M_BRAIN 15 // 300
#define M_GLADIATOR 16 // 400
#define M_TANK 17 // 750
#define M_SUPERTANK 18 // 1500
#define M_BOSS2 19 // 2000
#define M_JORG 20 // 3000
#define M_MAKRON 21 // 3000

void SP_monster_jorg(edict_t *self);
void SP_monster_boss2(edict_t *self);
void SP_monster_berserk(edict_t *self);
void SP_monster_soldier_ss(edict_t *self);
void SP_monster_soldier(edict_t *self);
void SP_monster_brain(edict_t *self);
void SP_monster_chick(edict_t *self);
void SP_monster_flipper(edict_t *self);
void SP_monster_floater(edict_t *self);
void SP_monster_flyer(edict_t *self);
void SP_monster_gladiator(edict_t *self);
void SP_monster_hover(edict_t *self);
void SP_monster_infantry(edict_t *self);
void SP_misc_insane(edict_t *self);
void SP_monster_medic(edict_t *self);
void SP_monster_mutant(edict_t *self);
void SP_monster_parasite(edict_t *self);
void SP_monster_tank(edict_t *self);
void SP_monster_makron(edict_t *self);
void SP_monster_gunner(edict_t *self);
void SP_monster_supertank(edict_t *self);
void SP_monster_soldier_light(edict_t *self);

//======================================================
// Timer entity initiates the Monsters Self-Detonation.
//
// Monster = timer->activator
// Owner = timer->owner
//======================================================
void Monster_Explode(edict_t *timer) {
vec3_t zvec={0,0,0};

// Has Monster died already?
if (!timer->activator) {
G_FreeEdict(timer);
return; }

// Maximally damage the monster entity...
T_Damage(timer->activator, timer->owner, timer->owner, zvec, timer->activator->s.origin, NULL, 5000, 1, 0,
MOD_SPLASH);

// Spawn an explosion fireball..
G_Spawn_Explosion(TE_EXPLOSION2, timer->activator->s.origin, timer->activator->s.origin);

// Do grenade-type radius damage to anybody nearby
T_RadiusDamage(timer->activator, timer->owner, 40, NULL, 200, MOD_SPLASH);

G_FreeEdict(timer);
}

//=========================================================
void Spawn_Timer(edict_t *ent) {
edict_t *timer;

timer=G_Spawn();
timer->owner=ent;
ent->mynoise2=timer; // Link back to timer..
timer->activator=ent->goalentity;
timer->takedamage=DAMAGE_NO;
timer->movetype=MOVETYPE_NONE;
timer->solid = SOLID_NOT;
VectorClear(timer->s.origin);
VectorClear(timer->mins);
VectorClear(timer->maxs);
timer->think=Monster_Explode;
timer->nextthink=level.time + 180.0; // 3 mins to Self-Destruct
gi.linkentity(timer);
}

//=========================================================
qboolean Spawn_Monster(edict_t *ent, int mtype) {
edict_t *monster;
vec3_t forward, up, torigin;
int temp;

// See if we can project Monster forward 100 units...
AngleVectors(ent->s.angles, forward, NULL, up);
VectorCopy(ent->s.origin, torigin);
VectorMA(torigin, 100, forward, torigin);
if (gi.pointcontents(torigin) & MASK_SHOT) {
gi.cprintf(ent,PRINT_HIGH,"Cannot project into Solid!\n");
return false; }

// Create basic entity stuff...
monster = G_Spawn();
monster->classname = "XMonster"; // Used for Killed() & ClientObits()
monster->activator = ent; // Link back to Owner.
ent->goalentity = monster; // Link Ent to this Monster.
VectorCopy(torigin, monster->s.origin);

gi.linkentity(monster);

//
// Now the Monster Stuff..
//

skill->value=3; // Toggle Advanced AI Mode.

temp=deathmatch->value;
deathmatch->value=0; // Must = 0 to bypass quick-exit in Monster Code

// create this monster type
switch (mtype) {
case M_BERSERK: SP_monster_berserk(monster); break;
case M_BOSS2: SP_monster_boss2(monster); break;
case M_SOLDIERSS: SP_monster_soldier_ss(monster); break;
case M_JORG: SP_monster_jorg(monster); break;
case M_BRAIN: SP_monster_brain(monster); break;
case M_CHICK: SP_monster_chick(monster); break;
case M_FLIPPER: SP_monster_flipper(monster); break;
case M_FLOATER: SP_monster_floater(monster); break;
case M_FLYER: SP_monster_flyer(monster); break;
case M_INSANE: SP_misc_insane(monster); break;
case M_GLADIATOR: SP_monster_gladiator(monster); break;
case M_HOVER: SP_monster_hover(monster); break;
case M_INFANTRY: SP_monster_infantry(monster); break;
case M_SOLDIERLT: SP_monster_soldier_light(monster); break;
case M_SOLDIER: SP_monster_soldier(monster); break;
case M_MEDIC: SP_monster_medic(monster); break;
case M_MUTANT: SP_monster_mutant(monster); break;
case M_PARASITE: SP_monster_parasite(monster); break;
case M_TANK: SP_monster_tank(monster); break;
case M_MAKRON: SP_monster_makron(monster); break;
case M_GUNNER: SP_monster_gunner(monster); break;
case M_SUPERTANK: SP_monster_supertank(monster); break;
} // end switch

deathmatch->value=temp; // Restore to previous value.

monster->monsterinfo.aiflags &= AI_BRUTAL; // Kill Everything Mode!!

gi.sound(ent, CHAN_VOICE, POWER1_SOUND, 1, ATTN_IDLE, 0);

return true; // Spawn successful
}

//====================================================
void Cmd_Monsters_f(edict_t *ent) {

if (ent->goalentity) {
Monster_Explode(ent->mynoise2);
ent->goalentity=NULL;
gi.centerprintf(ent, "MONSTER DETONATED\n");
return; }

// Pass in the Flag for the Type of Monster you want!!
if (Spawn_Monster(ent, M_BRAIN)) {
Spawn_Timer(ent);
gi.centerprintf(ent, "MOVE AWAY NOW!!\n"); }
}

--------------- STOP HERE -----------------------

Remember to make the necessary changes to your g_cmds.c file (not discussed).. Also, note that the Flipper Monster is really the Shark and doesn't move around very well if you spawn one of them on dry land...

Have Fun!!

Philip