djcev.com

//

Git Repos / fte_dogmode / qc / func / monster_spawner.qc

Last update to this file was on 2024-09-17 at 12:58.

Show monster_spawner.qc

//==============================================================================
// func_monster_spawner -- mobot.qc
//==============================================================================

// Using "bot" creation code for func_monster_spawner
// most of the code is from a tutorial on creating a bot monster found here:
// https://www.quaddicted.com/webarchive/minion.planetquake.gamespy.com/tutorial/tutor9.htm
// I added the MobotSpawnPoint, retriggering and random gen with help from
// kreathor, 4LT, Paril, Spoike and others on the Quake Mapping Discord.
// ===================================================================
// Big thanks to ryanscissorhands for helping fix telefragging issues!
// ===================================================================

//======================================================================
// constants
//======================================================================

#ifdef SSQC
const float MOBOT_SPAWNER_RESET = 1;
const float MOBOT_PASSIVE = 2; // MOBOT_DONT_SPAWN_ANGRY
const float MOBOT_DONT_ADD_KILL_COUNT = 4;
const float MOBOT_SILENT_SPAWN = 32;
#endif

//======================================================================
// forward declarations
//======================================================================

// func_monster_spawner
#ifdef SSQC
entity() func_monster_spawner_find_spawnpoint;
void(entity e) func_monster_spawner_tfrag;
void() func_monster_spawner_create;
void() func_monster_spawner_think;
void(entity e) func_monster_spawner_init; // Initialization
void() func_monster_spawner;
#endif

//------------------------------------------------------------------------------

/*QUAKED func_monster_spawner (.75 0 .75) (-8 -8 -8) (8 8 8) REUSABLE X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
Spawns monsters to targeted info_monster_spawnpoint
bot
Choose Style
• 1 (Dog (Default)
• 2 (Grunt)
• 3 (Enforcer)
• 4 (Ogre)
• 5 (Fiend)
• 6 (Wizard)
• 7 (Shambler)
• 8 (Knight)
• 9 (HellKnight)
• 11 (Zombie)
• 12 (Shalrath)

Style 2 set to 1 overrides Style and chooses a random monster (excluding Zombies and Vores)

Default time between spawns is 5 seconds; 12 for Zombies and Vores to reduce telefrags

Can set Berserk to 1 to skip most pain animations.

Can only use default health, models and sounds.
*/
//----------------------------------------------------------------------
// class func_monster_spawner: base_func
// {
#ifdef SSQC
//--------------------------------------------------------------
// find_spawnpoint -- Returns the entity to spawn at; was named
// MobotSpawnPoint
//--------------------------------------------------------------
entity() func_monster_spawner_find_spawnpoint =
{
local entity spot;

// spot = find (world, classname, "info_monster_spawnpoint");
spot = find (world, targetname, self.target);

if (!spot)
objerror ("func_monster_spawner_find_spawnpoint: "
"couldn't find target!\n");

return spot;
};

//--------------------------------------------------------------
void(entity e) func_monster_spawner_tfrag =
{
if (!(self.spawnflags & MOBOT_SILENT_SPAWN))
// SILENT
spawn_tfog (e.origin);
spawn_tdeath (e.origin, e);
};

