Upload monster_blkop_apache, monster_blkop_osprey and monster_male_assassin implementations.

This commit is contained in:
Night Owl 2017-10-28 17:07:31 +05:00
parent 0168a6f212
commit cfb15b3c84
6 changed files with 705 additions and 2 deletions

View File

@ -35,6 +35,7 @@ class CApache : public CBaseMonster
void Spawn( void );
void Precache( void );
int IRelationship( CBaseEntity *pTarget );
int Classify( void ) { return CLASS_HUMAN_MILITARY; };
int BloodColor( void ) { return DONT_BLEED; }
void Killed( entvars_t *pevAttacker, int iGib );
@ -175,6 +176,20 @@ void CApache::Precache( void )
UTIL_PrecacheOther( "hvr_rocket" );
}
//=========================================================
// IRelationship - overridden because Black Ops are
// Human Grunt's nemesis.
//=========================================================
int CApache::IRelationship( CBaseEntity *pTarget )
{
if( FClassnameIs( pTarget->pev, "monster_male_assassin" ) || FClassnameIs( pTarget->pev, "monster_blkop_apache" ) || FClassnameIs( pTarget->pev, "monster_human_assassin" ) )
{
return R_NM;
}
return CBaseMonster::IRelationship( pTarget );
}
void CApache::NullThink( void )
{
StudioFrameAdvance();

View File

@ -68,6 +68,7 @@ public:
int Classify( void );
int ISoundMask( void);
void Shoot( void );
int IRelationship( CBaseEntity *pTarget );
void HandleAnimEvent( MonsterEvent_t *pEvent );
Schedule_t *GetSchedule( void );
Schedule_t *GetScheduleOfType( int Type );
@ -229,6 +230,20 @@ void CHAssassin::Shoot( void )
m_cAmmoLoaded--;
}
//=========================================================
// IRelationship - overridden because Human Grunts are
// BlackOps's nemesis.
//=========================================================
int CHAssassin::IRelationship( CBaseEntity *pTarget )
{
if( FClassnameIs( pTarget->pev, "monster_human_grunt" ) || ( FClassnameIs( pTarget->pev, "monster_apache" ) ) )
{
return R_NM;
}
return CBaseMonster::IRelationship( pTarget );
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.

View File

@ -257,12 +257,12 @@ void CHGrunt::SpeakSentence( void )
}
//=========================================================
// IRelationship - overridden because Alien Grunts are
// IRelationship - overridden because Black Ops are
// Human Grunt's nemesis.
//=========================================================
int CHGrunt::IRelationship( CBaseEntity *pTarget )
{
if( FClassnameIs( pTarget->pev, "monster_alien_grunt" ) || ( FClassnameIs( pTarget->pev, "monster_gargantua" ) ) )
if( FClassnameIs( pTarget->pev, "monster_male_assassin" ) || FClassnameIs( pTarget->pev, "monster_blkop_apache" ) || FClassnameIs( pTarget->pev, "monster_human_assassin" ) )
{
return R_NM;
}

112
dlls/rp/blkop_apache.cpp Normal file
View File

@ -0,0 +1,112 @@
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "effects.h"
#include "apache.h"
#define SF_WAITFORTRIGGER (0x04 | 0x40) // UNDONE: Fix!
#define SF_NOWRECKAGE 0x08
class CBlkopApache : public CApache
{
public:
void Spawn( void );
void Precache( void );
int IRelationship( CBaseEntity *pTarget );
};
LINK_ENTITY_TO_CLASS(monster_blkop_apache, CBlkopApache);
void CBlkopApache::Spawn(void)
{
Precache();
// motor
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_BBOX;
SET_MODEL(ENT(pev), "models/blkop_apache.mdl");
UTIL_SetSize(pev, Vector(-32, -32, -64), Vector(32, 32, 0));
UTIL_SetOrigin(pev, pev->origin);
pev->flags |= FL_MONSTER;
pev->takedamage = DAMAGE_AIM;
pev->health = gSkillData.apacheHealth;
m_flFieldOfView = -0.707; // 270 degrees
pev->sequence = 0;
ResetSequenceInfo();
pev->frame = RANDOM_LONG(0, 0xFF);
InitBoneControllers();
if (pev->spawnflags & SF_WAITFORTRIGGER)
{
SetUse(&CApache::StartupUse);
}
else
{
SetThink(&CApache::HuntThink);
SetTouch(&CApache::FlyTouch);
pev->nextthink = gpGlobals->time + 1.0;
}
m_iRockets = 10;
}
void CBlkopApache::Precache(void)
{
PRECACHE_MODEL("models/blkop_apache.mdl");
PRECACHE_SOUND("apache/ap_rotor1.wav");
PRECACHE_SOUND("apache/ap_rotor2.wav");
PRECACHE_SOUND("apache/ap_rotor3.wav");
PRECACHE_SOUND("apache/ap_whine1.wav");
PRECACHE_SOUND("weapons/mortarhit.wav");
m_iSpriteTexture = PRECACHE_MODEL("sprites/white.spr");
PRECACHE_SOUND("turret/tu_fire1.wav");
PRECACHE_MODEL("sprites/lgtning.spr");
m_iExplode = PRECACHE_MODEL("sprites/fexplo.spr");
m_iBodyGibs = PRECACHE_MODEL("models/blkop_bodygibs.mdl");
UTIL_PrecacheOther("hvr_rocket");
}
//=========================================================
// IRelationship - overridden because Human Grunt are
// Black Ops's nemesis.
//=========================================================
int CBlkopApache::IRelationship( CBaseEntity *pTarget )
{
if( FClassnameIs( pTarget->pev, "monster_apache" ) || FClassnameIs( pTarget->pev, "monster_human_grunt" ) )
{
return R_NM;
}
return CBaseMonster::IRelationship( pTarget );
}

169
dlls/rp/blkop_osprey.cpp Normal file
View File

@ -0,0 +1,169 @@
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "soundent.h"
#include "effects.h"
#include "customentity.h"
#include "osprey.h"
#define SF_WAITFORTRIGGER 0x40
#define MAX_CARRY OSPREY_MAX_CARRY
class CBlkopOsprey : public COsprey
{
public:
void Spawn( void );
void Precache( void );
void EXPORT FindAllThink(void);
CBaseMonster *MakeGrunt(Vector vecSrc);
};
LINK_ENTITY_TO_CLASS(monster_blkop_osprey, CBlkopOsprey);
void CBlkopOsprey::Spawn(void)
{
Precache();
// motor
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_BBOX;
SET_MODEL(ENT(pev), "models/blkop_osprey.mdl");
UTIL_SetSize(pev, Vector(-400, -400, -100), Vector(400, 400, 32));
UTIL_SetOrigin(pev, pev->origin);
pev->flags |= FL_MONSTER;
pev->takedamage = DAMAGE_YES;
m_flRightHealth = 200;
m_flLeftHealth = 200;
pev->health = 400;
m_flFieldOfView = 0; // 180 degrees
pev->sequence = 0;
ResetSequenceInfo();
pev->frame = RANDOM_LONG(0, 0xFF);
InitBoneControllers();
SetThink(&CBlkopOsprey::FindAllThink);
SetUse(&COsprey::CommandUse);
if (!(pev->spawnflags & SF_WAITFORTRIGGER))
{
pev->nextthink = gpGlobals->time + 1.0;
}
m_pos2 = pev->origin;
m_ang2 = pev->angles;
m_vel2 = pev->velocity;
}
void CBlkopOsprey::Precache(void)
{
UTIL_PrecacheOther("monster_male_assassin");
PRECACHE_MODEL("models/blkop_osprey.mdl");
PRECACHE_MODEL("models/HVR.mdl");
PRECACHE_SOUND("apache/ap_rotor4.wav");
PRECACHE_SOUND("weapons/mortarhit.wav");
m_iSpriteTexture = PRECACHE_MODEL("sprites/rope.spr");
m_iExplode = PRECACHE_MODEL("sprites/fexplo.spr");
m_iTailGibs = PRECACHE_MODEL("models/blkop_tailgibs.mdl");
m_iBodyGibs = PRECACHE_MODEL("models/blkop_bodygibs.mdl");
m_iEngineGibs = PRECACHE_MODEL("models/blkop_enginegibs.mdl");
}
void CBlkopOsprey::FindAllThink(void)
{
CBaseEntity *pEntity = NULL;
m_iUnits = 0;
while (m_iUnits < MAX_CARRY && (pEntity = UTIL_FindEntityByClassname(pEntity, "monster_male_assassin")) != NULL)
{
if (pEntity->IsAlive())
{
m_hGrunt[m_iUnits] = pEntity;
m_vecOrigin[m_iUnits] = pEntity->pev->origin;
m_iUnits++;
}
}
if (m_iUnits == 0)
{
ALERT(at_console, "osprey error: no assassins to resupply\n");
UTIL_Remove(this);
return;
}
SetThink(&COsprey::FlyThink);
pev->nextthink = gpGlobals->time + 0.1;
m_startTime = gpGlobals->time;
}
CBaseMonster *CBlkopOsprey::MakeGrunt(Vector vecSrc)
{
CBaseEntity *pEntity;
CBaseMonster *pGrunt;
TraceResult tr;
UTIL_TraceLine(vecSrc, vecSrc + Vector(0, 0, -4096.0), dont_ignore_monsters, ENT(pev), &tr);
if (tr.pHit && Instance(tr.pHit)->pev->solid != SOLID_BSP)
return NULL;
for (int i = 0; i < m_iUnits; i++)
{
if (m_hGrunt[i] == NULL || !m_hGrunt[i]->IsAlive())
{
if (m_hGrunt[i] != NULL && m_hGrunt[i]->pev->rendermode == kRenderNormal)
{
m_hGrunt[i]->SUB_StartFadeOut();
}
pEntity = Create("monster_male_assassin", vecSrc, pev->angles);
pGrunt = pEntity->MyMonsterPointer();
pGrunt->pev->movetype = MOVETYPE_FLY;
pGrunt->pev->velocity = Vector(0, 0, RANDOM_FLOAT(-196, -128));
pGrunt->SetActivity(ACT_GLIDE);
CBeam *pBeam = CBeam::BeamCreate("sprites/rope.spr", 10);
pBeam->PointEntInit(vecSrc + Vector(0, 0, 112), pGrunt->entindex());
pBeam->SetFlags(BEAM_FSOLID);
pBeam->SetColor(255, 255, 255);
pBeam->SetThink(&CBeam::SUB_Remove);
pBeam->pev->nextthink = gpGlobals->time + -4096.0 * tr.flFraction / pGrunt->pev->velocity.z + 0.5;
// ALERT( at_console, "%d at %.0f %.0f %.0f\n", i, m_vecOrigin[i].x, m_vecOrigin[i].y, m_vecOrigin[i].z );
pGrunt->m_vecLastPosition = m_vecOrigin[i];
m_hGrunt[i] = pGrunt;
return pGrunt;
}
}
// ALERT( at_console, "none dead\n");
return NULL;
}

392
dlls/rp/massn.cpp Normal file
View File

@ -0,0 +1,392 @@
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
//=========================================================
// Black Ops - Male Assassin
//=========================================================
#include "extdll.h"
#include "plane.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "schedule.h"
#include "animation.h"
#include "squadmonster.h"
#include "weapons.h"
#include "talkmonster.h"
#include "soundent.h"
#include "effects.h"
#include "customentity.h"
#include "hgrunt.h"
//=========================================================
// monster-specific DEFINE's
//=========================================================
#define MASSN_CLIP_SIZE 36 // how many bullets in a clip? - NOTE: 3 round burst sound, so keep as 3 * x!
// Weapon flags
#define MASSN_9MMAR (1 << 0)
#define MASSN_HANDGRENADE (1 << 1)
#define MASSN_GRENADELAUNCHER (1 << 2)
#define MASSN_SNIPERRIFLE (1 << 4)
// Body groups.
#define HEAD_GROUP 1
#define GUN_GROUP 2
// Head values
#define HEAD_WHITE 0
#define HEAD_BLACK 1
#define HEAD_GOGGLES 2
// Gun values
#define GUN_MP5 0
#define GUN_SNIPERRIFLE 1
#define GUN_NONE 2
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define MASSN_AE_KICK ( 3 )
#define MASSN_AE_BURST1 ( 4 )
#define MASSN_AE_CAUGHT_ENEMY ( 10 ) // grunt established sight with an enemy (player only) that had previously eluded the squad.
#define MASSN_AE_DROP_GUN ( 11 ) // grunt (probably dead) is dropping his mp5.
//=========================================================
// Purpose:
//=========================================================
class CMassn : public CHGrunt
{
public:
int Classify(void);
int IRelationship( CBaseEntity *pTarget );
void HandleAnimEvent(MonsterEvent_t *pEvent);
void Sniperrifle(void);
BOOL FOkToSpeak(void);
void Spawn( void );
void Precache( void );
void DeathSound(void);
void PainSound(void);
void IdleSound(void);
};
LINK_ENTITY_TO_CLASS(monster_male_assassin, CMassn)
LINK_ENTITY_TO_CLASS(monster_male_asssassin, CMassn)
//=========================================================
// Purpose:
//=========================================================
BOOL CMassn::FOkToSpeak(void)
{
return FALSE;
}
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
//=========================================================
int CMassn::Classify(void)
{
return CLASS_HUMAN_MILITARY;
}
//=========================================================
// Purpose:
//=========================================================
void CMassn::IdleSound(void)
{
}
//=========================================================
// IRelationship - overridden because Human Grunts are
// BlackOps's nemesis.
//=========================================================
int CMassn::IRelationship( CBaseEntity *pTarget )
{
if( FClassnameIs( pTarget->pev, "monster_human_grunt" ) || ( FClassnameIs( pTarget->pev, "monster_apache" ) ) )
{
return R_NM;
}
return CSquadMonster::IRelationship( pTarget );
}
//=========================================================
// Shoot
//=========================================================
void CMassn::Sniperrifle(void)
{
if (m_hEnemy == NULL)
{
return;
}
Vector vecShootOrigin = GetGunPosition();
Vector vecShootDir = ShootAtEnemy(vecShootOrigin);
UTIL_MakeVectors(pev->angles);
Vector vecShellVelocity = gpGlobals->v_right * RANDOM_FLOAT(40, 90) + gpGlobals->v_up * RANDOM_FLOAT(75, 200) + gpGlobals->v_forward * RANDOM_FLOAT(-40, 40);
EjectBrass(vecShootOrigin - vecShootDir * 24, vecShellVelocity, pev->angles.y, m_iBrassShell, TE_BOUNCE_SHELL);
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_1DEGREES, 2048, BULLET_PLAYER_357, 0); // shoot +-7.5 degrees
pev->effects |= EF_MUZZLEFLASH;
m_cAmmoLoaded--;// take away a bullet!
Vector angDir = UTIL_VecToAngles(vecShootDir);
SetBlending(0, angDir.x);
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//=========================================================
void CMassn::HandleAnimEvent(MonsterEvent_t *pEvent)
{
Vector vecShootDir;
Vector vecShootOrigin;
switch (pEvent->event)
{
case MASSN_AE_DROP_GUN:
{
Vector vecGunPos;
Vector vecGunAngles;
GetAttachment(0, vecGunPos, vecGunAngles);
// switch to body group with no gun.
SetBodygroup(GUN_GROUP, GUN_NONE);
// now spawn a gun.
if (FBitSet(pev->weapons, MASSN_SNIPERRIFLE))
{
//DropItem("weapon_sniperrifle", vecGunPos, vecGunAngles);
}
else
{
DropItem("weapon_9mmAR", vecGunPos, vecGunAngles);
}
if (FBitSet(pev->weapons, MASSN_GRENADELAUNCHER))
{
DropItem("ammo_ARgrenades", BodyTarget(pev->origin), vecGunAngles);
}
}
break;
case MASSN_AE_BURST1:
{
if (FBitSet(pev->weapons, MASSN_9MMAR))
{
Shoot();
// the first round of the three round burst plays the sound and puts a sound in the world sound list.
if (RANDOM_LONG(0, 1))
{
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "hgrunt/gr_mgun1.wav", 1, ATTN_NORM);
}
else
{
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "hgrunt/gr_mgun2.wav", 1, ATTN_NORM);
}
}
else if (FBitSet(pev->weapons, MASSN_SNIPERRIFLE))
{
Sniperrifle();
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/sniper_fire.wav", 1, ATTN_NORM);
}
CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, 384, 0.3);
}
break;
case MASSN_AE_KICK:
{
CBaseEntity *pHurt = Kick();
if (pHurt)
{
// SOUND HERE!
UTIL_MakeVectors(pev->angles);
pHurt->pev->punchangle.x = 15;
pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * 100 + gpGlobals->v_up * 50;
pHurt->TakeDamage(pev, pev, gSkillData.massnDmgKick, DMG_CLUB);
}
}
break;
case MASSN_AE_CAUGHT_ENEMY:
break;
default:
CHGrunt::HandleAnimEvent(pEvent);
break;
}
}
//=========================================================
// Spawn
//=========================================================
void CMassn::Spawn()
{
Precache();
SET_MODEL(ENT(pev), "models/massn.mdl");
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_RED;
pev->effects = 0;
pev->health = gSkillData.massnHealth;
m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
m_flNextGrenadeCheck = gpGlobals->time + 1;
m_flNextPainTime = gpGlobals->time;
m_iSentence = -1;
m_afCapability = bits_CAP_SQUAD | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
m_fEnemyEluded = FALSE;
m_fFirstEncounter = TRUE;// this is true when the grunt spawns, because he hasn't encountered an enemy yet.
m_HackedGunPos = Vector(0, 0, 55);
if (pev->weapons == 0)
{
// initialize to original values
pev->weapons = MASSN_9MMAR | MASSN_HANDGRENADE;
// pev->weapons = HGRUNT_SHOTGUN;
// pev->weapons = HGRUNT_9MMAR | HGRUNT_GRENADELAUNCHER;
}
if (FBitSet(pev->weapons, MASSN_SNIPERRIFLE))
{
SetBodygroup(GUN_GROUP, GUN_SNIPERRIFLE);
m_cClipSize = 5;
}
else
{
m_cClipSize = MASSN_CLIP_SIZE;
}
m_cAmmoLoaded = m_cClipSize;
if (RANDOM_LONG(0, 99) < 80)
pev->skin = 0; // light skin
else
pev->skin = 1; // dark skin
CTalkMonster::g_talkWaitTime = 0;
MonsterInit();
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CMassn::Precache()
{
PRECACHE_MODEL("models/massn.mdl");
PRECACHE_SOUND("hgrunt/gr_mgun1.wav");
PRECACHE_SOUND("hgrunt/gr_mgun2.wav");
PRECACHE_SOUND("hgrunt/gr_reload1.wav");
PRECACHE_SOUND("weapons/glauncher.wav");
PRECACHE_SOUND("weapons/sniper_fire.wav");
PRECACHE_SOUND("zombie/claw_miss2.wav");// because we use the basemonster SWIPE animation event
// get voice pitch
if (RANDOM_LONG(0, 1))
m_voicePitch = 109 + RANDOM_LONG(0, 7);
else
m_voicePitch = 100;
m_iBrassShell = PRECACHE_MODEL("models/shell.mdl");// brass shell
}
//=========================================================
// PainSound
//=========================================================
void CMassn::PainSound(void)
{
}
//=========================================================
// DeathSound
//=========================================================
void CMassn::DeathSound(void)
{
}
//=========================================================
// CAssassinRepel - when triggered, spawns a monster_male_assassin
// repelling down a line.
//=========================================================
class CAssassinRepel : public CHGruntRepel
{
public:
void Precache(void);
void EXPORT RepelUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
};
LINK_ENTITY_TO_CLASS(monster_assassin_repel, CAssassinRepel);
void CAssassinRepel::Precache(void)
{
UTIL_PrecacheOther("monster_male_assassin");
m_iSpriteTexture = PRECACHE_MODEL("sprites/rope.spr");
}
void CAssassinRepel::RepelUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
{
TraceResult tr;
UTIL_TraceLine(pev->origin, pev->origin + Vector(0, 0, -4096.0), dont_ignore_monsters, ENT(pev), &tr);
/*
if ( tr.pHit && Instance( tr.pHit )->pev->solid != SOLID_BSP)
return NULL;
*/
CBaseEntity *pEntity = Create("monster_male_assassin", pev->origin, pev->angles);
CBaseMonster *pGrunt = pEntity->MyMonsterPointer();
pGrunt->pev->movetype = MOVETYPE_FLY;
pGrunt->pev->velocity = Vector(0, 0, RANDOM_FLOAT(-196, -128));
pGrunt->SetActivity(ACT_GLIDE);
// UNDONE: position?
pGrunt->m_vecLastPosition = tr.vecEndPos;
CBeam *pBeam = CBeam::BeamCreate("sprites/rope.spr", 10);
pBeam->PointEntInit(pev->origin + Vector(0, 0, 112), pGrunt->entindex());
pBeam->SetFlags(BEAM_FSOLID);
pBeam->SetColor(255, 255, 255);
pBeam->SetThink(&CBeam::SUB_Remove);
pBeam->pev->nextthink = gpGlobals->time + -4096.0 * tr.flFraction / pGrunt->pev->velocity.z + 0.5;
UTIL_Remove(this);
}