Add env_xenmaker entity.
This commit is contained in:
@@ -60,6 +60,7 @@ OBJ = \
|
|||||||
util.o \
|
util.o \
|
||||||
voltigore.o \
|
voltigore.o \
|
||||||
weapons.o \
|
weapons.o \
|
||||||
|
xenmaker.o \
|
||||||
zombie.o
|
zombie.o
|
||||||
|
|
||||||
monster_mm_i386.so: ${OBJ}
|
monster_mm_i386.so: ${OBJ}
|
||||||
|
|||||||
@@ -48,4 +48,46 @@ public:
|
|||||||
BOOL m_fPlaying; // music is active
|
BOOL m_fPlaying; // music is active
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// XenMaker - spawns a monster with a teleportation effect.
|
||||||
|
//=========================================================
|
||||||
|
class CMXenMaker : public CMBaseMonster
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Spawn(void);
|
||||||
|
void Precache(void);
|
||||||
|
void KeyValue(KeyValueData* pkvd);
|
||||||
|
void EXPORT CyclicUse(edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value);
|
||||||
|
void EXPORT RetryThink(void);
|
||||||
|
void StartEffect(void);
|
||||||
|
void EXPORT MiddleEffect(void);
|
||||||
|
void EXPORT EndEffect(void);
|
||||||
|
|
||||||
|
int m_iMonsterIndex;// index of the monster that will be created.
|
||||||
|
|
||||||
|
float m_flGround; // z coord of the ground under me, used to make sure no monsters are under the spawner
|
||||||
|
|
||||||
|
float m_flBeamRadius; // Maximum beam strike radius.
|
||||||
|
int m_iBeamAlpha;
|
||||||
|
int m_iBeamCount; // Number of single beam instances.
|
||||||
|
Vector m_vBeamColor;
|
||||||
|
|
||||||
|
float m_flLightRadius;
|
||||||
|
Vector m_vLightColor;
|
||||||
|
|
||||||
|
float m_flStartSpriteFramerate;
|
||||||
|
float m_flStartSpriteScale;
|
||||||
|
int m_iStartSpriteAlpha;
|
||||||
|
Vector m_vStartSpriteColor;
|
||||||
|
|
||||||
|
float m_flEndSpriteFramerate;
|
||||||
|
float m_flEndSpriteScale;
|
||||||
|
int m_iEndSpriteAlpha;
|
||||||
|
Vector m_vEndSpriteColor;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SpawnBeam(void);
|
||||||
|
int m_iBeamIndex;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // BASEEXTRA_H
|
#endif // BASEEXTRA_H
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ monster_type_t monster_types[]=
|
|||||||
"info_node_air", FALSE,
|
"info_node_air", FALSE,
|
||||||
"monstermaker", FALSE, // Extra entities
|
"monstermaker", FALSE, // Extra entities
|
||||||
"ambient_music", FALSE,
|
"ambient_music", FALSE,
|
||||||
|
"env_xenmaker", FALSE,
|
||||||
"squadmaker", FALSE, // Aliases
|
"squadmaker", FALSE, // Aliases
|
||||||
"", FALSE
|
"", FALSE
|
||||||
};
|
};
|
||||||
@@ -711,6 +712,7 @@ edict_t* spawn_monster(int monster_type, Vector origin, Vector angles, int spawn
|
|||||||
// Extra entities
|
// Extra entities
|
||||||
case 32: monsters[monster_index].pMonster = CreateClassPtr((CMMonsterMaker *)NULL); break;
|
case 32: monsters[monster_index].pMonster = CreateClassPtr((CMMonsterMaker *)NULL); break;
|
||||||
case 33: monsters[monster_index].pMonster = CreateClassPtr((CMAmbientMusic *)NULL); break;
|
case 33: monsters[monster_index].pMonster = CreateClassPtr((CMAmbientMusic *)NULL); break;
|
||||||
|
case 34: monsters[monster_index].pMonster = CreateClassPtr((CMXenMaker *)NULL); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monsters[monster_index].pMonster == NULL)
|
if (monsters[monster_index].pMonster == NULL)
|
||||||
@@ -1435,7 +1437,8 @@ void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
|
|||||||
// Extra entities
|
// Extra entities
|
||||||
CMMonsterMaker monstermaker; // 32
|
CMMonsterMaker monstermaker; // 32
|
||||||
CMAmbientMusic ambientmusic;
|
CMAmbientMusic ambientmusic;
|
||||||
|
CMXenMaker xenmaker;
|
||||||
|
|
||||||
g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" );
|
g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" );
|
||||||
|
|
||||||
(g_engfuncs.pfnAddServerCommand)("monster", MonsterCommand);
|
(g_engfuncs.pfnAddServerCommand)("monster", MonsterCommand);
|
||||||
@@ -1485,6 +1488,7 @@ void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
|
|||||||
case 29: stukabat.Precache(); break;
|
case 29: stukabat.Precache(); break;
|
||||||
case 32: monstermaker.Precache(); break;
|
case 32: monstermaker.Precache(); break;
|
||||||
//case 33: ambientmusic.Precache(); break;
|
//case 33: ambientmusic.Precache(); break;
|
||||||
|
case 34: xenmaker.Precache(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -225,6 +225,22 @@ void scan_monster_cfg(FILE *fp)
|
|||||||
monster = TRUE;
|
monster = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp(monster_types[mIndex].name, "env_xenmaker") == 0)
|
||||||
|
{
|
||||||
|
// A monster spawner, add it to the list
|
||||||
|
if (monster_spawn_count == MAX_MONSTERS)
|
||||||
|
{
|
||||||
|
// error.exe
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: can't add monstermaker, reached MAX_MONSTERS!");
|
||||||
|
badent = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
monster_spawnpoint[monster_spawn_count].monster = mIndex;
|
||||||
|
monster_types[mIndex].need_to_precache = TRUE;
|
||||||
|
monster = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (strcmp(monster_types[mIndex].name, "info_node") == 0)
|
else if (strcmp(monster_types[mIndex].name, "info_node") == 0)
|
||||||
{
|
{
|
||||||
// Normal node
|
// Normal node
|
||||||
@@ -391,8 +407,8 @@ void scan_monster_cfg(FILE *fp)
|
|||||||
{
|
{
|
||||||
if (monster)
|
if (monster)
|
||||||
{
|
{
|
||||||
// this keyvalue is only valid for monstermaker entity
|
// this keyvalue is only valid for monstermaker entities
|
||||||
if (strcmp(data[kvd_index-1].value, "monstermaker") == 0 || strcmp(data[kvd_index-1].value, "squadmaker") == 0)
|
if (strcmp(data[kvd_index - 1].value, "monstermaker") == 0 || strcmp(data[kvd_index - 1].value, "squadmaker") == 0 || strcmp(data[kvd_index - 1].value, "env_xenmaker") == 0)
|
||||||
{
|
{
|
||||||
// process the entity precache here
|
// process the entity precache here
|
||||||
int mIndex;
|
int mIndex;
|
||||||
@@ -771,7 +787,7 @@ void scan_monster_bsp(void)
|
|||||||
if (monster)
|
if (monster)
|
||||||
{
|
{
|
||||||
// this keyvalue is only valid for monstermaker entity
|
// this keyvalue is only valid for monstermaker entity
|
||||||
if (strcmp(data[classname_kvdI].value, "monstermaker") == 0 || strcmp(data[classname_kvdI].value, "squadmaker") == 0)
|
if (strcmp(data[classname_kvdI].value, "monstermaker") == 0 || strcmp(data[classname_kvdI].value, "squadmaker") == 0 || strcmp(data[classname_kvdI].value, "env_xenmaker") == 0)
|
||||||
{
|
{
|
||||||
// process the entity precache here
|
// process the entity precache here
|
||||||
for (mIndex = 0; monster_types[mIndex].name[0]; mIndex++)
|
for (mIndex = 0; monster_types[mIndex].name[0]; mIndex++)
|
||||||
|
|||||||
@@ -127,6 +127,7 @@
|
|||||||
<DataExecutionPrevention>
|
<DataExecutionPrevention>
|
||||||
</DataExecutionPrevention>
|
</DataExecutionPrevention>
|
||||||
<ImportLibrary>.\Release/monster_mm.lib</ImportLibrary>
|
<ImportLibrary>.\Release/monster_mm.lib</ImportLibrary>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -186,6 +187,7 @@
|
|||||||
<ClCompile Include="util.cpp" />
|
<ClCompile Include="util.cpp" />
|
||||||
<ClCompile Include="voltigore.cpp" />
|
<ClCompile Include="voltigore.cpp" />
|
||||||
<ClCompile Include="weapons.cpp" />
|
<ClCompile Include="weapons.cpp" />
|
||||||
|
<ClCompile Include="xenmaker.cpp" />
|
||||||
<ClCompile Include="zombie.cpp" />
|
<ClCompile Include="zombie.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -224,4 +226,4 @@
|
|||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -186,6 +186,9 @@
|
|||||||
<ClCompile Include="globalreplace.cpp">
|
<ClCompile Include="globalreplace.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="xenmaker.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="activity.h">
|
<ClInclude Include="activity.h">
|
||||||
@@ -282,4 +285,4 @@
|
|||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
356
src/dlls/xenmaker.cpp
Normal file
356
src/dlls/xenmaker.cpp
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
//=========================================================
|
||||||
|
// Xen Maker - Sven Co-op's env_xenmaker.
|
||||||
|
// Spawns a monster with visual/auditive teleportation effects.
|
||||||
|
//=========================================================
|
||||||
|
|
||||||
|
#include "extdll.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "cmbase.h"
|
||||||
|
#include "cmbasemonster.h"
|
||||||
|
#include "cmbaseextra.h"
|
||||||
|
#include "monsters.h"
|
||||||
|
|
||||||
|
// Xenmaker spawnflags
|
||||||
|
#define SF_XENMAKER_TRY_ONCE 1 // only one attempt to spawn each time it is fired
|
||||||
|
#define SF_XENMAKER_NO_SPAWN 2 // don't spawn anything, only do effects
|
||||||
|
|
||||||
|
extern monster_type_t monster_types[];
|
||||||
|
extern edict_t* spawn_monster(int monster_type, Vector origin, Vector angles, int spawnflags, pKVD *keyvalue);
|
||||||
|
|
||||||
|
|
||||||
|
// ========================================================
|
||||||
|
void CMXenMaker::KeyValue(KeyValueData *pkvd)
|
||||||
|
{
|
||||||
|
if (FStrEq(pkvd->szKeyName, "monstertype"))
|
||||||
|
{
|
||||||
|
// Process monster_index
|
||||||
|
int mIndex;
|
||||||
|
for (mIndex = 0; monster_types[mIndex].name[0]; mIndex++)
|
||||||
|
{
|
||||||
|
if (strcmp(pkvd->szValue, monster_types[mIndex].name) == 0)
|
||||||
|
{
|
||||||
|
m_iMonsterIndex = mIndex;
|
||||||
|
break; // grab the first entry we find
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (monster_types[mIndex].name[0] == 0)
|
||||||
|
{
|
||||||
|
ALERT(at_logged, "[MONSTER] XenMaker - %s is not a valid monster type!\n", pkvd->szValue);
|
||||||
|
m_iMonsterIndex = -1;
|
||||||
|
}
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_flBeamRadius"))
|
||||||
|
{
|
||||||
|
m_flBeamRadius = atof(pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_iBeamAlpha"))
|
||||||
|
{
|
||||||
|
m_iBeamAlpha = atoi(pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_iBeamCount"))
|
||||||
|
{
|
||||||
|
m_iBeamCount = atoi(pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_vBeamColor"))
|
||||||
|
{
|
||||||
|
UTIL_StringToVector(m_vBeamColor, pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_flLightRadius"))
|
||||||
|
{
|
||||||
|
m_flLightRadius = atof(pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_vLightColor"))
|
||||||
|
{
|
||||||
|
UTIL_StringToVector(m_vLightColor, pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_flStartSpriteFramerate"))
|
||||||
|
{
|
||||||
|
m_flStartSpriteFramerate = atof(pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_flStartSpriteScale"))
|
||||||
|
{
|
||||||
|
m_flStartSpriteScale = atof(pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_iStartSpriteAlpha"))
|
||||||
|
{
|
||||||
|
m_iStartSpriteAlpha = atoi(pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_vStartSpriteColor"))
|
||||||
|
{
|
||||||
|
UTIL_StringToVector(m_vStartSpriteColor, pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_flEndSpriteFramerate"))
|
||||||
|
{
|
||||||
|
m_flEndSpriteFramerate = atof(pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_flEndSpriteScale"))
|
||||||
|
{
|
||||||
|
m_flEndSpriteScale = atof(pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_iEndSpriteAlpha"))
|
||||||
|
{
|
||||||
|
m_iEndSpriteAlpha = atoi(pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else if (FStrEq(pkvd->szKeyName, "m_vEndSpriteColor"))
|
||||||
|
{
|
||||||
|
UTIL_StringToVector(m_vEndSpriteColor, pkvd->szValue);
|
||||||
|
pkvd->fHandled = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
CMBaseMonster::KeyValue(pkvd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CMXenMaker::Spawn()
|
||||||
|
{
|
||||||
|
// likely omitted keyvalue, but it could truly be an alien grunt spawn
|
||||||
|
if (m_iMonsterIndex == 0)
|
||||||
|
{
|
||||||
|
if (!monster_types[0].need_to_precache)
|
||||||
|
{
|
||||||
|
// monstertype was not defined, it may be intentional if nothing is to spawn here
|
||||||
|
if (!FBitSet(pev->spawnflags, SF_XENMAKER_NO_SPAWN))
|
||||||
|
ALERT(at_logged, "[MONSTER] Spawned a env_xenmaker entity without a monstertype! targetname: \"%s\"\n", STRING(pev->targetname));
|
||||||
|
m_iMonsterIndex = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pev->solid = SOLID_NOT;
|
||||||
|
|
||||||
|
Precache();
|
||||||
|
|
||||||
|
SetUse(&CMXenMaker::CyclicUse); // drop one monster each time we fire
|
||||||
|
SetThink(&CMXenMaker::SUB_DoNothing);
|
||||||
|
|
||||||
|
m_flGround = 0;
|
||||||
|
pev->classname = MAKE_STRING("env_xenmaker");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMXenMaker::Precache(void)
|
||||||
|
{
|
||||||
|
m_iBeamIndex = PRECACHE_MODELINDEX("sprites/lgtning.spr");
|
||||||
|
PRECACHE_MODEL("sprites/fexplo1.spr");
|
||||||
|
PRECACHE_MODEL("sprites/xflare1.spr");
|
||||||
|
|
||||||
|
PRECACHE_SOUND("debris/beamstart7.wav");
|
||||||
|
PRECACHE_SOUND("debris/beamstart2.wav");
|
||||||
|
|
||||||
|
CMBaseMonster::Precache();
|
||||||
|
// choosen monster is auto-precached
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// StartEffect - spawns the monster and starts the effects
|
||||||
|
//=========================================================
|
||||||
|
void CMXenMaker::StartEffect(void)
|
||||||
|
{
|
||||||
|
if (!m_flGround)
|
||||||
|
{
|
||||||
|
// setup altitude
|
||||||
|
TraceResult tr;
|
||||||
|
|
||||||
|
UTIL_TraceLine(pev->origin, pev->origin - Vector(0, 0, 2048), ignore_monsters, ENT(pev), &tr);
|
||||||
|
m_flGround = tr.vecEndPos.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FBitSet(pev->spawnflags, SF_XENMAKER_NO_SPAWN))
|
||||||
|
{
|
||||||
|
// monstermaker incorrectly setup
|
||||||
|
if (m_iMonsterIndex == -1)
|
||||||
|
{
|
||||||
|
ALERT(at_console, "[MONSTER] NULL Ent in XenMaker!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
edict_t *pent;
|
||||||
|
|
||||||
|
Vector mins = pev->origin - Vector(34, 34, 0);
|
||||||
|
Vector maxs = pev->origin + Vector(34, 34, 0);
|
||||||
|
maxs.z = pev->origin.z;
|
||||||
|
mins.z = m_flGround;
|
||||||
|
|
||||||
|
edict_t *pList[2];
|
||||||
|
int count = UTIL_EntitiesInBox(pList, 2, mins, maxs, FL_CLIENT | FL_MONSTER);
|
||||||
|
if (!count)
|
||||||
|
{
|
||||||
|
// Attempt to spawn monster
|
||||||
|
pent = spawn_monster(m_iMonsterIndex, pev->origin, pev->angles, SF_MONSTER_FALL_TO_GROUND, NULL);
|
||||||
|
if (pent == NULL)
|
||||||
|
{
|
||||||
|
ALERT(at_console, "[MONSTER] XenMaker - failed to spawn monster! targetname: \"%s\"\n", STRING(pev->targetname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!FBitSet(pev->spawnflags, SF_XENMAKER_TRY_ONCE))
|
||||||
|
{
|
||||||
|
// wait until spawnpoint is clear
|
||||||
|
pev->nextthink = gpGlobals->time + 1;
|
||||||
|
SetUse(NULL);
|
||||||
|
SetThink(&CMXenMaker::RetryThink);
|
||||||
|
return; // don't do effects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BEAM EFFECT
|
||||||
|
for (int beam = 0; beam < m_iBeamCount; beam++)
|
||||||
|
{
|
||||||
|
SpawnBeam();
|
||||||
|
}
|
||||||
|
|
||||||
|
// LIGHT EFFECT
|
||||||
|
MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY);
|
||||||
|
WRITE_BYTE(TE_DLIGHT);
|
||||||
|
WRITE_COORD(pev->origin.x);
|
||||||
|
WRITE_COORD(pev->origin.y);
|
||||||
|
WRITE_COORD(pev->origin.z);
|
||||||
|
WRITE_BYTE((int)(m_flLightRadius / 10));
|
||||||
|
WRITE_BYTE((int)m_vLightColor.x);
|
||||||
|
WRITE_BYTE((int)m_vLightColor.y);
|
||||||
|
WRITE_BYTE((int)m_vLightColor.z);
|
||||||
|
WRITE_BYTE(10); // life
|
||||||
|
WRITE_BYTE(0); // decay rate
|
||||||
|
MESSAGE_END();
|
||||||
|
|
||||||
|
// SPRITE EFFECT
|
||||||
|
CMSprite *pSprite = CMSprite::SpriteCreate("sprites/fexplo1.spr", pev->origin, FALSE);
|
||||||
|
if (pSprite)
|
||||||
|
{
|
||||||
|
pSprite->SetScale(m_flStartSpriteScale);
|
||||||
|
pSprite->SetTransparency(kRenderGlow, (int)m_vStartSpriteColor.x, (int)m_vStartSpriteColor.y, (int)m_vStartSpriteColor.z, m_iStartSpriteAlpha, kRenderFxNoDissipation);
|
||||||
|
pSprite->AnimateAndDie(m_flStartSpriteFramerate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SOUND EFFECT
|
||||||
|
EMIT_SOUND_DYN(ENT(pev), CHAN_AUTO, "debris/beamstart7.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
|
||||||
|
|
||||||
|
pev->nextthink = gpGlobals->time + 0.5;
|
||||||
|
SetUse(NULL);
|
||||||
|
SetThink(&CMXenMaker::MiddleEffect);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// MiddleEffect - second set of effects
|
||||||
|
//=========================================================
|
||||||
|
void CMXenMaker::MiddleEffect(void)
|
||||||
|
{
|
||||||
|
// SPRITE EFFECT
|
||||||
|
CMSprite *pSprite = CMSprite::SpriteCreate("sprites/xflare1.spr", pev->origin, FALSE);
|
||||||
|
if (pSprite)
|
||||||
|
{
|
||||||
|
pSprite->SetScale(m_flEndSpriteScale);
|
||||||
|
pSprite->SetTransparency(kRenderGlow, (int)m_vEndSpriteColor.x, (int)m_vEndSpriteColor.y, (int)m_vEndSpriteColor.z, m_iEndSpriteAlpha, kRenderFxNoDissipation);
|
||||||
|
pSprite->AnimateAndDie(m_flEndSpriteFramerate);
|
||||||
|
}
|
||||||
|
|
||||||
|
pev->nextthink = gpGlobals->time + 0.5;
|
||||||
|
SetThink(&CMXenMaker::EndEffect);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// EndEffect - final set of effects
|
||||||
|
//=========================================================
|
||||||
|
void CMXenMaker::EndEffect(void)
|
||||||
|
{
|
||||||
|
// SOUND EFFECT
|
||||||
|
EMIT_SOUND_DYN(ENT(pev), CHAN_AUTO, "debris/beamstart2.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
|
||||||
|
|
||||||
|
SetUse(&CMXenMaker::CyclicUse);
|
||||||
|
SetThink(&CMXenMaker::SUB_DoNothing);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// CyclicUse - drops one monster from the xen maker
|
||||||
|
// each time we call this.
|
||||||
|
//=========================================================
|
||||||
|
void CMXenMaker::CyclicUse(edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value)
|
||||||
|
{
|
||||||
|
StartEffect();
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// RetryThink - try spawning again if spawn was obstructed
|
||||||
|
//=========================================================
|
||||||
|
void CMXenMaker::RetryThink(void)
|
||||||
|
{
|
||||||
|
SetUse(&CMXenMaker::CyclicUse);
|
||||||
|
SetThink(&CMXenMaker::SUB_DoNothing);
|
||||||
|
|
||||||
|
StartEffect();
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// SpawnBeam - calculates beam end position and creates it.
|
||||||
|
// starting position is the origin of the xenmaker itself.
|
||||||
|
//=========================================================
|
||||||
|
void CMXenMaker::SpawnBeam(void)
|
||||||
|
{
|
||||||
|
// CLightning::RandomArea
|
||||||
|
for (int iLoops = 0; iLoops < 10; iLoops++)
|
||||||
|
{
|
||||||
|
Vector vecSrc = pev->origin;
|
||||||
|
|
||||||
|
Vector vecDir1 = Vector(RANDOM_FLOAT(-1.0, 1.0), RANDOM_FLOAT(-1.0, 1.0), RANDOM_FLOAT(-1.0, 1.0));
|
||||||
|
vecDir1 = vecDir1.Normalize();
|
||||||
|
TraceResult tr1;
|
||||||
|
UTIL_TraceLine(vecSrc, vecSrc + vecDir1 * m_flBeamRadius, ignore_monsters, ENT(pev), &tr1);
|
||||||
|
|
||||||
|
if (tr1.flFraction == 1.0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector vecDir2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
vecDir2 = Vector(RANDOM_FLOAT(-1.0, 1.0), RANDOM_FLOAT(-1.0, 1.0), RANDOM_FLOAT(-1.0, 1.0));
|
||||||
|
} while (DotProduct(vecDir1, vecDir2) > 0);
|
||||||
|
vecDir2 = vecDir2.Normalize();
|
||||||
|
TraceResult tr2;
|
||||||
|
UTIL_TraceLine(vecSrc, vecSrc + vecDir2 * m_flBeamRadius, ignore_monsters, ENT(pev), &tr2);
|
||||||
|
|
||||||
|
if (tr2.flFraction == 1.0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((tr1.vecEndPos - tr2.vecEndPos).Length() < m_flBeamRadius * 0.1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
UTIL_TraceLine(tr1.vecEndPos, tr2.vecEndPos, ignore_monsters, ENT(pev), &tr2);
|
||||||
|
|
||||||
|
if (tr2.flFraction != 1.0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// CLightning::Zap
|
||||||
|
MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY);
|
||||||
|
WRITE_BYTE(TE_BEAMPOINTS);
|
||||||
|
WRITE_COORD(tr1.vecEndPos.x);
|
||||||
|
WRITE_COORD(tr1.vecEndPos.y);
|
||||||
|
WRITE_COORD(tr1.vecEndPos.z);
|
||||||
|
WRITE_COORD(tr2.vecEndPos.x);
|
||||||
|
WRITE_COORD(tr2.vecEndPos.y);
|
||||||
|
WRITE_COORD(tr2.vecEndPos.z);
|
||||||
|
WRITE_SHORT(m_iBeamIndex);
|
||||||
|
WRITE_BYTE(0); // starting frame
|
||||||
|
WRITE_BYTE(10); // framerate
|
||||||
|
WRITE_BYTE(10); // life
|
||||||
|
WRITE_BYTE(16); // width
|
||||||
|
WRITE_BYTE(64); // noise
|
||||||
|
WRITE_BYTE((int)m_vBeamColor.x);
|
||||||
|
WRITE_BYTE((int)m_vBeamColor.y);
|
||||||
|
WRITE_BYTE((int)m_vBeamColor.z);
|
||||||
|
WRITE_BYTE(m_iBeamAlpha);
|
||||||
|
WRITE_BYTE(15); // speed
|
||||||
|
MESSAGE_END();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user