//--------------------------------------------------------------
void() func_monster_spawner_create =
{
// let's not use deathmatch points for this -- dumptruck_ds
// spawn_spot = SelectSpawnPoint ();
local entity spawn_spot =
func_monster_spawner_find_spawnpoint ();
local float angry = self.spawnflags & MOBOT_PASSIVE ? 0 : 1;
local entity e = __NULL__;

switch (self.style)
{
case 1:
// spawn a Doggo
e = spawn_monster_dog (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
e.view_ofs = '0 0 22';
break;
case 2:
// spawn a Grunt
e = spawn_monster_army (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
e.view_ofs = '0 0 22';
break;
case 3:
// spawn an Enforcer
e = spawn_monster_enforcer (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
e.view_ofs = '0 0 22';
break;
case 4:
// spawn an Ogre
e = spawn_monster_ogre (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
e.view_ofs = '0 0 22';
break;
case 5:
// spawn a Fiend
e = spawn_monster_demon1 (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
e.view_ofs = '0 0 22';
break;
case 6:
// spawn a Wizard / Scrag
e = spawn_monster_wizard (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
// e.mdl_proj = "progs/w_spike.mdl";
e.view_ofs = '0 0 22';
break;
case 7:
// spawn a Shambler
e = spawn_monster_shambler (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
e.view_ofs = '0 0 2';
break;
case 8:
// spawn a Knight
e = spawn_monster_knight (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
e.view_ofs = '0 0 22';
break;
case 9:
// spawn a HellKnight
e = spawn_monster_hell_knight (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
e.view_ofs = '0 0 22';
break;
case 11:
// spawn a Zombie
e = spawn_monster_zombie (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
e.view_ofs = '0 0 2';
break;
case 12:
// spawn a Shalrath
e = spawn_monster_shalrath (
spawn_spot.origin + '0 0 1',
spawn_spot.angles,
0,
120,
angry);
e.view_ofs = '0 0 22';
break;
default:
dprint (sprintf("func_monster_spawner_create: "
"unknown style %g!\n", self.style));
}

if (e)
{
e.fixangle = TRUE;
func_monster_spawner_tfrag (e);

if (!(self.spawnflags & MOBOT_DONT_ADD_KILL_COUNT))
// replacement function from iw -- dumptruck_ds
monster_update_total (1);
}
};

//--------------------------------------------------------------
void() func_monster_spawner_think =
{
dprint ("func_monster_spawner_think: starting...\n");
// telefrag check thanks to ryanscissorhands for this code!
// -- dumptruck_ds
// findradius (vector origin, float radius in Quake units)
local entity nearby = findradius (self.origin, 128);

while (nearby)
{
if (nearby.takedamage && nearby.solid != SOLID_CORPSE)
{
dprint ("func_monster_spawner_think: "
"monster waiting to spawn\n");
// qss crash fix from paavohuhtala
// -- dumptruck_ds
self.think = func_monster_spawner_think;
// delay the spawn by some amount;
self.nextthink = time + 1;
return;
}
nearby = nearby.chain;
}

self.count = self.count - 1;

if (self.count < 0)
return;

if (self.count != 0)
{
if !(self.wait)
self.nextthink = time + 5;
else
self.nextthink = time + self.wait;

if (self.style2 == 1)
{
// random monster!! -- dumptruck_ds
self.style = floor (random() * 12) + 1;

// re-roll 10s -- CEV
while (self.style == 10)
self.style = floor (random() * 12) + 1;

// thanks whirledtsar for your help on this
// -- dumptruck_ds
func_monster_spawner_create ();
}
else
{
func_monster_spawner_create ();
}
}
else
{
if (self.spawnflags & MOBOT_SPAWNER_RESET)
{
self.count = self.cnt;
self.think = sub_null;
}
}

self.think = func_monster_spawner_think;
};

//==============================================================
// Initialization
//==============================================================

//--------------------------------------------------------------
void(entity e) func_monster_spawner_init =
{
if !(e.target)
{
objerror ("func_monster_spawner needs a target");
remove (e);
return;
}

e.classname = "func_monster_spawner";
e.classtype = CT_FUNC_MONSTER_SPAWNER;
base_mapentity_init (e);

if !(e.style)
e.style = 1;

if (!e.count)
e.count = 5;
// fixes count display
e.count = e.count + 1;
// hold original count
e.cnt = e.count;

e.use = func_monster_spawner_think;
};

//--------------------------------------------------------------
void() func_monster_spawner =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

func_monster_spawner_init (self);
};
#endif
// };

Return to the top of this page or return to the overview of this repo.

Log monster_spawner.qc

Date Commit Message Author + -
2024-09-17 Ice, improved stairs, other movement changes cev +3 -2
2024-06-15 Major update, committing as-is, will have bugs cev +148 -135
2024-04-08 Registered monsters, projectile bugfixes cev +47 -54
2024-02-18 Client/player, projectiles, entrypoints refactor cev +141 -436
2024-01-31 Class based monster refactor & start projectiles cev +58 -3
2024-01-09 Continue OO / Class-based refactor cev +514 -503
2023-11-27 Code reorg, minor movement changes, misc cev +565  

Return to the top of this page or return to the overview of this repo.