From be17c4375c2f62b6d087ab4fdd40a4574ec2bbb3 Mon Sep 17 00:00:00 2001 From: "Bernt A. Eide" Date: Sat, 5 Jun 2021 20:13:51 +0200 Subject: [PATCH] - Removed unused HL1 code. --- MSShared/sharedutil.cpp | 4 - bin/client.dll | Bin 1170432 -> 1170432 bytes bin/ms.dll | Bin 1279488 -> 1279488 bytes dlls/Global/Gametype.cpp | 103 - dlls/Half-life/aflock.cpp | 916 --------- dlls/Half-life/agrunt.cpp | 1177 ----------- dlls/Half-life/airtank.cpp | 118 -- dlls/Half-life/apache.cpp | 1031 ---------- dlls/Half-life/barnacle.cpp | 440 ---- dlls/Half-life/barney.cpp | 822 -------- dlls/Half-life/bigmomma.cpp | 1207 ----------- dlls/Half-life/bloater.cpp | 215 -- dlls/Half-life/bullsquid.cpp | 1251 ------------ dlls/Half-life/controller.cpp | 1357 ------------- dlls/Half-life/crossbow.cpp | 592 ------ dlls/Half-life/crowbar.cpp | 329 --- dlls/Half-life/egon.cpp | 623 ------ dlls/Half-life/flyingmonster.cpp | 269 --- dlls/Half-life/flyingmonster.h | 50 - dlls/Half-life/gargantua.cpp | 1317 ------------ dlls/Half-life/gauss.cpp | 626 ------ dlls/Half-life/genericmonster.cpp | 140 -- dlls/Half-life/gman.cpp | 234 --- dlls/Half-life/h_ai.cpp | 193 -- dlls/Half-life/h_battery.cpp | 197 -- dlls/Half-life/h_cine.cpp | 237 --- dlls/Half-life/h_cycler.cpp | 441 ---- dlls/Half-life/handgrenade.cpp | 236 --- dlls/Half-life/hassassin.cpp | 976 --------- dlls/Half-life/headcrab.cpp | 542 ----- dlls/Half-life/healthkit.cpp | 251 --- dlls/Half-life/hgrunt.cpp | 2455 ----------------------- dlls/Half-life/hornet.cpp | 447 ----- dlls/Half-life/hornet.h | 57 - dlls/Half-life/hornetgun.cpp | 286 --- dlls/Half-life/houndeye.cpp | 1282 ------------ dlls/Half-life/ichthyosaur.cpp | 1085 ---------- dlls/Half-life/islave.cpp | 840 -------- dlls/Half-life/items.cpp | 331 --- dlls/Half-life/leech.cpp | 689 ------- dlls/Half-life/maprules.cpp | 888 -------- dlls/Half-life/maprules.h | 19 - dlls/Half-life/monstermaker.cpp | 292 --- dlls/Half-life/mortar.cpp | 314 --- dlls/Half-life/mp5.cpp | 362 ---- dlls/Half-life/nihilanth.cpp | 1774 ---------------- dlls/Half-life/osprey.cpp | 776 ------- dlls/Half-life/python.cpp | 296 --- dlls/Half-life/roach.cpp | 460 ----- dlls/Half-life/rpg.cpp | 667 ------ dlls/Half-life/satchel.cpp | 521 ----- dlls/Half-life/scientist.cpp | 1401 ------------- dlls/Half-life/shotgun.cpp | 414 ---- dlls/Half-life/singleplay_gamerules.cpp | 325 --- dlls/Half-life/sound.cpp | 8 +- dlls/Half-life/squadmonster.cpp | 613 ------ dlls/Half-life/squadmonster.h | 119 -- dlls/Half-life/squeakgrenade.cpp | 590 ------ dlls/Half-life/talkmonster.cpp | 1419 ------------- dlls/Half-life/talkmonster.h | 178 -- dlls/Half-life/teamplay_gamerules.cpp | 576 ------ dlls/Half-life/tempmonster.cpp | 117 -- dlls/Half-life/tentacle.cpp | 1029 ---------- dlls/Half-life/tripmine.cpp | 519 ----- dlls/Half-life/turret.cpp | 1283 ------------ dlls/Half-life/xen.cpp | 563 ------ dlls/Items/Shields/shield.cpp | 1 - dlls/Items/Shields/shieldglobal.h | 1 - dlls/Monsters/Bludgeon.cpp | 505 ----- dlls/Monsters/MonsterList.cpp | 46 - dlls/Monsters/zombie.cpp | 341 ---- dlls/Weapons/giattack.cpp | 1 - 72 files changed, 4 insertions(+), 39780 deletions(-) delete mode 100644 dlls/Global/Gametype.cpp delete mode 100644 dlls/Half-life/aflock.cpp delete mode 100644 dlls/Half-life/agrunt.cpp delete mode 100644 dlls/Half-life/airtank.cpp delete mode 100644 dlls/Half-life/apache.cpp delete mode 100644 dlls/Half-life/barnacle.cpp delete mode 100644 dlls/Half-life/barney.cpp delete mode 100644 dlls/Half-life/bigmomma.cpp delete mode 100644 dlls/Half-life/bloater.cpp delete mode 100644 dlls/Half-life/bullsquid.cpp delete mode 100644 dlls/Half-life/controller.cpp delete mode 100644 dlls/Half-life/crossbow.cpp delete mode 100644 dlls/Half-life/crowbar.cpp delete mode 100644 dlls/Half-life/egon.cpp delete mode 100644 dlls/Half-life/flyingmonster.cpp delete mode 100644 dlls/Half-life/flyingmonster.h delete mode 100644 dlls/Half-life/gargantua.cpp delete mode 100644 dlls/Half-life/gauss.cpp delete mode 100644 dlls/Half-life/genericmonster.cpp delete mode 100644 dlls/Half-life/gman.cpp delete mode 100644 dlls/Half-life/h_ai.cpp delete mode 100644 dlls/Half-life/h_battery.cpp delete mode 100644 dlls/Half-life/h_cine.cpp delete mode 100644 dlls/Half-life/h_cycler.cpp delete mode 100644 dlls/Half-life/handgrenade.cpp delete mode 100644 dlls/Half-life/hassassin.cpp delete mode 100644 dlls/Half-life/headcrab.cpp delete mode 100644 dlls/Half-life/healthkit.cpp delete mode 100644 dlls/Half-life/hgrunt.cpp delete mode 100644 dlls/Half-life/hornet.cpp delete mode 100644 dlls/Half-life/hornet.h delete mode 100644 dlls/Half-life/hornetgun.cpp delete mode 100644 dlls/Half-life/houndeye.cpp delete mode 100644 dlls/Half-life/ichthyosaur.cpp delete mode 100644 dlls/Half-life/islave.cpp delete mode 100644 dlls/Half-life/items.cpp delete mode 100644 dlls/Half-life/leech.cpp delete mode 100644 dlls/Half-life/maprules.cpp delete mode 100644 dlls/Half-life/maprules.h delete mode 100644 dlls/Half-life/monstermaker.cpp delete mode 100644 dlls/Half-life/mortar.cpp delete mode 100644 dlls/Half-life/mp5.cpp delete mode 100644 dlls/Half-life/nihilanth.cpp delete mode 100644 dlls/Half-life/osprey.cpp delete mode 100644 dlls/Half-life/python.cpp delete mode 100644 dlls/Half-life/roach.cpp delete mode 100644 dlls/Half-life/rpg.cpp delete mode 100644 dlls/Half-life/satchel.cpp delete mode 100644 dlls/Half-life/scientist.cpp delete mode 100644 dlls/Half-life/shotgun.cpp delete mode 100644 dlls/Half-life/singleplay_gamerules.cpp delete mode 100644 dlls/Half-life/squadmonster.cpp delete mode 100644 dlls/Half-life/squadmonster.h delete mode 100644 dlls/Half-life/squeakgrenade.cpp delete mode 100644 dlls/Half-life/talkmonster.cpp delete mode 100644 dlls/Half-life/talkmonster.h delete mode 100644 dlls/Half-life/teamplay_gamerules.cpp delete mode 100644 dlls/Half-life/tempmonster.cpp delete mode 100644 dlls/Half-life/tentacle.cpp delete mode 100644 dlls/Half-life/tripmine.cpp delete mode 100644 dlls/Half-life/turret.cpp delete mode 100644 dlls/Half-life/xen.cpp delete mode 100644 dlls/Items/Shields/shieldglobal.h delete mode 100644 dlls/Monsters/Bludgeon.cpp delete mode 100644 dlls/Monsters/MonsterList.cpp delete mode 100644 dlls/Monsters/zombie.cpp diff --git a/MSShared/sharedutil.cpp b/MSShared/sharedutil.cpp index 1081162c..c3f240ab 100644 --- a/MSShared/sharedutil.cpp +++ b/MSShared/sharedutil.cpp @@ -367,7 +367,3 @@ extern "C" char *strlwr(char *str) { return FStrEq( EngineFunc::GetString( m_string ), a ) ? true : false; }*/ - -//Needed to support sound.cpp -#include "talkmonster.h" -float CTalkMonster::g_talkWaitTime = 0; // time delay until it's ok to speak: used so that two NPCs don't talk at once diff --git a/bin/client.dll b/bin/client.dll index ccdc2285663833b6ec70af9bb9d204c9cd52c542..474553814e812e28c7da450e6f20b1fb3e75045b 100644 GIT binary patch delta 151 zcmZqJ;oh*reS-ocQ`f#`CB}9oMi6EKVrC#_0b*7lW&>h&Am#vKP9Ww2V(#rqj69EY z<+}FmPGA56CLj(2F%I)FFl+^4An4lHuB6Wc#Jt;;^!XmO3SQe~{@`2YUcW5|luT`u dgS{BHi*DtUp9-|R-OP(0hy}Krc?q7H2mm!eDTe?6 delta 151 zcmZqJ;oh*reS-ocQ|Gp3CB}9oMi6EKVrC#_0b*7lW&>h&Am#vKP9Ww2V(#rqj69EY zD8(!wkK~> ckQx7W(XD*)Q-PMZn|bjAvA}jSFTqn20r*TPBme*a diff --git a/bin/ms.dll b/bin/ms.dll index 533bfc388daef9eb7f13bf4f90ce41597a81abf5..f4b70e1d378b8915e3a82c83397a2e8b05de1bb4 100644 GIT binary patch delta 1836 zcmZuyTTB#J7@pag*!|CawYol6&jKCLxEo9^Pk*H5-(<>M zm*Z;9P38dItKERq4e*oO7W~E?6Fzx|x#VIV@A0dD4=^8^gQ7uZ00$ZwWM;O})9U!| zOyg_Qd;H>s2bU>|3L19{(|QZ7eY-h-BKKR zNbB5ATogXJ`voud;FQkowlSUCVULLanFqSD^5Tjh#$sz5hLNI@z=Vg2MG+iAf(x2kI0j!rV6W9 ziuI{P>PJ14!s9aF$@|J&^$?QCxdISk!im4U43Ailw2nh<&fp@*GtADht5smSLdzvu zInCZX`oVFiQywoR=$4YmIG7|sZkklE%8Q*mPU~F226e8=9+A#2Qy&o2vH<&f74z#jyt%-s?D23%PYpAfd-naLUGX?u0!e z3yS4XY;D~z-qbmVM%uz2N)ChsQN~({w1qrWyjEQauzB@}#4@wU0jQCz(42~QU_c~4mcj)-?2U|Vllwbvjb%V&YPZJtgDn?i^`we27VrT!3! zWD~ZVjaj#azAOZqy7*#DVr`;Mqy*e3nOJQN^hIb$Y#{W$6s%g&_%l6ces(qF!hv(n zJ>NOs{pQ}?i#^9L_8cE_GPdyO-E_u(gQ*PG4TS3k7^QB&*0;ozD*SaeS73@_`8U}L zn|v!)bCW&DTv4t=XovLEpN;fecl7j`JM3i}d#lP9`+J!ESa;qVVTaLC=mq#Soe*YsOk(@cjJI!8whnbH(`IjxuCneb;p&kcpE%@oG zosi(9Gc?{_(OB?_Ok#zL?14P2k>{bGT*haKjf|G_&F8yB*+?s0i|l$vU_aFKGwmh8 zM~uoBVpCXh?@K}K!!4CBGIJ_lV0twBxdWzg^75KXj7B%MG%W?CzG(-EhA=sX0Eq_0 zO)U~#g@lX=nS1FHBa9|_YR*KCDJxs-C}Xg&Aq$(zmzs0r`4o#XGpF(%)1yzH=`4&{ zDb%MDt)Fm^h=6TClMf>c-Z2Ex^94XePbdCzvI6G(v||ctb4Hedo~BQZetQ%|k1(=F zsbskOCl2|bE;6^0VA@NAQy|h&h;@+))&;R!z-^V6%%sX6F+JMdqw@nmtis2=893A-BXOJog7;erorc)>PC%j0U{Gu3RQ{Cd z(WQu?P;_Hc)Ap*o1*4q-2a$bUE>Xr>iFS55Nc?nc&Bx`{VCu0#ZaY#6Mq4jfC&E&Rww?#ZhHRPrPP|x7m2b0#)UFFvmTu>g zLt3mM-NukOl1ib1t4xPnvJx6^t1r<)D;K;Gp&?e|=W?sD?--&%nY3wC1~c1~!99s? zwW2b(rFY(;46>G6lyN_|o^3COps!L%G;;rO85p24Dqk5+G;?4)m>tXk<^)RvOIH%j z8Bcufp(>w9Z}+5X*yCA|Jf6@AlklkW!0tNrC{{e{Di+SxeA#rOx%q5cXUi8P?45Nf-r20+vU~8W zy}c7f!-s}${L#@=C;skMUQCG3I^o|+dH8|*ftOE*wz25{KbO4c;Ni z1oJ?A&x~CVmqRQ;+yFic`k093L`pDd8!l7$!C3J1qXD_(@<>lqd^FVgK{eOlo BeGC8q diff --git a/dlls/Global/Gametype.cpp b/dlls/Global/Gametype.cpp deleted file mode 100644 index 58c3e656..00000000 --- a/dlls/Global/Gametype.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "extdll.h" -#include "util.h" -#include "../cbase.h" -#include "../Player/player.h" -#include "MSGlobals.h" -#include "../Stats/statdefs.h" -// Entity that determines the Game type - -/*class CBasePlayerSpawnHuman : public CBaseEntity { - void Spawn( ) { pev->classname = MAKE_STRING("playerspawn_human"); } -}; -class CBasePlayerSpawnDwarf : public CBaseEntity { - void Spawn( ) { pev->classname = MAKE_STRING("playerspawn_dwarf"); } -}; -class CBasePlayerSpawnElf : public CBaseEntity { - void Spawn( ) { pev->classname = MAKE_STRING("playerspawn_elf"); } -}; -*/ -DLL_GLOBAL gametype_e GameType; -DLL_GLOBAL int bGameTypeInitialized = FALSE; - -LINK_ENTITY_TO_CLASS(playerspawn_human, CBaseEntity); -LINK_ENTITY_TO_CLASS(playerspawn_dwarf, CBaseEntity); -LINK_ENTITY_TO_CLASS(playerspawn_elf, CBaseEntity); - -BOOL IsSpawnPointValid(CBaseEntity *pPlayer, CBaseEntity *pSpot); - -CBaseEntity *GetAssaultSpawnSpot(CBasePlayer *pPlayer) -{ - CBaseEntity *pFirstSpot, *pSpot = NULL; - char *SpawnSpotName; - int RaceID, n = 0; - - if (!pPlayer->Race) - RaceID = RANDOM_LONG(0, RACE_NUM - 1); - else - RaceID = pPlayer->Race->id; - - if (RaceID == RACE_HUMAN) - SpawnSpotName = "playerspawn_human"; - else if (RaceID == RACE_DWARF) - SpawnSpotName = "playerspawn_dwarf"; - else if (RaceID == RACE_ELF) - SpawnSpotName = "playerspawn_elf"; - - pFirstSpot = UTIL_FindEntityByClassname(pSpot, SpawnSpotName); - if (FNullEnt(pFirstSpot)) - { - ALERT(at_console, "COULD NOT FIND ONE %s entity to SPAWN!!\n", SpawnSpotName); - return NULL; - } - - while (pSpot != pFirstSpot) - { - // check if pSpot is valid - if (pSpot && IsSpawnPointValid(pPlayer, pSpot) && RANDOM_LONG(0, 1)) - break; - n++; - if (n > 255) - { - ALERT(at_console, "RACE SPAWN ERROR: Couldn't loop back to first %s\n", SpawnSpotName); - return NULL; - } - // increment pSpot - if (!pSpot) - pSpot = UTIL_FindEntityByClassname(pFirstSpot, SpawnSpotName); - else - pSpot = UTIL_FindEntityByClassname(pSpot, SpawnSpotName); - } - - if (pSpot == pFirstSpot && !IsSpawnPointValid(pPlayer, pSpot)) - { - //No valid spots except the first and somebody's standing there... - //!!Broken!, the traceline below doesn't account for the player thats blocking my spawn - ALERT(at_console, "Telefrag!\n"); - int i = 0; - BOOL bCanBreak = FALSE; - TraceResult tr; - while (!bCanBreak && i < 100) - { - float fAngle = RANDOM_FLOAT(0, 359); - Vector vDir, vecSrc, vecEnd; - UTIL_MakeVectorsPrivate(Vector(0, fAngle, 0), vDir, NULL, NULL); - vecSrc = pSpot->pev->origin; - vecEnd = pSpot->pev->origin + vDir * 250; - UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, pSpot->edict(), &tr); - if (tr.flFraction >= 1.0) - bCanBreak = TRUE; - i++; - } - if (bCanBreak) - { - ALERT(at_console, "Avoided a Telefrag!\n"); - pSpot = GetClassPtr((CBaseEntity *)NULL); - pSpot->pev->origin = tr.vecEndPos; - pSpot->pev->flags |= FL_KILLME; - pSpot->pev->effects |= EF_NODRAW; - } - else - ALERT(at_console, "Sorry, there's no where to spawn!!!\n"); - } - return pSpot; -} \ No newline at end of file diff --git a/dlls/Half-life/aflock.cpp b/dlls/Half-life/aflock.cpp deleted file mode 100644 index 5ff9bd8e..00000000 --- a/dlls/Half-life/aflock.cpp +++ /dev/null @@ -1,916 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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 "squadmonster.h" - -#define AFLOCK_MAX_RECRUIT_RADIUS 1024 -#define AFLOCK_FLY_SPEED 125 -#define AFLOCK_TURN_RATE 75 -#define AFLOCK_ACCELERATE 10 -#define AFLOCK_CHECK_DIST 192 -#define AFLOCK_TOO_CLOSE 100 -#define AFLOCK_TOO_FAR 256 - -//========================================================= -//========================================================= -class CFlockingFlyerFlock : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void KeyValue(KeyValueData *pkvd); - void SpawnFlock(void); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - // Sounds are shared by the flock - static void PrecacheFlockSounds(void); - - int m_cFlockSize; - float m_flFlockRadius; -}; - -TYPEDESCRIPTION CFlockingFlyerFlock::m_SaveData[] = - { - DEFINE_FIELD(CFlockingFlyerFlock, m_cFlockSize, FIELD_INTEGER), - DEFINE_FIELD(CFlockingFlyerFlock, m_flFlockRadius, FIELD_FLOAT), -}; - -IMPLEMENT_SAVERESTORE(CFlockingFlyerFlock, CBaseMonster); - -//========================================================= -//========================================================= -class CFlockingFlyer : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void SpawnCommonCode(void); - void EXPORT IdleThink(void); - void BoidAdvanceFrame(void); - void EXPORT FormFlock(void); - void EXPORT Start(void); - void EXPORT FlockLeaderThink(void); - void EXPORT FlockFollowerThink(void); - void EXPORT FallHack(void); - void MakeSound(void); - void AlertFlock(void); - void SpreadFlock(void); - void SpreadFlock2(void); - void Killed(entvars_t *pevAttacker, int iGib); - void Poop(void); - BOOL FPathBlocked(void); - //void KeyValue( KeyValueData *pkvd ); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - int IsLeader(void) { return m_pSquadLeader == this; } - int InSquad(void) { return m_pSquadLeader != NULL; } - int SquadCount(void); - void SquadRemove(CFlockingFlyer *pRemove); - void SquadUnlink(void); - void SquadAdd(CFlockingFlyer *pAdd); - void SquadDisband(void); - - CFlockingFlyer *m_pSquadLeader; - CFlockingFlyer *m_pSquadNext; - BOOL m_fTurning; // is this boid turning? - BOOL m_fCourseAdjust; // followers set this flag TRUE to override flocking while they avoid something - BOOL m_fPathBlocked; // TRUE if there is an obstacle ahead - Vector m_vecReferencePoint; // last place we saw leader - Vector m_vecAdjustedVelocity; // adjusted velocity (used when fCourseAdjust is TRUE) - float m_flGoalSpeed; - float m_flLastBlockedTime; - float m_flFakeBlockedTime; - float m_flAlertTime; - float m_flFlockNextSoundTime; -}; -LINK_ENTITY_TO_CLASS(monster_flyer, CFlockingFlyer); -LINK_ENTITY_TO_CLASS(monster_flyer_flock, CFlockingFlyerFlock); - -TYPEDESCRIPTION CFlockingFlyer::m_SaveData[] = - { - DEFINE_FIELD(CFlockingFlyer, m_pSquadLeader, FIELD_CLASSPTR), - DEFINE_FIELD(CFlockingFlyer, m_pSquadNext, FIELD_CLASSPTR), - DEFINE_FIELD(CFlockingFlyer, m_fTurning, FIELD_BOOLEAN), - DEFINE_FIELD(CFlockingFlyer, m_fCourseAdjust, FIELD_BOOLEAN), - DEFINE_FIELD(CFlockingFlyer, m_fPathBlocked, FIELD_BOOLEAN), - DEFINE_FIELD(CFlockingFlyer, m_vecReferencePoint, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CFlockingFlyer, m_vecAdjustedVelocity, FIELD_VECTOR), - DEFINE_FIELD(CFlockingFlyer, m_flGoalSpeed, FIELD_FLOAT), - DEFINE_FIELD(CFlockingFlyer, m_flLastBlockedTime, FIELD_TIME), - DEFINE_FIELD(CFlockingFlyer, m_flFakeBlockedTime, FIELD_TIME), - DEFINE_FIELD(CFlockingFlyer, m_flAlertTime, FIELD_TIME), - // DEFINE_FIELD( CFlockingFlyer, m_flFlockNextSoundTime, FIELD_TIME ), // don't need to save -}; - -IMPLEMENT_SAVERESTORE(CFlockingFlyer, CBaseMonster); - -//========================================================= -//========================================================= -void CFlockingFlyerFlock ::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "iFlockSize")) - { - m_cFlockSize = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "flFlockRadius")) - { - m_flFlockRadius = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } -} - -//========================================================= -//========================================================= -void CFlockingFlyerFlock ::Spawn() -{ - Precache(); - SpawnFlock(); - - REMOVE_ENTITY(ENT(pev)); // dump the spawn ent -} - -//========================================================= -//========================================================= -void CFlockingFlyerFlock ::Precache() -{ - //PRECACHE_MODEL("models/aflock.mdl"); - PRECACHE_MODEL("models/boid.mdl"); - - PrecacheFlockSounds(); -} - -void CFlockingFlyerFlock ::PrecacheFlockSounds(void) -{ - PRECACHE_SOUND("boid/boid_alert1.wav"); - PRECACHE_SOUND("boid/boid_alert2.wav"); - - PRECACHE_SOUND("boid/boid_idle1.wav"); - PRECACHE_SOUND("boid/boid_idle2.wav"); -} - -//========================================================= -//========================================================= -void CFlockingFlyerFlock ::SpawnFlock(void) -{ - float R = m_flFlockRadius; - int iCount; - Vector vecSpot; - CFlockingFlyer *pBoid, *pLeader; - - pLeader = pBoid = NULL; - - for (iCount = 0; iCount < m_cFlockSize; iCount++) - { - pBoid = GetClassPtr((CFlockingFlyer *)NULL); - - if (!pLeader) - { - // make this guy the leader. - pLeader = pBoid; - - pLeader->m_pSquadLeader = pLeader; - pLeader->m_pSquadNext = NULL; - } - - vecSpot.x = RANDOM_FLOAT(-R, R); - vecSpot.y = RANDOM_FLOAT(-R, R); - vecSpot.z = RANDOM_FLOAT(0, 16); - vecSpot = pev->origin + vecSpot; - - UTIL_SetOrigin(pBoid->pev, vecSpot); - pBoid->pev->movetype = MOVETYPE_FLY; - pBoid->SpawnCommonCode(); - pBoid->pev->flags &= ~FL_ONGROUND; - pBoid->pev->velocity = g_vecZero; - pBoid->pev->angles = pev->angles; - - pBoid->pev->frame = 0; - pBoid->pev->nextthink = gpGlobals->time + 0.2; - pBoid->SetThink(CFlockingFlyer ::IdleThink); - - if (pBoid != pLeader) - { - pLeader->SquadAdd(pBoid); - } - } -} - -//========================================================= -//========================================================= -void CFlockingFlyer ::Spawn() -{ - Precache(); - SpawnCommonCode(); - - pev->frame = 0; - pev->nextthink = gpGlobals->time + 0.1; - SetThink(IdleThink); -} - -//========================================================= -//========================================================= -void CFlockingFlyer ::Precache() -{ - //PRECACHE_MODEL("models/aflock.mdl"); - PRECACHE_MODEL("models/boid.mdl"); - CFlockingFlyerFlock::PrecacheFlockSounds(); -} - -//========================================================= -//========================================================= -void CFlockingFlyer ::MakeSound(void) -{ - if (m_flAlertTime > gpGlobals->time) - { - // make agitated sounds - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "boid/boid_alert1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "boid/boid_alert2.wav", 1, ATTN_NORM); - break; - } - - return; - } - - // make normal sound - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "boid/boid_idle1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "boid/boid_idle2.wav", 1, ATTN_NORM); - break; - } -} - -//========================================================= -//========================================================= -void CFlockingFlyer ::Killed(entvars_t *pevAttacker, int iGib) -{ - CFlockingFlyer *pSquad; - - pSquad = (CFlockingFlyer *)m_pSquadLeader; - - while (pSquad) - { - pSquad->m_flAlertTime = gpGlobals->time + 15; - pSquad = (CFlockingFlyer *)pSquad->m_pSquadNext; - } - - if (m_pSquadLeader) - { - m_pSquadLeader->SquadRemove(this); - } - - pev->deadflag = DEAD_DEAD; - - pev->framerate = 0; - pev->effects = EF_NOINTERP; - - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); - pev->movetype = MOVETYPE_TOSS; - - SetThink(FallHack); - pev->nextthink = gpGlobals->time + 0.1; -} - -void CFlockingFlyer ::FallHack(void) -{ - if (pev->flags & FL_ONGROUND) - { - if (!FClassnameIs(pev->groundentity, "worldspawn")) - { - pev->flags &= ~FL_ONGROUND; - pev->nextthink = gpGlobals->time + 0.1; - } - else - { - pev->velocity = g_vecZero; - SetThink(NULL); - } - } -} - -//========================================================= -//========================================================= -void CFlockingFlyer ::SpawnCommonCode() -{ - pev->deadflag = DEAD_NO; - pev->classname = MAKE_STRING("monster_flyer"); - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_FLY; - pev->takedamage = DAMAGE_NO; - pev->health = 1; - - m_fPathBlocked = FALSE; // obstacles will be detected - m_flFieldOfView = 0.2; - - //SET_MODEL(ENT(pev), "models/aflock.mdl"); - SET_MODEL(ENT(pev), "models/boid.mdl"); - - // UTIL_SetSize(pev, Vector(0,0,0), Vector(0,0,0)); - UTIL_SetSize(pev, Vector(-5, -5, 0), Vector(5, 5, 2)); -} - -//========================================================= -//========================================================= -void CFlockingFlyer ::BoidAdvanceFrame() -{ - float flapspeed = (pev->speed - pev->armorvalue) / AFLOCK_ACCELERATE; - pev->armorvalue = pev->armorvalue * .8 + pev->speed * .2; - - if (flapspeed < 0) - flapspeed = -flapspeed; - if (flapspeed < 0.25) - flapspeed = 0.25; - if (flapspeed > 1.9) - flapspeed = 1.9; - - pev->framerate = flapspeed; - - // lean - pev->avelocity.x = -(pev->angles.x + flapspeed * 5); - - // bank - pev->avelocity.z = -(pev->angles.z + pev->avelocity.y); - - // pev->framerate = flapspeed; - StudioFrameAdvance(0.1); -} - -//========================================================= -//========================================================= -void CFlockingFlyer ::IdleThink(void) -{ - pev->nextthink = gpGlobals->time + 0.2; - - // see if there's a client in the same pvs as the monster - if (!FNullEnt(FIND_CLIENT_IN_PVS(edict()))) - { - SetThink(Start); - pev->nextthink = gpGlobals->time + 0.1; - } -} - -//========================================================= -// Start - player enters the pvs, so get things going. -//========================================================= -void CFlockingFlyer ::Start(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - if (IsLeader()) - { - SetThink(FlockLeaderThink); - } - else - { - SetThink(FlockFollowerThink); - } - - /* - Vector vecTakeOff; - vecTakeOff = Vector ( 0 , 0 , 0 ); - - vecTakeOff.z = 50 + RANDOM_FLOAT ( 0, 100 ); - vecTakeOff.x = 20 - RANDOM_FLOAT ( 0, 40); - vecTakeOff.y = 20 - RANDOM_FLOAT ( 0, 40); - - pev->velocity = vecTakeOff; - - - pev->speed = pev->velocity.Length(); - pev->sequence = 0; -*/ - SetActivity(ACT_FLY); - ResetSequenceInfo(); - BoidAdvanceFrame(); - - pev->speed = AFLOCK_FLY_SPEED; // no delay! -} - -//========================================================= -// Leader boid calls this to form a flock from surrounding boids -//========================================================= -void CFlockingFlyer ::FormFlock(void) -{ - if (!InSquad()) - { - // I am my own leader - m_pSquadLeader = this; - m_pSquadNext = NULL; - int squadCount = 1; - - CBaseEntity *pEntity = NULL; - - while ((pEntity = UTIL_FindEntityInSphere(pEntity, pev->origin, AFLOCK_MAX_RECRUIT_RADIUS)) != NULL) - { - CBaseMonster *pRecruit = pEntity->MyMonsterPointer(); - - if (pRecruit && pRecruit != this && pRecruit->IsAlive() && !pRecruit->m_pCine) - { - // Can we recruit this guy? - if (FClassnameIs(pRecruit->pev, "monster_flyer")) - { - squadCount++; - SquadAdd((CFlockingFlyer *)pRecruit); - } - } - } - } - - SetThink(IdleThink); // now that flock is formed, go to idle and wait for a player to come along. - pev->nextthink = gpGlobals->time; -} - -//========================================================= -// Searches for boids that are too close and pushes them away -//========================================================= -void CFlockingFlyer ::SpreadFlock() -{ - Vector vecDir; - float flSpeed; // holds vector magnitude while we fiddle with the direction - - CFlockingFlyer *pList = m_pSquadLeader; - while (pList) - { - if (pList != this && (pev->origin - pList->pev->origin).Length() <= AFLOCK_TOO_CLOSE) - { - // push the other away - vecDir = (pList->pev->origin - pev->origin); - vecDir = vecDir.Normalize(); - - // store the magnitude of the other boid's velocity, and normalize it so we - // can average in a course that points away from the leader. - flSpeed = pList->pev->velocity.Length(); - pList->pev->velocity = pList->pev->velocity.Normalize(); - pList->pev->velocity = (pList->pev->velocity + vecDir) * 0.5; - pList->pev->velocity = pList->pev->velocity * flSpeed; - } - - pList = pList->m_pSquadNext; - } -} - -//========================================================= -// Alters the caller's course if he's too close to others -// -// This function should **ONLY** be called when Caller's velocity is normalized!! -//========================================================= -void CFlockingFlyer ::SpreadFlock2() -{ - Vector vecDir; - - CFlockingFlyer *pList = m_pSquadLeader; - while (pList) - { - if (pList != this && (pev->origin - pList->pev->origin).Length() <= AFLOCK_TOO_CLOSE) - { - vecDir = (pev->origin - pList->pev->origin); - vecDir = vecDir.Normalize(); - - pev->velocity = (pev->velocity + vecDir); - } - - pList = pList->m_pSquadNext; - } -} - -//========================================================= -// FBoidPathBlocked - returns TRUE if there is an obstacle ahead -//========================================================= -BOOL CFlockingFlyer ::FPathBlocked() -{ - TraceResult tr; - Vector vecDist; // used for general measurements - Vector vecDir; // used for general measurements - BOOL fBlocked; - - if (m_flFakeBlockedTime > gpGlobals->time) - { - m_flLastBlockedTime = gpGlobals->time; - return TRUE; - } - - // use VELOCITY, not angles, not all boids point the direction they are flying - //vecDir = UTIL_VecToAngles( pevBoid->velocity ); - UTIL_MakeVectors(pev->angles); - - fBlocked = FALSE; // assume the way ahead is clear - - // check for obstacle ahead - UTIL_TraceLine(pev->origin, pev->origin + gpGlobals->v_forward * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); - if (tr.flFraction != 1.0) - { - m_flLastBlockedTime = gpGlobals->time; - fBlocked = TRUE; - } - - // extra wide checks - UTIL_TraceLine(pev->origin + gpGlobals->v_right * 12, pev->origin + gpGlobals->v_right * 12 + gpGlobals->v_forward * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); - if (tr.flFraction != 1.0) - { - m_flLastBlockedTime = gpGlobals->time; - fBlocked = TRUE; - } - - UTIL_TraceLine(pev->origin - gpGlobals->v_right * 12, pev->origin - gpGlobals->v_right * 12 + gpGlobals->v_forward * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); - if (tr.flFraction != 1.0) - { - m_flLastBlockedTime = gpGlobals->time; - fBlocked = TRUE; - } - - if (!fBlocked && gpGlobals->time - m_flLastBlockedTime > 6) - { - // not blocked, and it's been a few seconds since we've actually been blocked. - m_flFakeBlockedTime = gpGlobals->time + RANDOM_LONG(1, 3); - } - - return fBlocked; -} - -//========================================================= -// Leader boids use this think every tenth -//========================================================= -void CFlockingFlyer ::FlockLeaderThink(void) -{ - TraceResult tr; - Vector vecDist; // used for general measurements - Vector vecDir; // used for general measurements - int cProcessed = 0; // keep track of how many other boids we've processed - float flLeftSide; - float flRightSide; - - pev->nextthink = gpGlobals->time + 0.1; - - UTIL_MakeVectors(pev->angles); - - // is the way ahead clear? - if (!FPathBlocked()) - { - // if the boid is turning, stop the trend. - if (m_fTurning) - { - m_fTurning = FALSE; - pev->avelocity.y = 0; - } - - m_fPathBlocked = FALSE; - - if (pev->speed <= AFLOCK_FLY_SPEED) - pev->speed += 5; - - pev->velocity = gpGlobals->v_forward * pev->speed; - - BoidAdvanceFrame(); - - return; - } - - // IF we get this far in the function, the leader's path is blocked! - m_fPathBlocked = TRUE; - - if (!m_fTurning) // something in the way and boid is not already turning to avoid - { - // measure clearance on left and right to pick the best dir to turn - UTIL_TraceLine(pev->origin, pev->origin + gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); - vecDist = (tr.vecEndPos - pev->origin); - flRightSide = vecDist.Length(); - - UTIL_TraceLine(pev->origin, pev->origin - gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); - vecDist = (tr.vecEndPos - pev->origin); - flLeftSide = vecDist.Length(); - - // turn right if more clearance on right side - if (flRightSide > flLeftSide) - { - pev->avelocity.y = -AFLOCK_TURN_RATE; - m_fTurning = TRUE; - } - // default to left turn :) - else if (flLeftSide > flRightSide) - { - pev->avelocity.y = AFLOCK_TURN_RATE; - m_fTurning = TRUE; - } - else - { - // equidistant. Pick randomly between left and right. - m_fTurning = TRUE; - - if (RANDOM_LONG(0, 1) == 0) - { - pev->avelocity.y = AFLOCK_TURN_RATE; - } - else - { - pev->avelocity.y = -AFLOCK_TURN_RATE; - } - } - } - SpreadFlock(); - - pev->velocity = gpGlobals->v_forward * pev->speed; - - // check and make sure we aren't about to plow into the ground, don't let it happen - UTIL_TraceLine(pev->origin, pev->origin - gpGlobals->v_up * 16, ignore_monsters, ENT(pev), &tr); - if (tr.flFraction != 1.0 && pev->velocity.z < 0) - pev->velocity.z = 0; - - // maybe it did, though. - if (FBitSet(pev->flags, FL_ONGROUND)) - { - UTIL_SetOrigin(pev, pev->origin + Vector(0, 0, 1)); - pev->velocity.z = 0; - } - - if (m_flFlockNextSoundTime < gpGlobals->time) - { - MakeSound(); - m_flFlockNextSoundTime = gpGlobals->time + RANDOM_FLOAT(1, 3); - } - - BoidAdvanceFrame(); - - return; -} - -//========================================================= -// follower boids execute this code when flocking -//========================================================= -void CFlockingFlyer ::FlockFollowerThink(void) -{ - TraceResult tr; - Vector vecDist; - Vector vecDir; - Vector vecDirToLeader; - float flDistToLeader; - - pev->nextthink = gpGlobals->time + 0.1; - - if (IsLeader() || !InSquad()) - { - // the leader has been killed and this flyer suddenly finds himself the leader. - SetThink(FlockLeaderThink); - return; - } - - vecDirToLeader = (m_pSquadLeader->pev->origin - pev->origin); - flDistToLeader = vecDirToLeader.Length(); - - // match heading with leader - pev->angles = m_pSquadLeader->pev->angles; - - // - // We can see the leader, so try to catch up to it - // - if (FInViewCone(m_pSquadLeader)) - { - // if we're too far away, speed up - if (flDistToLeader > AFLOCK_TOO_FAR) - { - m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 1.5; - } - - // if we're too close, slow down - else if (flDistToLeader < AFLOCK_TOO_CLOSE) - { - m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 0.5; - } - } - else - { - // wait up! the leader isn't out in front, so we slow down to let him pass - m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 0.5; - } - - SpreadFlock2(); - - pev->speed = pev->velocity.Length(); - pev->velocity = pev->velocity.Normalize(); - - // if we are too far from leader, average a vector towards it into our current velocity - if (flDistToLeader > AFLOCK_TOO_FAR) - { - vecDirToLeader = vecDirToLeader.Normalize(); - pev->velocity = (pev->velocity + vecDirToLeader) * 0.5; - } - - // clamp speeds and handle acceleration - if (m_flGoalSpeed > AFLOCK_FLY_SPEED * 2) - { - m_flGoalSpeed = AFLOCK_FLY_SPEED * 2; - } - - if (pev->speed < m_flGoalSpeed) - { - pev->speed += AFLOCK_ACCELERATE; - } - else if (pev->speed > m_flGoalSpeed) - { - pev->speed -= AFLOCK_ACCELERATE; - } - - pev->velocity = pev->velocity * pev->speed; - - BoidAdvanceFrame(); -} - -/* - // Is this boid's course blocked? - if ( FBoidPathBlocked (pev) ) - { - // course is still blocked from last time. Just keep flying along adjusted - // velocity - if ( m_fCourseAdjust ) - { - pev->velocity = m_vecAdjustedVelocity * pev->speed; - return; - } - else // set course adjust flag and calculate adjusted velocity - { - m_fCourseAdjust = TRUE; - - // use VELOCITY, not angles, not all boids point the direction they are flying - //vecDir = UTIL_VecToAngles( pev->velocity ); - //UTIL_MakeVectors ( vecDir ); - - UTIL_MakeVectors ( pev->angles ); - - // measure clearance on left and right to pick the best dir to turn - UTIL_TraceLine(pev->origin, pev->origin + gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); - vecDist = (tr.vecEndPos - pev->origin); - flRightSide = vecDist.Length(); - - UTIL_TraceLine(pev->origin, pev->origin - gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); - vecDist = (tr.vecEndPos - pev->origin); - flLeftSide = vecDist.Length(); - - // slide right if more clearance on right side - if ( flRightSide > flLeftSide ) - { - m_vecAdjustedVelocity = gpGlobals->v_right; - } - // else slide left - else - { - m_vecAdjustedVelocity = gpGlobals->v_right * -1; - } - } - return; - } - - // if we make it this far, boids path is CLEAR! - m_fCourseAdjust = FALSE; -*/ - -//========================================================= -// -// SquadUnlink(), Unlink the squad pointers. -// -//========================================================= -void CFlockingFlyer ::SquadUnlink(void) -{ - m_pSquadLeader = NULL; - m_pSquadNext = NULL; -} - -//========================================================= -// -// SquadAdd(), add pAdd to my squad -// -//========================================================= -void CFlockingFlyer ::SquadAdd(CFlockingFlyer *pAdd) -{ - ASSERT(pAdd != NULL); - ASSERT(!pAdd->InSquad()); - ASSERT(this->IsLeader()); - - pAdd->m_pSquadNext = m_pSquadNext; - m_pSquadNext = pAdd; - pAdd->m_pSquadLeader = this; -} -//========================================================= -// -// SquadRemove(), remove pRemove from my squad. -// If I am pRemove, promote m_pSquadNext to leader -// -//========================================================= -void CFlockingFlyer ::SquadRemove(CFlockingFlyer *pRemove) -{ - ASSERT(pRemove != NULL); - ASSERT(this->IsLeader()); - ASSERT(pRemove->m_pSquadLeader == this); - - if (SquadCount() > 2) - { - // Removing the leader, promote m_pSquadNext to leader - if (pRemove == this) - { - CFlockingFlyer *pLeader = m_pSquadNext; - - // copy the enemy LKP to the new leader - pLeader->m_vecEnemyLKP = m_vecEnemyLKP; - - if (pLeader) - { - CFlockingFlyer *pList = pLeader; - - while (pList) - { - pList->m_pSquadLeader = pLeader; - pList = pList->m_pSquadNext; - } - } - SquadUnlink(); - } - else // removing a node - { - CFlockingFlyer *pList = this; - - // Find the node before pRemove - while (pList->m_pSquadNext != pRemove) - { - // assert to test valid list construction - ASSERT(pList->m_pSquadNext != NULL); - pList = pList->m_pSquadNext; - } - // List validity - ASSERT(pList->m_pSquadNext == pRemove); - - // Relink without pRemove - pList->m_pSquadNext = pRemove->m_pSquadNext; - - // Unlink pRemove - pRemove->SquadUnlink(); - } - } - else - SquadDisband(); -} -//========================================================= -// -// SquadCount(), return the number of members of this squad -// callable from leaders & followers -// -//========================================================= -int CFlockingFlyer ::SquadCount(void) -{ - CFlockingFlyer *pList = m_pSquadLeader; - int squadCount = 0; - while (pList) - { - squadCount++; - pList = pList->m_pSquadNext; - } - - return squadCount; -} - -//========================================================= -// -// SquadDisband(), Unlink all squad members -// -//========================================================= -void CFlockingFlyer ::SquadDisband(void) -{ - CFlockingFlyer *pList = m_pSquadLeader; - CFlockingFlyer *pNext; - - while (pList) - { - pNext = pList->m_pSquadNext; - pList->SquadUnlink(); - pList = pNext; - } -} diff --git a/dlls/Half-life/agrunt.cpp b/dlls/Half-life/agrunt.cpp deleted file mode 100644 index 055190cc..00000000 --- a/dlls/Half-life/agrunt.cpp +++ /dev/null @@ -1,1177 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// Agrunt - Dominant, warlike alien grunt monster -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" -#include "squadmonster.h" -#include "weapons.h" -#include "soundent.h" -#include "hornet.h" - -//========================================================= -// monster-specific schedule types -//========================================================= -enum -{ - SCHED_AGRUNT_SUPPRESS = LAST_COMMON_SCHEDULE + 1, - SCHED_AGRUNT_THREAT_DISPLAY, -}; - -//========================================================= -// monster-specific tasks -//========================================================= -enum -{ - TASK_AGRUNT_SETUP_HIDE_ATTACK = LAST_COMMON_TASK + 1, - TASK_AGRUNT_GET_PATH_TO_ENEMY_CORPSE, -}; - -int iAgruntMuzzleFlash; - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define AGRUNT_AE_HORNET1 ( 1 ) -#define AGRUNT_AE_HORNET2 ( 2 ) -#define AGRUNT_AE_HORNET3 ( 3 ) -#define AGRUNT_AE_HORNET4 ( 4 ) -#define AGRUNT_AE_HORNET5 ( 5 ) -// some events are set up in the QC file that aren't recognized by the code yet. -#define AGRUNT_AE_PUNCH ( 6 ) -#define AGRUNT_AE_BITE ( 7 ) - -#define AGRUNT_AE_LEFT_FOOT ( 10 ) -#define AGRUNT_AE_RIGHT_FOOT ( 11 ) - -#define AGRUNT_AE_LEFT_PUNCH ( 12 ) -#define AGRUNT_AE_RIGHT_PUNCH ( 13 ) - - - -#define AGRUNT_MELEE_DIST 100 - -class CAGrunt : public CSquadMonster -{ -public: - void Spawn( void ); - void Precache( void ); - void SetYawSpeed ( void ); - int Classify ( void ); - int ISoundMask ( void ); - void HandleAnimEvent( MonsterEvent_t *pEvent ); - void SetObjectCollisionBox( void ) - { - pev->absmin = pev->origin + Vector( -32, -32, 0 ); - pev->absmax = pev->origin + Vector( 32, 32, 85 ); - } - - Schedule_t* GetSchedule ( void ); - Schedule_t* GetScheduleOfType ( int Type ); - BOOL FCanCheckAttacks ( void ); - BOOL CheckMeleeAttack1 ( float flDot, float flDist ); - BOOL CheckRangeAttack1 ( float flDot, float flDist ); - void StartTask ( Task_t *pTask ); - void AlertSound( void ); - void DeathSound ( void ); - void PainSound ( void ); - void AttackSound ( void ); - void PrescheduleThink ( void ); - void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - int IRelationship( CBaseEntity *pTarget ); - void StopTalking ( void ); - BOOL ShouldSpeak( void ); - CUSTOM_SCHEDULES; - - virtual int Save( CSave &save ); - virtual int Restore( CRestore &restore ); - static TYPEDESCRIPTION m_SaveData[]; - - static const char *pAttackHitSounds[]; - static const char *pAttackMissSounds[]; - static const char *pAttackSounds[]; - static const char *pDieSounds[]; - static const char *pPainSounds[]; - static const char *pIdleSounds[]; - static const char *pAlertSounds[]; - - BOOL m_fCanHornetAttack; - float m_flNextHornetAttackCheck; - - float m_flNextPainTime; - - // three hacky fields for speech stuff. These don't really need to be saved. - float m_flNextSpeakTime; - float m_flNextWordTime; - int m_iLastWord; -}; -LINK_ENTITY_TO_CLASS( monster_alien_grunt, CAGrunt ); - -TYPEDESCRIPTION CAGrunt::m_SaveData[] = -{ - DEFINE_FIELD( CAGrunt, m_fCanHornetAttack, FIELD_BOOLEAN ), - DEFINE_FIELD( CAGrunt, m_flNextHornetAttackCheck, FIELD_TIME ), - DEFINE_FIELD( CAGrunt, m_flNextPainTime, FIELD_TIME ), - DEFINE_FIELD( CAGrunt, m_flNextSpeakTime, FIELD_TIME ), - DEFINE_FIELD( CAGrunt, m_flNextWordTime, FIELD_TIME ), - DEFINE_FIELD( CAGrunt, m_iLastWord, FIELD_INTEGER ), -}; - -IMPLEMENT_SAVERESTORE( CAGrunt, CSquadMonster ); - -const char *CAGrunt::pAttackHitSounds[] = -{ - "zombie/claw_strike1.wav", - "zombie/claw_strike2.wav", - "zombie/claw_strike3.wav", -}; - -const char *CAGrunt::pAttackMissSounds[] = -{ - "zombie/claw_miss1.wav", - "zombie/claw_miss2.wav", -}; - -const char *CAGrunt::pAttackSounds[] = -{ - "agrunt/ag_attack1.wav", - "agrunt/ag_attack2.wav", - "agrunt/ag_attack3.wav", -}; - -const char *CAGrunt::pDieSounds[] = -{ - "agrunt/ag_die1.wav", - "agrunt/ag_die4.wav", - "agrunt/ag_die5.wav", -}; - -const char *CAGrunt::pPainSounds[] = -{ - "agrunt/ag_pain1.wav", - "agrunt/ag_pain2.wav", - "agrunt/ag_pain3.wav", - "agrunt/ag_pain4.wav", - "agrunt/ag_pain5.wav", -}; - -const char *CAGrunt::pIdleSounds[] = -{ - "agrunt/ag_idle1.wav", - "agrunt/ag_idle2.wav", - "agrunt/ag_idle3.wav", - "agrunt/ag_idle4.wav", -}; - -const char *CAGrunt::pAlertSounds[] = -{ - "agrunt/ag_alert1.wav", - "agrunt/ag_alert3.wav", - "agrunt/ag_alert4.wav", - "agrunt/ag_alert5.wav", -}; - -//========================================================= -// IRelationship - overridden because Human Grunts are -// Alien Grunt's nemesis. -//========================================================= -int CAGrunt::IRelationship ( CBaseEntity *pTarget ) -{ - if ( FClassnameIs( pTarget->pev, "monster_human_grunt" ) ) - { - return R_NM; - } - - return CSquadMonster :: IRelationship( pTarget ); -} - -//========================================================= -// ISoundMask -//========================================================= -int CAGrunt :: ISoundMask ( void ) -{ - return bits_SOUND_WORLD | - bits_SOUND_COMBAT | - bits_SOUND_PLAYER | - bits_SOUND_DANGER; -} - -//========================================================= -// TraceAttack -//========================================================= -void CAGrunt :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - if ( ptr->iHitgroup == 10 && (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_CLUB))) - { - // hit armor - if ( pev->dmgtime != gpGlobals->time || (RANDOM_LONG(0,10) < 1) ) - { - UTIL_Ricochet( ptr->vecEndPos, RANDOM_FLOAT( 1, 2) ); - pev->dmgtime = gpGlobals->time; - } - - if ( RANDOM_LONG( 0, 1 ) == 0 ) - { - Vector vecTracerDir = vecDir; - - vecTracerDir.x += RANDOM_FLOAT( -0.3, 0.3 ); - vecTracerDir.y += RANDOM_FLOAT( -0.3, 0.3 ); - vecTracerDir.z += RANDOM_FLOAT( -0.3, 0.3 ); - - vecTracerDir = vecTracerDir * -512; - - MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, ptr->vecEndPos ); - WRITE_BYTE( TE_TRACER ); - WRITE_COORD( ptr->vecEndPos.x ); - WRITE_COORD( ptr->vecEndPos.y ); - WRITE_COORD( ptr->vecEndPos.z ); - - WRITE_COORD( vecTracerDir.x ); - WRITE_COORD( vecTracerDir.y ); - WRITE_COORD( vecTracerDir.z ); - MESSAGE_END(); - } - - flDamage -= 20; - if (flDamage <= 0) - flDamage = 0.1;// don't hurt the monster much, but allow bits_COND_LIGHT_DAMAGE to be generated - } - else - { - SpawnBlood(ptr->vecEndPos, BloodColor(), flDamage);// a little surface blood. - TraceBleed( flDamage, vecDir, ptr, bitsDamageType ); - } - - AddMultiDamage( pevAttacker, this, flDamage, bitsDamageType ); -} - -//========================================================= -// StopTalking - won't speak again for 10-20 seconds. -//========================================================= -void CAGrunt::StopTalking( void ) -{ - m_flNextWordTime = m_flNextSpeakTime = gpGlobals->time + 10 + RANDOM_LONG(0, 10); -} - -//========================================================= -// ShouldSpeak - Should this agrunt be talking? -//========================================================= -BOOL CAGrunt::ShouldSpeak( void ) -{ - if ( m_flNextSpeakTime > gpGlobals->time ) - { - // my time to talk is still in the future. - return FALSE; - } - - if ( pev->spawnflags & SF_MONSTER_GAG ) - { - if ( m_MonsterState != MONSTERSTATE_COMBAT ) - { - // if gagged, don't talk outside of combat. - // if not going to talk because of this, put the talk time - // into the future a bit, so we don't talk immediately after - // going into combat - m_flNextSpeakTime = gpGlobals->time + 3; - return FALSE; - } - } - - return TRUE; -} - -//========================================================= -// PrescheduleThink -//========================================================= -void CAGrunt :: PrescheduleThink ( void ) -{ - if ( ShouldSpeak() ) - { - if ( m_flNextWordTime < gpGlobals->time ) - { - int num = -1; - - do - { - num = RANDOM_LONG(0,ARRAYSIZE(pIdleSounds)-1); - } while( num == m_iLastWord ); - - m_iLastWord = num; - - // play a new sound - EMIT_SOUND ( ENT(pev), CHAN_VOICE, pIdleSounds[ num ], 1.0, ATTN_NORM ); - - // is this word our last? - if ( RANDOM_LONG( 1, 10 ) <= 1 ) - { - // stop talking. - StopTalking(); - } - else - { - m_flNextWordTime = gpGlobals->time + RANDOM_FLOAT( 0.5, 1 ); - } - } - } -} - -//========================================================= -// DieSound -//========================================================= -void CAGrunt :: DeathSound ( void ) -{ - StopTalking(); - - EMIT_SOUND ( ENT(pev), CHAN_VOICE, pDieSounds[RANDOM_LONG(0,ARRAYSIZE(pDieSounds)-1)], 1.0, ATTN_NORM ); -} - -//========================================================= -// AlertSound -//========================================================= -void CAGrunt :: AlertSound ( void ) -{ - StopTalking(); - - EMIT_SOUND ( ENT(pev), CHAN_VOICE, pAlertSounds[RANDOM_LONG(0,ARRAYSIZE(pAlertSounds)-1)], 1.0, ATTN_NORM ); -} - -//========================================================= -// AttackSound -//========================================================= -void CAGrunt :: AttackSound ( void ) -{ - StopTalking(); - - EMIT_SOUND ( ENT(pev), CHAN_VOICE, pAttackSounds[RANDOM_LONG(0,ARRAYSIZE(pAttackSounds)-1)], 1.0, ATTN_NORM ); -} - -//========================================================= -// PainSound -//========================================================= -void CAGrunt :: PainSound ( void ) -{ - if ( m_flNextPainTime > gpGlobals->time ) - { - return; - } - - m_flNextPainTime = gpGlobals->time + 0.6; - - StopTalking(); - - EMIT_SOUND ( ENT(pev), CHAN_VOICE, pPainSounds[RANDOM_LONG(0,ARRAYSIZE(pPainSounds)-1)], 1.0, ATTN_NORM ); -} - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CAGrunt :: Classify ( void ) -{ - return CLASS_ALIEN_MILITARY; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CAGrunt :: SetYawSpeed ( void ) -{ - int ys; - - switch ( m_Activity ) - { - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - ys = 110; - break; - default: ys = 100; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -// -// Returns number of events handled, 0 if none. -//========================================================= -void CAGrunt :: HandleAnimEvent( MonsterEvent_t *pEvent ) -{ - switch( pEvent->event ) - { - case AGRUNT_AE_HORNET1: - case AGRUNT_AE_HORNET2: - case AGRUNT_AE_HORNET3: - case AGRUNT_AE_HORNET4: - case AGRUNT_AE_HORNET5: - { - // m_vecEnemyLKP should be center of enemy body - Vector vecArmPos, vecArmDir; - Vector vecDirToEnemy; - Vector angDir; - - if (HasConditions( bits_COND_SEE_ENEMY)) - { - vecDirToEnemy = ( ( m_vecEnemyLKP ) - pev->origin ); - angDir = UTIL_VecToAngles( vecDirToEnemy ); - vecDirToEnemy = vecDirToEnemy.Normalize(); - } - else - { - angDir = pev->angles; - UTIL_MakeAimVectors( angDir ); - vecDirToEnemy = gpGlobals->v_forward; - } - - pev->effects = EF_MUZZLEFLASH; - - // make angles +-180 - if (angDir.x > 180) - { - angDir.x = angDir.x - 360; - } - - SetBlending( 0, angDir.x ); - GetAttachment( 0, vecArmPos, vecArmDir ); - - vecArmPos = vecArmPos + vecDirToEnemy * 32; - MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecArmPos ); - WRITE_BYTE( TE_SPRITE ); - WRITE_COORD( vecArmPos.x ); // pos - WRITE_COORD( vecArmPos.y ); - WRITE_COORD( vecArmPos.z ); - WRITE_SHORT( iAgruntMuzzleFlash ); // model - WRITE_BYTE( 6 ); // size * 10 - WRITE_BYTE( 128 ); // brightness - MESSAGE_END(); - - CBaseEntity *pHornet = CBaseEntity::Create( "hornet", vecArmPos, UTIL_VecToAngles( vecDirToEnemy ), edict() ); - UTIL_MakeVectors ( pHornet->pev->angles ); - pHornet->pev->velocity = gpGlobals->v_forward * 300; - - CBaseMonster *pHornetMonster = pHornet->MyMonsterPointer(); - - if ( pHornetMonster ) - { - pHornetMonster->m_hEnemy = m_hEnemy; - } - } - break; - - case AGRUNT_AE_LEFT_FOOT: - switch (RANDOM_LONG(0,1)) - { - // left foot - case 0: EMIT_SOUND_DYN ( ENT(pev), CHAN_BODY, "player/pl_ladder2.wav", 1, ATTN_NORM, 0, 70 ); break; - case 1: EMIT_SOUND_DYN ( ENT(pev), CHAN_BODY, "player/pl_ladder4.wav", 1, ATTN_NORM, 0, 70 ); break; - } - break; - case AGRUNT_AE_RIGHT_FOOT: - // right foot - switch (RANDOM_LONG(0,1)) - { - case 0: EMIT_SOUND_DYN ( ENT(pev), CHAN_BODY, "player/pl_ladder1.wav", 1, ATTN_NORM, 0, 70 ); break; - case 1: EMIT_SOUND_DYN ( ENT(pev), CHAN_BODY, "player/pl_ladder3.wav", 1, ATTN_NORM, 0 ,70); break; - } - break; - - case AGRUNT_AE_LEFT_PUNCH: - { - CBaseEntity *pHurt = CheckTraceHullAttack( AGRUNT_MELEE_DIST, gSkillData.agruntDmgPunch, DMG_CLUB ); - - if ( pHurt ) - { - pHurt->pev->punchangle.y = -25; - pHurt->pev->punchangle.x = 8; - - // OK to use gpGlobals without calling MakeVectors, cause CheckTraceHullAttack called it above. - if ( pHurt->IsPlayer() ) - { - // this is a player. Knock him around. - pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_right * 250; - } - - EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); - - Vector vecArmPos, vecArmAng; - GetAttachment( 0, vecArmPos, vecArmAng ); - SpawnBlood(vecArmPos, pHurt->BloodColor(), 25);// a little surface blood. - } - else - { - // Play a random attack miss sound - EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); - } - } - break; - - case AGRUNT_AE_RIGHT_PUNCH: - { - CBaseEntity *pHurt = CheckTraceHullAttack( AGRUNT_MELEE_DIST, gSkillData.agruntDmgPunch, DMG_CLUB ); - - if ( pHurt ) - { - pHurt->pev->punchangle.y = 25; - pHurt->pev->punchangle.x = 8; - - // OK to use gpGlobals without calling MakeVectors, cause CheckTraceHullAttack called it above. - if ( pHurt->IsPlayer() ) - { - // this is a player. Knock him around. - pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_right * -250; - } - - EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); - - Vector vecArmPos, vecArmAng; - GetAttachment( 0, vecArmPos, vecArmAng ); - SpawnBlood(vecArmPos, pHurt->BloodColor(), 25);// a little surface blood. - } - else - { - // Play a random attack miss sound - EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); - } - } - break; - - default: - CSquadMonster::HandleAnimEvent( pEvent ); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CAGrunt :: Spawn() -{ - Precache( ); - - SET_MODEL(ENT(pev), "models/agrunt.mdl"); - UTIL_SetSize(pev, Vector(-32, -32, 0), Vector(32, 32, 64)); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->effects = 0; - pev->health = gSkillData.agruntHealth; - m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - m_afCapability = 0; - m_afCapability |= bits_CAP_SQUAD; - - m_HackedGunPos = Vector( 24, 64, 48 ); - - m_flNextSpeakTime = m_flNextWordTime = gpGlobals->time + 10 + RANDOM_LONG(0, 10); - - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CAGrunt :: Precache() -{ - int i; - - PRECACHE_MODEL("models/agrunt.mdl"); - - for ( i = 0; i < ARRAYSIZE( pAttackHitSounds ); i++ ) - PRECACHE_SOUND((char *)pAttackHitSounds[i]); - - for ( i = 0; i < ARRAYSIZE( pAttackMissSounds ); i++ ) - PRECACHE_SOUND((char *)pAttackMissSounds[i]); - - for ( i = 0; i < ARRAYSIZE( pIdleSounds ); i++ ) - PRECACHE_SOUND((char *)pIdleSounds[i]); - - for ( i = 0; i < ARRAYSIZE( pDieSounds ); i++ ) - PRECACHE_SOUND((char *)pDieSounds[i]); - - for ( i = 0; i < ARRAYSIZE( pPainSounds ); i++ ) - PRECACHE_SOUND((char *)pPainSounds[i]); - - for ( i = 0; i < ARRAYSIZE( pAttackSounds ); i++ ) - PRECACHE_SOUND((char *)pAttackSounds[i]); - - for ( i = 0; i < ARRAYSIZE( pAlertSounds ); i++ ) - PRECACHE_SOUND((char *)pAlertSounds[i]); - - - PRECACHE_SOUND( "hassault/hw_shoot1.wav" ); - - iAgruntMuzzleFlash = PRECACHE_MODEL( "sprites/muz4.spr" ); - - UTIL_PrecacheOther( "hornet" ); -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - -//========================================================= -// Fail Schedule -//========================================================= -Task_t tlAGruntFail[] = -{ - { TASK_STOP_MOVING, 0 }, - { TASK_SET_ACTIVITY, (float)ACT_IDLE }, - { TASK_WAIT, (float)2 }, - { TASK_WAIT_PVS, (float)0 }, -}; - -Schedule_t slAGruntFail[] = -{ - { - tlAGruntFail, - ARRAYSIZE ( tlAGruntFail ), - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_MELEE_ATTACK1, - 0, - "AGrunt Fail" - }, -}; - -//========================================================= -// Combat Fail Schedule -//========================================================= -Task_t tlAGruntCombatFail[] = -{ - { TASK_STOP_MOVING, 0 }, - { TASK_SET_ACTIVITY, (float)ACT_IDLE }, - { TASK_WAIT_FACE_ENEMY, (float)2 }, - { TASK_WAIT_PVS, (float)0 }, -}; - -Schedule_t slAGruntCombatFail[] = -{ - { - tlAGruntCombatFail, - ARRAYSIZE ( tlAGruntCombatFail ), - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_MELEE_ATTACK1, - 0, - "AGrunt Combat Fail" - }, -}; - -//========================================================= -// Standoff schedule. Used in combat when a monster is -// hiding in cover or the enemy has moved out of sight. -// Should we look around in this schedule? -//========================================================= -Task_t tlAGruntStandoff[] = -{ - { TASK_STOP_MOVING, (float)0 }, - { TASK_SET_ACTIVITY, (float)ACT_IDLE }, - { TASK_WAIT_FACE_ENEMY, (float)2 }, -}; - -Schedule_t slAGruntStandoff[] = -{ - { - tlAGruntStandoff, - ARRAYSIZE ( tlAGruntStandoff ), - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_MELEE_ATTACK1 | - bits_COND_SEE_ENEMY | - bits_COND_NEW_ENEMY | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER, - "Agrunt Standoff" - } -}; - -//========================================================= -// Suppress -//========================================================= -Task_t tlAGruntSuppressHornet[] = -{ - { TASK_STOP_MOVING, (float)0 }, - { TASK_RANGE_ATTACK1, (float)0 }, -}; - -Schedule_t slAGruntSuppress[] = -{ - { - tlAGruntSuppressHornet, - ARRAYSIZE ( tlAGruntSuppressHornet ), - 0, - 0, - "AGrunt Suppress Hornet", - }, -}; - -//========================================================= -// primary range attacks -//========================================================= -Task_t tlAGruntRangeAttack1[] = -{ - { TASK_STOP_MOVING, (float)0 }, - { TASK_FACE_ENEMY, (float)0 }, - { TASK_RANGE_ATTACK1, (float)0 }, -}; - -Schedule_t slAGruntRangeAttack1[] = -{ - { - tlAGruntRangeAttack1, - ARRAYSIZE ( tlAGruntRangeAttack1 ), - bits_COND_NEW_ENEMY | - bits_COND_ENEMY_DEAD | - bits_COND_HEAVY_DAMAGE, - - 0, - "AGrunt Range Attack1" - }, -}; - - -Task_t tlAGruntHiddenRangeAttack1[] = -{ - { TASK_SET_FAIL_SCHEDULE, (float)SCHED_STANDOFF }, - { TASK_AGRUNT_SETUP_HIDE_ATTACK, 0 }, - { TASK_STOP_MOVING, 0 }, - { TASK_FACE_IDEAL, 0 }, - { TASK_RANGE_ATTACK1_NOTURN, (float)0 }, -}; - -Schedule_t slAGruntHiddenRangeAttack[] = -{ - { - tlAGruntHiddenRangeAttack1, - ARRAYSIZE ( tlAGruntHiddenRangeAttack1 ), - bits_COND_NEW_ENEMY | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER, - "AGrunt Hidden Range Attack1" - }, -}; - -//========================================================= -// Take cover from enemy! Tries lateral cover before node -// cover! -//========================================================= -Task_t tlAGruntTakeCoverFromEnemy[] = -{ - { TASK_STOP_MOVING, (float)0 }, - { TASK_WAIT, (float)0.2 }, - { TASK_FIND_COVER_FROM_ENEMY, (float)0 }, - { TASK_RUN_PATH, (float)0 }, - { TASK_WAIT_FOR_MOVEMENT, (float)0 }, - { TASK_REMEMBER, (float)bits_MEMORY_INCOVER }, - { TASK_FACE_ENEMY, (float)0 }, -}; - -Schedule_t slAGruntTakeCoverFromEnemy[] = -{ - { - tlAGruntTakeCoverFromEnemy, - ARRAYSIZE ( tlAGruntTakeCoverFromEnemy ), - bits_COND_NEW_ENEMY, - 0, - "AGruntTakeCoverFromEnemy" - }, -}; - -//========================================================= -// Victory dance! -//========================================================= -Task_t tlAGruntVictoryDance[] = -{ - { TASK_STOP_MOVING, (float)0 }, - { TASK_SET_FAIL_SCHEDULE, (float)SCHED_AGRUNT_THREAT_DISPLAY }, - { TASK_WAIT, (float)0.2 }, - { TASK_AGRUNT_GET_PATH_TO_ENEMY_CORPSE, (float)0 }, - { TASK_WALK_PATH, (float)0 }, - { TASK_WAIT_FOR_MOVEMENT, (float)0 }, - { TASK_FACE_ENEMY, (float)0 }, - { TASK_PLAY_SEQUENCE, (float)ACT_CROUCH }, - { TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE }, - { TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE }, - { TASK_PLAY_SEQUENCE, (float)ACT_STAND }, - { TASK_PLAY_SEQUENCE, (float)ACT_THREAT_DISPLAY }, - { TASK_PLAY_SEQUENCE, (float)ACT_CROUCH }, - { TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE }, - { TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE }, - { TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE }, - { TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE }, - { TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE }, - { TASK_PLAY_SEQUENCE, (float)ACT_STAND }, -}; - -Schedule_t slAGruntVictoryDance[] = -{ - { - tlAGruntVictoryDance, - ARRAYSIZE ( tlAGruntVictoryDance ), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "AGruntVictoryDance" - }, -}; - -//========================================================= -//========================================================= -Task_t tlAGruntThreatDisplay[] = -{ - { TASK_STOP_MOVING, (float)0 }, - { TASK_FACE_ENEMY, (float)0 }, - { TASK_PLAY_SEQUENCE, (float)ACT_THREAT_DISPLAY }, -}; - -Schedule_t slAGruntThreatDisplay[] = -{ - { - tlAGruntThreatDisplay, - ARRAYSIZE ( tlAGruntThreatDisplay ), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - - bits_SOUND_PLAYER | - bits_SOUND_COMBAT | - bits_SOUND_WORLD, - "AGruntThreatDisplay" - }, -}; - -DEFINE_CUSTOM_SCHEDULES( CAGrunt ) -{ - slAGruntFail, - slAGruntCombatFail, - slAGruntStandoff, - slAGruntSuppress, - slAGruntRangeAttack1, - slAGruntHiddenRangeAttack, - slAGruntTakeCoverFromEnemy, - slAGruntVictoryDance, - slAGruntThreatDisplay, -}; - -IMPLEMENT_CUSTOM_SCHEDULES( CAGrunt, CSquadMonster ); - -//========================================================= -// FCanCheckAttacks - this is overridden for alien grunts -// because they can use their smart weapons against unseen -// enemies. Base class doesn't attack anyone it can't see. -//========================================================= -BOOL CAGrunt :: FCanCheckAttacks ( void ) -{ - if ( !HasConditions( bits_COND_ENEMY_TOOFAR ) ) - { - return TRUE; - } - else - { - return FALSE; - } -} - -//========================================================= -// CheckMeleeAttack1 - alien grunts zap the crap out of -// any enemy that gets too close. -//========================================================= -BOOL CAGrunt :: CheckMeleeAttack1 ( float flDot, float flDist ) -{ - if ( HasConditions ( bits_COND_SEE_ENEMY ) && flDist <= AGRUNT_MELEE_DIST && flDot >= 0.6 && m_hEnemy != NULL ) - { - return TRUE; - } - return FALSE; -} - -//========================================================= -// CheckRangeAttack1 -// -// !!!LATER - we may want to load balance this. Several -// tracelines are done, so we may not want to do this every -// server frame. Definitely not while firing. -//========================================================= -BOOL CAGrunt :: CheckRangeAttack1 ( float flDot, float flDist ) -{ - if ( gpGlobals->time < m_flNextHornetAttackCheck ) - { - return m_fCanHornetAttack; - } - - if ( HasConditions( bits_COND_SEE_ENEMY ) && flDist >= AGRUNT_MELEE_DIST && flDist <= 1024 && flDot >= 0.5 && NoFriendlyFire() ) - { - TraceResult tr; - Vector vecArmPos, vecArmDir; - - // verify that a shot fired from the gun will hit the enemy before the world. - // !!!LATER - we may wish to do something different for projectile weapons as opposed to instant-hit - UTIL_MakeVectors( pev->angles ); - GetAttachment( 0, vecArmPos, vecArmDir ); -// UTIL_TraceLine( vecArmPos, vecArmPos + gpGlobals->v_forward * 256, ignore_monsters, ENT(pev), &tr); - UTIL_TraceLine( vecArmPos, m_hEnemy->BodyTarget(vecArmPos), dont_ignore_monsters, ENT(pev), &tr); - - if ( tr.flFraction == 1.0 || tr.pHit == m_hEnemy->edict() ) - { - m_flNextHornetAttackCheck = gpGlobals->time + RANDOM_FLOAT( 2, 5 ); - m_fCanHornetAttack = TRUE; - return m_fCanHornetAttack; - } - } - - m_flNextHornetAttackCheck = gpGlobals->time + 0.2;// don't check for half second if this check wasn't successful - m_fCanHornetAttack = FALSE; - return m_fCanHornetAttack; -} - -//========================================================= -// StartTask -//========================================================= -void CAGrunt :: StartTask ( Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_AGRUNT_GET_PATH_TO_ENEMY_CORPSE: - { - UTIL_MakeVectors( pev->angles ); - if ( BuildRoute ( m_vecEnemyLKP - gpGlobals->v_forward * 50, bits_MF_TO_LOCATION, NULL ) ) - { - TaskComplete(); - } - else - { - ALERT ( at_aiconsole, "AGruntGetPathToEnemyCorpse failed!!\n" ); - TaskFail(); - } - } - break; - - case TASK_AGRUNT_SETUP_HIDE_ATTACK: - // alien grunt shoots hornets back out into the open from a concealed location. - // try to find a spot to throw that gives the smart weapon a good chance of finding the enemy. - // ideally, this spot is along a line that is perpendicular to a line drawn from the agrunt to the enemy. - - CBaseMonster *pEnemyMonsterPtr; - - pEnemyMonsterPtr = m_hEnemy->MyMonsterPointer(); - - if ( pEnemyMonsterPtr ) - { - Vector vecCenter; - TraceResult tr; - BOOL fSkip; - - fSkip = FALSE; - vecCenter = Center(); - - UTIL_VecToAngles( m_vecEnemyLKP - pev->origin ); - - UTIL_TraceLine( Center() + gpGlobals->v_forward * 128, m_vecEnemyLKP, ignore_monsters, ENT(pev), &tr); - if ( tr.flFraction == 1.0 ) - { - MakeIdealYaw ( pev->origin + gpGlobals->v_right * 128 ); - fSkip = TRUE; - TaskComplete(); - } - - if ( !fSkip ) - { - UTIL_TraceLine( Center() - gpGlobals->v_forward * 128, m_vecEnemyLKP, ignore_monsters, ENT(pev), &tr); - if ( tr.flFraction == 1.0 ) - { - MakeIdealYaw ( pev->origin - gpGlobals->v_right * 128 ); - fSkip = TRUE; - TaskComplete(); - } - } - - if ( !fSkip ) - { - UTIL_TraceLine( Center() + gpGlobals->v_forward * 256, m_vecEnemyLKP, ignore_monsters, ENT(pev), &tr); - if ( tr.flFraction == 1.0 ) - { - MakeIdealYaw ( pev->origin + gpGlobals->v_right * 256 ); - fSkip = TRUE; - TaskComplete(); - } - } - - if ( !fSkip ) - { - UTIL_TraceLine( Center() - gpGlobals->v_forward * 256, m_vecEnemyLKP, ignore_monsters, ENT(pev), &tr); - if ( tr.flFraction == 1.0 ) - { - MakeIdealYaw ( pev->origin - gpGlobals->v_right * 256 ); - fSkip = TRUE; - TaskComplete(); - } - } - - if ( !fSkip ) - { - TaskFail(); - } - } - else - { - ALERT ( at_aiconsole, "AGRunt - no enemy monster ptr!!!\n" ); - TaskFail(); - } - break; - - default: - CSquadMonster :: StartTask ( pTask ); - break; - } -} - -//========================================================= -// GetSchedule - Decides which type of schedule best suits -// the monster's current state and conditions. Then calls -// monster's member function to get a pointer to a schedule -// of the proper type. -//========================================================= -Schedule_t *CAGrunt :: GetSchedule ( void ) -{ - if ( HasConditions(bits_COND_HEAR_SOUND) ) - { - CSound *pSound; - pSound = PBestSound(); - - ASSERT( pSound != NULL ); - if ( pSound && (pSound->m_iType & bits_SOUND_DANGER) ) - { - // dangerous sound nearby! - return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND ); - } - } - - switch ( m_MonsterState ) - { - case MONSTERSTATE_COMBAT: - { -// dead enemy - if ( HasConditions( bits_COND_ENEMY_DEAD ) ) - { - // call base class, all code to handle dead enemies is centralized there. - return CBaseMonster :: GetSchedule(); - } - - if ( HasConditions(bits_COND_NEW_ENEMY) ) - { - return GetScheduleOfType( SCHED_WAKE_ANGRY ); - } - - // zap player! - if ( HasConditions ( bits_COND_CAN_MELEE_ATTACK1 ) ) - { - AttackSound();// this is a total hack. Should be parto f the schedule - return GetScheduleOfType ( SCHED_MELEE_ATTACK1 ); - } - - if ( HasConditions ( bits_COND_HEAVY_DAMAGE ) ) - { - return GetScheduleOfType( SCHED_SMALL_FLINCH ); - } - - // can attack - if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) && OccupySlot ( bits_SLOTS_AGRUNT_HORNET ) ) - { - return GetScheduleOfType ( SCHED_RANGE_ATTACK1 ); - } - - if ( OccupySlot ( bits_SLOT_AGRUNT_CHASE ) ) - { - return GetScheduleOfType ( SCHED_CHASE_ENEMY ); - } - - return GetScheduleOfType ( SCHED_STANDOFF ); - } - } - - return CSquadMonster :: GetSchedule(); -} - -//========================================================= -//========================================================= -Schedule_t* CAGrunt :: GetScheduleOfType ( int Type ) -{ - switch ( Type ) - { - case SCHED_TAKE_COVER_FROM_ENEMY: - return &slAGruntTakeCoverFromEnemy[ 0 ]; - break; - - case SCHED_RANGE_ATTACK1: - if ( HasConditions( bits_COND_SEE_ENEMY ) ) - { - //normal attack - return &slAGruntRangeAttack1[ 0 ]; - } - else - { - // attack an unseen enemy - // return &slAGruntHiddenRangeAttack[ 0 ]; - return &slAGruntRangeAttack1[ 0 ]; - } - break; - - case SCHED_AGRUNT_THREAT_DISPLAY: - return &slAGruntThreatDisplay[ 0 ]; - break; - - case SCHED_AGRUNT_SUPPRESS: - return &slAGruntSuppress[ 0 ]; - break; - - case SCHED_STANDOFF: - return &slAGruntStandoff[ 0 ]; - break; - - case SCHED_VICTORY_DANCE: - return &slAGruntVictoryDance[ 0 ]; - break; - - case SCHED_FAIL: - // no fail schedule specified, so pick a good generic one. - { - if ( m_hEnemy != NULL ) - { - // I have an enemy - // !!!LATER - what if this enemy is really far away and i'm chasing him? - // this schedule will make me stop, face his last known position for 2 - // seconds, and then try to move again - return &slAGruntCombatFail[ 0 ]; - } - - return &slAGruntFail[ 0 ]; - } - break; - - } - - return CSquadMonster :: GetScheduleOfType( Type ); -} - diff --git a/dlls/Half-life/airtank.cpp b/dlls/Half-life/airtank.cpp deleted file mode 100644 index 9bca29eb..00000000 --- a/dlls/Half-life/airtank.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" - -class CAirtank : public CGrenade -{ - void Spawn( void ); - void Precache( void ); - void EXPORT TankThink( void ); - void EXPORT TankTouch( CBaseEntity *pOther ); - int BloodColor( void ) { return DONT_BLEED; }; - void Killed( entvars_t *pevAttacker, int iGib ); - - virtual int Save( CSave &save ); - virtual int Restore( CRestore &restore ); - - static TYPEDESCRIPTION m_SaveData[]; - - int m_state; -}; - - -LINK_ENTITY_TO_CLASS( item_airtank, CAirtank ); -TYPEDESCRIPTION CAirtank::m_SaveData[] = -{ - DEFINE_FIELD( CAirtank, m_state, FIELD_INTEGER ), -}; - -IMPLEMENT_SAVERESTORE( CAirtank, CGrenade ); - - -void CAirtank :: Spawn( void ) -{ - Precache( ); - // motor - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - SET_MODEL(ENT(pev), "models/w_oxygen.mdl"); - UTIL_SetSize(pev, Vector( -16, -16, 0), Vector(16, 16, 36)); - UTIL_SetOrigin( pev, pev->origin ); - - SetTouch( TankTouch ); - SetThink( TankThink ); - - pev->flags |= FL_MONSTER; - pev->takedamage = DAMAGE_YES; - pev->health = 20; - pev->dmg = 50; - m_state = 1; -} - -void CAirtank::Precache( void ) -{ - PRECACHE_MODEL("models/w_oxygen.mdl"); - PRECACHE_SOUND("doors/aliendoor3.wav"); -} - - -void CAirtank :: Killed( entvars_t *pevAttacker, int iGib ) -{ - pev->owner = ENT( pevAttacker ); - - // UNDONE: this should make a big bubble cloud, not an explosion - - Explode( pev->origin, Vector( 0, 0, -1 ) ); -} - - -void CAirtank::TankThink( void ) -{ - // Fire trigger - m_state = 1; - SUB_UseTargets( this, USE_TOGGLE, 0 ); -} - - -void CAirtank::TankTouch( CBaseEntity *pOther ) -{ - if ( !pOther->IsPlayer() ) - return; - - if (!m_state) - { - // "no oxygen" sound - EMIT_SOUND( ENT(pev), CHAN_BODY, "player/pl_swim2.wav", 1.0, ATTN_NORM ); - return; - } - - // give player 12 more seconds of air - pOther->pev->air_finished = gpGlobals->time + 12; - - // suit recharge sound - EMIT_SOUND( ENT(pev), CHAN_VOICE, "doors/aliendoor3.wav", 1.0, ATTN_NORM ); - - // recharge airtank in 30 seconds - pev->nextthink = gpGlobals->time + 30; - m_state = 0; - SUB_UseTargets( this, USE_TOGGLE, 1 ); -} diff --git a/dlls/Half-life/apache.cpp b/dlls/Half-life/apache.cpp deleted file mode 100644 index 8f04b4bc..00000000 --- a/dlls/Half-life/apache.cpp +++ /dev/null @@ -1,1031 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -#ifndef OEM_BUILD - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "effects.h" - -extern DLL_GLOBAL int g_iSkillLevel; - -#define SF_WAITFORTRIGGER (0x04 | 0x40) // UNDONE: Fix! -#define SF_NOWRECKAGE 0x08 - -class CApache : public CBaseMonster -{ - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void Spawn(void); - void Precache(void); - int Classify(void) { return CLASS_HUMAN_MILITARY; }; - int BloodColor(void) { return DONT_BLEED; } - void Killed(entvars_t *pevAttacker, int iGib); - void GibMonster(void); - - void SetObjectCollisionBox(void) - { - pev->absmin = pev->origin + Vector(-300, -300, -172); - pev->absmax = pev->origin + Vector(300, 300, 8); - } - - void EXPORT HuntThink(void); - void EXPORT FlyTouch(CBaseEntity *pOther); - void EXPORT CrashTouch(CBaseEntity *pOther); - void EXPORT DyingThink(void); - void EXPORT StartupUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void EXPORT NullThink(void); - - void ShowDamage(void); - void Flight(void); - void FireRocket(void); - BOOL FireGun(void); - - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - - int m_iRockets; - float m_flForce; - float m_flNextRocket; - - Vector m_vecTarget; - Vector m_posTarget; - - Vector m_vecDesired; - Vector m_posDesired; - - Vector m_vecGoal; - - Vector m_angGun; - float m_flLastSeen; - float m_flPrevSeen; - - int m_iSoundState; // don't save this - - int m_iSpriteTexture; - int m_iExplode; - int m_iBodyGibs; - - float m_flGoalSpeed; - - int m_iDoSmokePuff; - CBeam *m_pBeam; -}; -LINK_ENTITY_TO_CLASS(monster_apache, CApache); - -TYPEDESCRIPTION CApache::m_SaveData[] = - { - DEFINE_FIELD(CApache, m_iRockets, FIELD_INTEGER), - DEFINE_FIELD(CApache, m_flForce, FIELD_FLOAT), - DEFINE_FIELD(CApache, m_flNextRocket, FIELD_TIME), - DEFINE_FIELD(CApache, m_vecTarget, FIELD_VECTOR), - DEFINE_FIELD(CApache, m_posTarget, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CApache, m_vecDesired, FIELD_VECTOR), - DEFINE_FIELD(CApache, m_posDesired, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CApache, m_vecGoal, FIELD_VECTOR), - DEFINE_FIELD(CApache, m_angGun, FIELD_VECTOR), - DEFINE_FIELD(CApache, m_flLastSeen, FIELD_TIME), - DEFINE_FIELD(CApache, m_flPrevSeen, FIELD_TIME), - // DEFINE_FIELD( CApache, m_iSoundState, FIELD_INTEGER ), // Don't save, precached - // DEFINE_FIELD( CApache, m_iSpriteTexture, FIELD_INTEGER ), - // DEFINE_FIELD( CApache, m_iExplode, FIELD_INTEGER ), - // DEFINE_FIELD( CApache, m_iBodyGibs, FIELD_INTEGER ), - DEFINE_FIELD(CApache, m_pBeam, FIELD_CLASSPTR), - DEFINE_FIELD(CApache, m_flGoalSpeed, FIELD_FLOAT), - DEFINE_FIELD(CApache, m_iDoSmokePuff, FIELD_INTEGER), -}; -IMPLEMENT_SAVERESTORE(CApache, CBaseMonster); - -void CApache ::Spawn(void) -{ - Precache(); - // motor - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - SET_MODEL(ENT(pev), "models/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(StartupUse); - } - else - { - SetThink(HuntThink); - SetTouch(FlyTouch); - pev->nextthink = gpGlobals->time + 1.0; - } - - m_iRockets = 10; -} - -void CApache::Precache(void) -{ - PRECACHE_MODEL("models/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/metalplategibs_green.mdl"); - - UTIL_PrecacheOther("hvr_rocket"); -} - -void CApache::NullThink(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.5; -} - -void CApache::StartupUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - SetThink(HuntThink); - SetTouch(FlyTouch); - pev->nextthink = gpGlobals->time + 0.1; - SetUse(NULL); -} - -void CApache ::Killed(entvars_t *pevAttacker, int iGib) -{ - pev->movetype = MOVETYPE_TOSS; - pev->gravity = 0.3; - - STOP_SOUND(ENT(pev), CHAN_STATIC, "apache/ap_rotor2.wav"); - - UTIL_SetSize(pev, Vector(-32, -32, -64), Vector(32, 32, 0)); - SetThink(DyingThink); - SetTouch(CrashTouch); - pev->nextthink = gpGlobals->time + 0.1; - pev->health = 0; - pev->takedamage = DAMAGE_NO; - - if (pev->spawnflags & SF_NOWRECKAGE) - { - m_flNextRocket = gpGlobals->time + 4.0; - } - else - { - m_flNextRocket = gpGlobals->time + 15.0; - } -} - -void CApache ::DyingThink(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - pev->avelocity = pev->avelocity * 1.02; - - // still falling? - if (m_flNextRocket > gpGlobals->time) - { - // random explosions - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_EXPLOSION); // This just makes a dynamic light now - WRITE_COORD(pev->origin.x + RANDOM_FLOAT(-150, 150)); - WRITE_COORD(pev->origin.y + RANDOM_FLOAT(-150, 150)); - WRITE_COORD(pev->origin.z + RANDOM_FLOAT(-150, -50)); - WRITE_SHORT(g_sModelIndexFireball); - WRITE_BYTE(RANDOM_LONG(0, 29) + 30); // scale * 10 - WRITE_BYTE(12); // framerate - WRITE_BYTE(TE_EXPLFLAG_NONE); - MESSAGE_END(); - - // lots of smoke - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(pev->origin.x + RANDOM_FLOAT(-150, 150)); - WRITE_COORD(pev->origin.y + RANDOM_FLOAT(-150, 150)); - WRITE_COORD(pev->origin.z + RANDOM_FLOAT(-150, -50)); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(100); // scale * 10 - WRITE_BYTE(10); // framerate - MESSAGE_END(); - - Vector vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5; - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSpot); - WRITE_BYTE(TE_BREAKMODEL); - - // position - WRITE_COORD(vecSpot.x); - WRITE_COORD(vecSpot.y); - WRITE_COORD(vecSpot.z); - - // size - WRITE_COORD(400); - WRITE_COORD(400); - WRITE_COORD(132); - - // velocity - WRITE_COORD(pev->velocity.x); - WRITE_COORD(pev->velocity.y); - WRITE_COORD(pev->velocity.z); - - // randomization - WRITE_BYTE(50); - - // Model - WRITE_SHORT(m_iBodyGibs); //model id# - - // # of shards - WRITE_BYTE(4); // let client decide - - // duration - WRITE_BYTE(30); // 3.0 seconds - - // flags - - WRITE_BYTE(BREAK_METAL); - MESSAGE_END(); - - // don't stop it we touch a entity - pev->flags &= ~FL_ONGROUND; - pev->nextthink = gpGlobals->time + 0.2; - return; - } - else - { - Vector vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5; - - /* - MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); - WRITE_BYTE( TE_EXPLOSION); // This just makes a dynamic light now - WRITE_COORD( vecSpot.x ); - WRITE_COORD( vecSpot.y ); - WRITE_COORD( vecSpot.z + 300 ); - WRITE_SHORT( g_sModelIndexFireball ); - WRITE_BYTE( 250 ); // scale * 10 - WRITE_BYTE( 8 ); // framerate - MESSAGE_END(); - */ - - // fireball - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSpot); - WRITE_BYTE(TE_SPRITE); - WRITE_COORD(vecSpot.x); - WRITE_COORD(vecSpot.y); - WRITE_COORD(vecSpot.z + 256); - WRITE_SHORT(m_iExplode); - WRITE_BYTE(120); // scale * 10 - WRITE_BYTE(255); // brightness - MESSAGE_END(); - - // big smoke - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSpot); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(vecSpot.x); - WRITE_COORD(vecSpot.y); - WRITE_COORD(vecSpot.z + 512); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(250); // scale * 10 - WRITE_BYTE(5); // framerate - MESSAGE_END(); - - // blast circle - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_BEAMCYLINDER); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z + 2000); // reach damage radius over .2 seconds - WRITE_SHORT(m_iSpriteTexture); - WRITE_BYTE(0); // startframe - WRITE_BYTE(0); // framerate - WRITE_BYTE(4); // life - WRITE_BYTE(32); // width - WRITE_BYTE(0); // noise - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(192); // r, g, b - WRITE_BYTE(128); // brightness - WRITE_BYTE(0); // speed - MESSAGE_END(); - - EMIT_SOUND(ENT(pev), CHAN_STATIC, "weapons/mortarhit.wav", 1.0, 0.3); - - RadiusDamage(pev->origin, pev, pev, 300, CLASS_NONE, DMG_BLAST); - - if (/*!(pev->spawnflags & SF_NOWRECKAGE) && */ (pev->flags & FL_ONGROUND)) - { - CBaseEntity *pWreckage = Create("cycler_wreckage", pev->origin, pev->angles); - // SET_MODEL( ENT(pWreckage->pev), STRING(pev->model) ); - UTIL_SetSize(pWreckage->pev, Vector(-200, -200, -128), Vector(200, 200, -32)); - pWreckage->pev->frame = pev->frame; - pWreckage->pev->sequence = pev->sequence; - pWreckage->pev->framerate = 0; - pWreckage->pev->dmgtime = gpGlobals->time + 5; - } - - // gibs - vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5; - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSpot); - WRITE_BYTE(TE_BREAKMODEL); - - // position - WRITE_COORD(vecSpot.x); - WRITE_COORD(vecSpot.y); - WRITE_COORD(vecSpot.z + 64); - - // size - WRITE_COORD(400); - WRITE_COORD(400); - WRITE_COORD(128); - - // velocity - WRITE_COORD(0); - WRITE_COORD(0); - WRITE_COORD(200); - - // randomization - WRITE_BYTE(30); - - // Model - WRITE_SHORT(m_iBodyGibs); //model id# - - // # of shards - WRITE_BYTE(200); - - // duration - WRITE_BYTE(200); // 10.0 seconds - - // flags - - WRITE_BYTE(BREAK_METAL); - MESSAGE_END(); - - SetThink(SUB_Remove); - pev->nextthink = gpGlobals->time + 0.1; - } -} - -void CApache::FlyTouch(CBaseEntity *pOther) -{ - // bounce if we hit something solid - if (pOther->pev->solid == SOLID_BSP) - { - TraceResult tr = UTIL_GetGlobalTrace(); - - // UNDONE, do a real bounce - pev->velocity = pev->velocity + tr.vecPlaneNormal * (pev->velocity.Length() + 200); - } -} - -void CApache::CrashTouch(CBaseEntity *pOther) -{ - // only crash if we hit something solid - if (pOther->pev->solid == SOLID_BSP) - { - SetTouch(NULL); - m_flNextRocket = gpGlobals->time; - pev->nextthink = gpGlobals->time; - } -} - -void CApache ::GibMonster(void) -{ - // EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "common/bodysplat.wav", 0.75, ATTN_NORM, 0, 200); -} - -void CApache ::HuntThink(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - ShowDamage(); - - if (m_pGoalEnt == NULL && !FStringNull(pev->target)) // this monster has a target - { - m_pGoalEnt = UTIL_FindEntityByTargetname(NULL, STRING(pev->target)); - if (m_pGoalEnt) - { - m_posDesired = m_pGoalEnt->pev->origin; - UTIL_MakeAimVectors(m_pGoalEnt->pev->angles); - m_vecGoal = gpGlobals->v_forward; - } - } - - // if (m_hEnemy == NULL) - { - Look(4092); - m_hEnemy = BestVisibleEnemy(); - } - - // generic speed up - if (m_flGoalSpeed < 800) - m_flGoalSpeed += 5; - - if (m_hEnemy != NULL) - { - // ALERT( at_console, "%s\n", STRING( m_hEnemy->pev->classname ) ); - if (FVisible(m_hEnemy)) - { - if (m_flLastSeen < gpGlobals->time - 5) - m_flPrevSeen = gpGlobals->time; - m_flLastSeen = gpGlobals->time; - m_posTarget = m_hEnemy->Center(); - } - else - { - m_hEnemy = NULL; - } - } - - m_vecTarget = (m_posTarget - pev->origin).Normalize(); - - float flLength = (pev->origin - m_posDesired).Length(); - - if (m_pGoalEnt) - { - // ALERT( at_console, "%.0f\n", flLength ); - - if (flLength < 128) - { - m_pGoalEnt = UTIL_FindEntityByTargetname(NULL, STRING(m_pGoalEnt->pev->target)); - if (m_pGoalEnt) - { - m_posDesired = m_pGoalEnt->pev->origin; - UTIL_MakeAimVectors(m_pGoalEnt->pev->angles); - m_vecGoal = gpGlobals->v_forward; - flLength = (pev->origin - m_posDesired).Length(); - } - } - } - else - { - m_posDesired = pev->origin; - } - - if (flLength > 250) // 500 - { - // float flLength2 = (m_posTarget - pev->origin).Length() * (1.5 - DotProduct((m_posTarget - pev->origin).Normalize(), pev->velocity.Normalize() )); - // if (flLength2 < flLength) - if (m_flLastSeen + 90 > gpGlobals->time && DotProduct((m_posTarget - pev->origin).Normalize(), (m_posDesired - pev->origin).Normalize()) > 0.25) - { - m_vecDesired = (m_posTarget - pev->origin).Normalize(); - } - else - { - m_vecDesired = (m_posDesired - pev->origin).Normalize(); - } - } - else - { - m_vecDesired = m_vecGoal; - } - - Flight(); - - // ALERT( at_console, "%.0f %.0f %.0f\n", gpGlobals->time, m_flLastSeen, m_flPrevSeen ); - if ((m_flLastSeen + 1 > gpGlobals->time) && (m_flPrevSeen + 2 < gpGlobals->time)) - { - if (FireGun()) - { - // slow down if we're fireing - if (m_flGoalSpeed > 400) - m_flGoalSpeed = 400; - } - - // don't fire rockets and gun on easy mode - if (g_iSkillLevel == SKILL_EASY) - m_flNextRocket = gpGlobals->time + 10.0; - } - - UTIL_MakeAimVectors(pev->angles); - Vector vecEst = (gpGlobals->v_forward * 800 + pev->velocity).Normalize(); - // ALERT( at_console, "%d %d %d %4.2f\n", pev->angles.x < 0, DotProduct( pev->velocity, gpGlobals->v_forward ) > -100, m_flNextRocket < gpGlobals->time, DotProduct( m_vecTarget, vecEst ) ); - - if ((m_iRockets % 2) == 1) - { - FireRocket(); - m_flNextRocket = gpGlobals->time + 0.5; - if (m_iRockets <= 0) - { - m_flNextRocket = gpGlobals->time + 10; - m_iRockets = 10; - } - } - else if (pev->angles.x < 0 && DotProduct(pev->velocity, gpGlobals->v_forward) > -100 && m_flNextRocket < gpGlobals->time) - { - if (m_flLastSeen + 60 > gpGlobals->time) - { - if (m_hEnemy != NULL) - { - // make sure it's a good shot - if (DotProduct(m_vecTarget, vecEst) > .965) - { - TraceResult tr; - - UTIL_TraceLine(pev->origin, pev->origin + vecEst * 4096, ignore_monsters, edict(), &tr); - if ((tr.vecEndPos - m_posTarget).Length() < 512) - FireRocket(); - } - } - else - { - TraceResult tr; - - UTIL_TraceLine(pev->origin, pev->origin + vecEst * 4096, dont_ignore_monsters, edict(), &tr); - // just fire when close - if ((tr.vecEndPos - m_posTarget).Length() < 512) - FireRocket(); - } - } - } -} - -void CApache ::Flight(void) -{ - // tilt model 5 degrees - Vector vecAdj = Vector(5.0, 0, 0); - - // estimate where I'll be facing in one seconds - UTIL_MakeAimVectors(pev->angles + pev->avelocity * 2 + vecAdj); - // Vector vecEst1 = pev->origin + pev->velocity + gpGlobals->v_up * m_flForce - Vector( 0, 0, 384 ); - // float flSide = DotProduct( m_posDesired - vecEst1, gpGlobals->v_right ); - - float flSide = DotProduct(m_vecDesired, gpGlobals->v_right); - - if (flSide < 0) - { - if (pev->avelocity.y < 60) - { - pev->avelocity.y += 8; // 9 * (3.0/2.0); - } - } - else - { - if (pev->avelocity.y > -60) - { - pev->avelocity.y -= 8; // 9 * (3.0/2.0); - } - } - pev->avelocity.y *= 0.98; - - // estimate where I'll be in two seconds - UTIL_MakeAimVectors(pev->angles + pev->avelocity * 1 + vecAdj); - Vector vecEst = pev->origin + pev->velocity * 2.0 + gpGlobals->v_up * m_flForce * 20 - Vector(0, 0, 384 * 2); - - // add immediate force - UTIL_MakeAimVectors(pev->angles + vecAdj); - pev->velocity.x += gpGlobals->v_up.x * m_flForce; - pev->velocity.y += gpGlobals->v_up.y * m_flForce; - pev->velocity.z += gpGlobals->v_up.z * m_flForce; - // add gravity - pev->velocity.z -= 38.4; // 32ft/sec - - float flSpeed = pev->velocity.Length(); - float flDir = DotProduct(Vector(gpGlobals->v_forward.x, gpGlobals->v_forward.y, 0), Vector(pev->velocity.x, pev->velocity.y, 0)); - if (flDir < 0) - flSpeed = -flSpeed; - - float flDist = DotProduct(m_posDesired - vecEst, gpGlobals->v_forward); - - // float flSlip = DotProduct( pev->velocity, gpGlobals->v_right ); - float flSlip = -DotProduct(m_posDesired - vecEst, gpGlobals->v_right); - - // fly sideways - if (flSlip > 0) - { - if (pev->angles.z > -30 && pev->avelocity.z > -15) - pev->avelocity.z -= 4; - else - pev->avelocity.z += 2; - } - else - { - - if (pev->angles.z < 30 && pev->avelocity.z < 15) - pev->avelocity.z += 4; - else - pev->avelocity.z -= 2; - } - - // sideways drag - pev->velocity.x = pev->velocity.x * (1.0 - fabs(gpGlobals->v_right.x) * 0.05); - pev->velocity.y = pev->velocity.y * (1.0 - fabs(gpGlobals->v_right.y) * 0.05); - pev->velocity.z = pev->velocity.z * (1.0 - fabs(gpGlobals->v_right.z) * 0.05); - - // general drag - pev->velocity = pev->velocity * 0.995; - - // apply power to stay correct height - if (m_flForce < 80 && vecEst.z < m_posDesired.z) - { - m_flForce += 12; - } - else if (m_flForce > 30) - { - if (vecEst.z > m_posDesired.z) - m_flForce -= 8; - } - - // pitch forward or back to get to target - if (flDist > 0 && flSpeed < m_flGoalSpeed /* && flSpeed < flDist */ && pev->angles.x + pev->avelocity.x > -40) - { - // ALERT( at_console, "F " ); - // lean forward - pev->avelocity.x -= 12.0; - } - else if (flDist < 0 && flSpeed > -50 && pev->angles.x + pev->avelocity.x < 20) - { - // ALERT( at_console, "B " ); - // lean backward - pev->avelocity.x += 12.0; - } - else if (pev->angles.x + pev->avelocity.x > 0) - { - // ALERT( at_console, "f " ); - pev->avelocity.x -= 4.0; - } - else if (pev->angles.x + pev->avelocity.x < 0) - { - // ALERT( at_console, "b " ); - pev->avelocity.x += 4.0; - } - - // ALERT( at_console, "%.0f %.0f : %.0f %.0f : %.0f %.0f : %.0f\n", pev->origin.x, pev->velocity.x, flDist, flSpeed, pev->angles.x, pev->avelocity.x, m_flForce ); - // ALERT( at_console, "%.0f %.0f : %.0f %0.f : %.0f\n", pev->origin.z, pev->velocity.z, vecEst.z, m_posDesired.z, m_flForce ); - - // make rotor, engine sounds - if (m_iSoundState == 0) - { - EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_rotor2.wav", 1.0, 0.3, 0, 110); - // EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_whine1.wav", 0.5, 0.2, 0, 110 ); - - m_iSoundState = SND_CHANGE_PITCH; // hack for going through level transitions - } - else - { - CBaseEntity *pPlayer = NULL; - - pPlayer = UTIL_FindEntityByClassname(NULL, "player"); - // UNDONE: this needs to send different sounds to every player for multiplayer. - if (pPlayer) - { - - float pitch = DotProduct(pev->velocity - pPlayer->pev->velocity, (pPlayer->pev->origin - pev->origin).Normalize()); - - pitch = (int)(100 + pitch / 50.0); - - if (pitch > 250) - pitch = 250; - if (pitch < 50) - pitch = 50; - if (pitch == 100) - pitch = 101; - - float flVol = (m_flForce / 100.0) + .1; - if (flVol > 1.0) - flVol = 1.0; - - EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_rotor2.wav", 1.0, 0.3, SND_CHANGE_PITCH | SND_CHANGE_VOL, pitch); - } - // EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_whine1.wav", flVol, 0.2, SND_CHANGE_PITCH | SND_CHANGE_VOL, pitch); - - // ALERT( at_console, "%.0f %.2f\n", pitch, flVol ); - } -} - -void CApache ::FireRocket(void) -{ - static float side = 1.0; - static int count; - - if (m_iRockets <= 0) - return; - - UTIL_MakeAimVectors(pev->angles); - Vector vecSrc = pev->origin + 1.5 * (gpGlobals->v_forward * 21 + gpGlobals->v_right * 70 * side + gpGlobals->v_up * -79); - - switch (m_iRockets % 5) - { - case 0: - vecSrc = vecSrc + gpGlobals->v_right * 10; - break; - case 1: - vecSrc = vecSrc - gpGlobals->v_right * 10; - break; - case 2: - vecSrc = vecSrc + gpGlobals->v_up * 10; - break; - case 3: - vecSrc = vecSrc - gpGlobals->v_up * 10; - break; - case 4: - break; - } - - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSrc); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(vecSrc.x); - WRITE_COORD(vecSrc.y); - WRITE_COORD(vecSrc.z); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(20); // scale * 10 - WRITE_BYTE(12); // framerate - MESSAGE_END(); - - CBaseEntity *pRocket = CBaseEntity::Create("hvr_rocket", vecSrc, pev->angles, edict()); - if (pRocket) - pRocket->pev->velocity = pev->velocity + gpGlobals->v_forward * 100; - - m_iRockets--; - - side = -side; -} - -BOOL CApache ::FireGun() -{ - UTIL_MakeAimVectors(pev->angles); - - Vector posGun, angGun; - GetAttachment(1, posGun, angGun); - - Vector vecTarget = (m_posTarget - posGun).Normalize(); - - Vector vecOut; - - vecOut.x = DotProduct(gpGlobals->v_forward, vecTarget); - vecOut.y = -DotProduct(gpGlobals->v_right, vecTarget); - vecOut.z = DotProduct(gpGlobals->v_up, vecTarget); - - Vector angles = UTIL_VecToAngles(vecOut); - - angles.x = -angles.x; - if (angles.y > 180) - angles.y = angles.y - 360; - if (angles.y < -180) - angles.y = angles.y + 360; - if (angles.x > 180) - angles.x = angles.x - 360; - if (angles.x < -180) - angles.x = angles.x + 360; - - if (angles.x > m_angGun.x) - m_angGun.x = min(angles.x, m_angGun.x + 12); - if (angles.x < m_angGun.x) - m_angGun.x = max(angles.x, m_angGun.x - 12); - if (angles.y > m_angGun.y) - m_angGun.y = min(angles.y, m_angGun.y + 12); - if (angles.y < m_angGun.y) - m_angGun.y = max(angles.y, m_angGun.y - 12); - - m_angGun.y = SetBoneController(0, m_angGun.y); - m_angGun.x = SetBoneController(1, m_angGun.x); - - Vector posBarrel, angBarrel; - GetAttachment(0, posBarrel, angBarrel); - Vector vecGun = (posBarrel - posGun).Normalize(); - - if (DotProduct(vecGun, vecTarget) > 0.98) - { -#if 1 - FireBullets(1, posGun, vecGun, VECTOR_CONE_4DEGREES, 8192, BULLET_MONSTER_12MM, 1); - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "turret/tu_fire1.wav", 1, 0.3); -#else - static float flNext; - TraceResult tr; - UTIL_TraceLine(posGun, posGun + vecGun * 8192, dont_ignore_monsters, ENT(pev), &tr); - - if (!m_pBeam) - { - m_pBeam = CBeam::BeamCreate("sprites/lgtning.spr", 80); - m_pBeam->PointEntInit(pev->origin, entindex()); - m_pBeam->SetEndAttachment(1); - m_pBeam->SetColor(255, 180, 96); - m_pBeam->SetBrightness(192); - } - - if (flNext < gpGlobals->time) - { - flNext = gpGlobals->time + 0.5; - m_pBeam->SetStartPos(tr.vecEndPos); - } -#endif - return TRUE; - } - else - { - if (m_pBeam) - { - UTIL_Remove(m_pBeam); - m_pBeam = NULL; - } - } - return FALSE; -} - -void CApache ::ShowDamage(void) -{ - if (m_iDoSmokePuff > 0 || RANDOM_LONG(0, 99) > pev->health) - { - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z - 32); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(RANDOM_LONG(0, 9) + 20); // scale * 10 - WRITE_BYTE(12); // framerate - MESSAGE_END(); - } - if (m_iDoSmokePuff > 0) - m_iDoSmokePuff--; -} - -int CApache ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (pevInflictor->owner == edict()) - return 0; - - if (bitsDamageType & DMG_BLAST) - { - flDamage *= 2; - } - - /* - if ( (bitsDamageType & DMG_BULLET) && flDamage > 50) - { - // clip bullet damage at 50 - flDamage = 50; - } - */ - - // ALERT( at_console, "%.0f\n", flDamage ); - return CBaseEntity::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -void CApache::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - // ALERT( at_console, "%d %.0f\n", ptr->iHitgroup, flDamage ); - - // ignore blades - if (ptr->iHitgroup == 6 && (bitsDamageType & (DMG_ENERGYBEAM | DMG_BULLET | DMG_CLUB))) - return; - - // hit hard, hits cockpit, hits engines - if (flDamage > 50 || ptr->iHitgroup == 1 || ptr->iHitgroup == 2) - { - // ALERT( at_console, "%.0f\n", flDamage ); - AddMultiDamage(pevAttacker, this, flDamage, bitsDamageType); - m_iDoSmokePuff = 3 + (flDamage / 5.0); - } - else - { - // do half damage in the body - // AddMultiDamage( pevAttacker, this, flDamage / 2.0, bitsDamageType ); - UTIL_Ricochet(ptr->vecEndPos, 2.0); - } -} - -class CApacheHVR : public CGrenade -{ - void Spawn(void); - void Precache(void); - void EXPORT IgniteThink(void); - void EXPORT AccelerateThink(void); - - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - int m_iTrail; - Vector m_vecForward; -}; -LINK_ENTITY_TO_CLASS(hvr_rocket, CApacheHVR); - -TYPEDESCRIPTION CApacheHVR::m_SaveData[] = - { - // DEFINE_FIELD( CApacheHVR, m_iTrail, FIELD_INTEGER ), // Dont' save, precache - DEFINE_FIELD(CApacheHVR, m_vecForward, FIELD_VECTOR), -}; - -IMPLEMENT_SAVERESTORE(CApacheHVR, CGrenade); - -void CApacheHVR ::Spawn(void) -{ - Precache(); - // motor - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - SET_MODEL(ENT(pev), "models/HVR.mdl"); - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); - UTIL_SetOrigin(pev, pev->origin); - - SetThink(IgniteThink); - SetTouch(ExplodeTouch); - - UTIL_MakeAimVectors(pev->angles); - m_vecForward = gpGlobals->v_forward; - pev->gravity = 0.5; - - pev->nextthink = gpGlobals->time + 0.1; - - pev->dmg = 150; -} - -void CApacheHVR ::Precache(void) -{ - PRECACHE_MODEL("models/HVR.mdl"); - m_iTrail = PRECACHE_MODEL("sprites/smoke.spr"); - PRECACHE_SOUND("weapons/rocket1.wav"); -} - -void CApacheHVR ::IgniteThink(void) -{ - // pev->movetype = MOVETYPE_TOSS; - - // pev->movetype = MOVETYPE_FLY; - pev->effects |= EF_LIGHT; - - // make rocket sound - EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/rocket1.wav", 1, 0.5); - - // rocket trail - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - - WRITE_BYTE(TE_BEAMFOLLOW); - WRITE_SHORT(entindex()); // entity - WRITE_SHORT(m_iTrail); // model - WRITE_BYTE(15); // life - WRITE_BYTE(5); // width - WRITE_BYTE(224); // r, g, b - WRITE_BYTE(224); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // brightness - - MESSAGE_END(); // move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS) - - // set to accelerate - SetThink(AccelerateThink); - pev->nextthink = gpGlobals->time + 0.1; -} - -void CApacheHVR ::AccelerateThink(void) -{ - // check world boundaries - if (pev->origin.x < -4096 || pev->origin.x > 4096 || pev->origin.y < -4096 || pev->origin.y > 4096 || pev->origin.z < -4096 || pev->origin.z > 4096) - { - UTIL_Remove(this); - return; - } - - // accelerate - float flSpeed = pev->velocity.Length(); - if (flSpeed < 1800) - { - pev->velocity = pev->velocity + m_vecForward * 200; - } - - // re-aim - pev->angles = UTIL_VecToAngles(pev->velocity); - - pev->nextthink = gpGlobals->time + 0.1; -} - -#endif \ No newline at end of file diff --git a/dlls/Half-life/barnacle.cpp b/dlls/Half-life/barnacle.cpp deleted file mode 100644 index 6c7823e1..00000000 --- a/dlls/Half-life/barnacle.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// barnacle - stationary ceiling mounted 'fishing' monster -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" - -#define BARNACLE_BODY_HEIGHT 44 // how 'tall' the barnacle's model is. -#define BARNACLE_PULL_SPEED 8 -#define BARNACLE_KILL_VICTIM_DELAY 5 // how many seconds after pulling prey in to gib them. - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define BARNACLE_AE_PUKEGIB 2 - -class CBarnacle : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - CBaseEntity *TongueTouchEnt(float *pflLength); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - void EXPORT BarnacleThink(void); - void EXPORT WaitTillDead(void); - void Killed(entvars_t *pevAttacker, int iGib); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - float m_flAltitude; - float m_flKillVictimTime; - int m_cGibs; // barnacle loads up on gibs each time it kills something. - BOOL m_fTongueExtended; - BOOL m_fLiftingPrey; - float m_flTongueAdj; -}; -LINK_ENTITY_TO_CLASS(monster_barnacle, CBarnacle); - -TYPEDESCRIPTION CBarnacle::m_SaveData[] = - { - DEFINE_FIELD(CBarnacle, m_flAltitude, FIELD_FLOAT), - DEFINE_FIELD(CBarnacle, m_flKillVictimTime, FIELD_TIME), - DEFINE_FIELD(CBarnacle, m_cGibs, FIELD_INTEGER), // barnacle loads up on gibs each time it kills something. - DEFINE_FIELD(CBarnacle, m_fTongueExtended, FIELD_BOOLEAN), - DEFINE_FIELD(CBarnacle, m_fLiftingPrey, FIELD_BOOLEAN), - DEFINE_FIELD(CBarnacle, m_flTongueAdj, FIELD_FLOAT), -}; - -IMPLEMENT_SAVERESTORE(CBarnacle, CBaseMonster); - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CBarnacle ::Classify(void) -{ - return CLASS_ALIEN_MONSTER; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -// -// Returns number of events handled, 0 if none. -//========================================================= -void CBarnacle ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case BARNACLE_AE_PUKEGIB: - CGib::SpawnRandomGibs(pev, 1, 1); - break; - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CBarnacle ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/barnacle.mdl"); - UTIL_SetSize(pev, Vector(-16, -16, -32), Vector(16, 16, 0)); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_NONE; - pev->takedamage = DAMAGE_AIM; - m_bloodColor = BLOOD_COLOR_RED; - pev->effects = EF_INVLIGHT; // take light from the ceiling - pev->health = 25; - m_flFieldOfView = 0.5; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - m_flKillVictimTime = 0; - m_cGibs = 0; - m_fLiftingPrey = FALSE; - m_flTongueAdj = -100; - - InitBoneControllers(); - - SetActivity(ACT_IDLE); - - SetThink(BarnacleThink); - pev->nextthink = gpGlobals->time + 0.5; - - UTIL_SetOrigin(pev, pev->origin); -} - -int CBarnacle::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (bitsDamageType & DMG_CLUB) - { - flDamage = pev->health; - } - - return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -//========================================================= -//========================================================= -void CBarnacle ::BarnacleThink(void) -{ - CBaseEntity *pTouchEnt; - CBaseMonster *pVictim; - float flLength; - - pev->nextthink = gpGlobals->time + 0.1; - - if (m_hEnemy != NULL) - { - // barnacle has prey. - - if (!m_hEnemy->IsAlive()) - { - // someone (maybe even the barnacle) killed the prey. Reset barnacle. - m_fLiftingPrey = FALSE; // indicate that we're not lifting prey. - m_hEnemy = NULL; - return; - } - - if (m_fLiftingPrey) - { - if (m_hEnemy != NULL && m_hEnemy->pev->deadflag != DEAD_NO) - { - // crap, someone killed the prey on the way up. - m_hEnemy = NULL; - m_fLiftingPrey = FALSE; - return; - } - - // still pulling prey. - Vector vecNewEnemyOrigin = m_hEnemy->pev->origin; - vecNewEnemyOrigin.x = pev->origin.x; - vecNewEnemyOrigin.y = pev->origin.y; - - // guess as to where their neck is - vecNewEnemyOrigin.x -= 6 * cos(m_hEnemy->pev->angles.y * M_PI / 180.0); - vecNewEnemyOrigin.y -= 6 * sin(m_hEnemy->pev->angles.y * M_PI / 180.0); - - m_flAltitude -= BARNACLE_PULL_SPEED; - vecNewEnemyOrigin.z += BARNACLE_PULL_SPEED; - - if (fabs(pev->origin.z - (vecNewEnemyOrigin.z + m_hEnemy->pev->view_ofs.z - 8)) < BARNACLE_BODY_HEIGHT) - { - // prey has just been lifted into position ( if the victim origin + eye height + 8 is higher than the bottom of the barnacle, it is assumed that the head is within barnacle's body ) - m_fLiftingPrey = FALSE; - - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "barnacle/bcl_bite3.wav", 1, ATTN_NORM); - - pVictim = m_hEnemy->MyMonsterPointer(); - - m_flKillVictimTime = gpGlobals->time + 10; // now that the victim is in place, the killing bite will be administered in 10 seconds. - - if (pVictim) - { - pVictim->BarnacleVictimBitten(pev); - SetActivity(ACT_EAT); - } - } - - UTIL_SetOrigin(m_hEnemy->pev, vecNewEnemyOrigin); - } - else - { - // prey is lifted fully into feeding position and is dangling there. - - pVictim = m_hEnemy->MyMonsterPointer(); - - if (m_flKillVictimTime != -1 && gpGlobals->time > m_flKillVictimTime) - { - // kill! - if (pVictim) - { - pVictim->TakeDamage(pev, pev, pVictim->pev->health, DMG_SLASH | DMG_ALWAYSGIB); - m_cGibs = 3; - } - - return; - } - - // bite prey every once in a while - if (pVictim && (RANDOM_LONG(0, 49) == 0)) - { - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew3.wav", 1, ATTN_NORM); - break; - } - - pVictim->BarnacleVictimBitten(pev); - } - } - } - else - { - // barnacle has no prey right now, so just idle and check to see if anything is touching the tongue. - - // If idle and no nearby client, don't think so often - if (FNullEnt(FIND_CLIENT_IN_PVS(edict()))) - pev->nextthink = gpGlobals->time + RANDOM_FLOAT(1, 1.5); // Stagger a bit to keep barnacles from thinking on the same frame - - if (m_fSequenceFinished) - { // this is done so barnacle will fidget. - SetActivity(ACT_IDLE); - m_flTongueAdj = -100; - } - - if (m_cGibs && RANDOM_LONG(0, 99) == 1) - { - // cough up a gib. - CGib::SpawnRandomGibs(pev, 1, 1); - m_cGibs--; - - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew3.wav", 1, ATTN_NORM); - break; - } - } - - pTouchEnt = TongueTouchEnt(&flLength); - - if (pTouchEnt != NULL && m_fTongueExtended) - { - // tongue is fully extended, and is touching someone. - if (pTouchEnt->FBecomeProne()) - { - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "barnacle/bcl_alert2.wav", 1, ATTN_NORM); - - SetSequenceByName("attack1"); - m_flTongueAdj = -20; - - m_hEnemy = pTouchEnt; - - pTouchEnt->pev->movetype = MOVETYPE_FLY; - pTouchEnt->pev->velocity = g_vecZero; - pTouchEnt->pev->basevelocity = g_vecZero; - pTouchEnt->pev->origin.x = pev->origin.x; - pTouchEnt->pev->origin.y = pev->origin.y; - - m_fLiftingPrey = TRUE; // indicate that we should be lifting prey. - m_flKillVictimTime = -1; // set this to a bogus time while the victim is lifted. - - m_flAltitude = (pev->origin.z - pTouchEnt->EyePosition().z); - } - } - else - { - // calculate a new length for the tongue to be clear of anything else that moves under it. - if (m_flAltitude < flLength) - { - // if tongue is higher than is should be, lower it kind of slowly. - m_flAltitude += BARNACLE_PULL_SPEED; - m_fTongueExtended = FALSE; - } - else - { - m_flAltitude = flLength; - m_fTongueExtended = TRUE; - } - } - } - - // ALERT( at_console, "tounge %f\n", m_flAltitude + m_flTongueAdj ); - SetBoneController(0, -(m_flAltitude + m_flTongueAdj)); - StudioFrameAdvance(0.1); -} - -//========================================================= -// Killed. -//========================================================= -void CBarnacle ::Killed(entvars_t *pevAttacker, int iGib) -{ - CBaseMonster *pVictim; - - pev->solid = SOLID_NOT; - pev->takedamage = DAMAGE_NO; - - if (m_hEnemy != NULL) - { - pVictim = m_hEnemy->MyMonsterPointer(); - - if (pVictim) - { - pVictim->BarnacleVictimReleased(); - } - } - - // CGib::SpawnRandomGibs( pev, 4, 1 ); - - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "barnacle/bcl_die1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "barnacle/bcl_die3.wav", 1, ATTN_NORM); - break; - } - - SetActivity(ACT_DIESIMPLE); - SetBoneController(0, 0); - - StudioFrameAdvance(0.1); - - pev->nextthink = gpGlobals->time + 0.1; - SetThink(WaitTillDead); -} - -//========================================================= -//========================================================= -void CBarnacle ::WaitTillDead(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - float flInterval = StudioFrameAdvance(0.1); - DispatchAnimEvents(flInterval); - - if (m_fSequenceFinished) - { - // death anim finished. - StopAnimation(); - SetThink(NULL); - } -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CBarnacle ::Precache() -{ - PRECACHE_MODEL("models/barnacle.mdl"); - - PRECACHE_SOUND("barnacle/bcl_alert2.wav"); //happy, lifting food up - PRECACHE_SOUND("barnacle/bcl_bite3.wav"); //just got food to mouth - PRECACHE_SOUND("barnacle/bcl_chew1.wav"); - PRECACHE_SOUND("barnacle/bcl_chew2.wav"); - PRECACHE_SOUND("barnacle/bcl_chew3.wav"); - PRECACHE_SOUND("barnacle/bcl_die1.wav"); - PRECACHE_SOUND("barnacle/bcl_die3.wav"); -} - -//========================================================= -// TongueTouchEnt - does a trace along the barnacle's tongue -// to see if any entity is touching it. Also stores the length -// of the trace in the int pointer provided. -//========================================================= -#define BARNACLE_CHECK_SPACING 8 -CBaseEntity *CBarnacle ::TongueTouchEnt(float *pflLength) -{ - TraceResult tr; - float length; - - // trace once to hit architecture and see if the tongue needs to change position. - UTIL_TraceLine(pev->origin, pev->origin - Vector(0, 0, 2048), ignore_monsters, ENT(pev), &tr); - length = fabs(pev->origin.z - tr.vecEndPos.z); - if (pflLength) - { - *pflLength = length; - } - - Vector delta = Vector(BARNACLE_CHECK_SPACING, BARNACLE_CHECK_SPACING, 0); - Vector mins = pev->origin - delta; - Vector maxs = pev->origin + delta; - maxs.z = pev->origin.z; - mins.z -= length; - - CBaseEntity *pList[10]; - int count = UTIL_EntitiesInBox(pList, 10, mins, maxs, (FL_CLIENT | FL_MONSTER)); - if (count) - { - for (int i = 0; i < count; i++) - { - // only clients and monsters - if (pList[i] != this && IRelationship(pList[i]) > R_NO && pList[i]->pev->deadflag == DEAD_NO) // this ent is one of our enemies. Barnacle tries to eat it. - { - return pList[i]; - } - } - } - - return NULL; -} diff --git a/dlls/Half-life/barney.cpp b/dlls/Half-life/barney.cpp deleted file mode 100644 index dfb2a052..00000000 --- a/dlls/Half-life/barney.cpp +++ /dev/null @@ -1,822 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// monster template -//========================================================= -// UNDONE: Holster weapon? - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "talkmonster.h" -#include "schedule.h" -#include "defaultai.h" -#include "scripted.h" -#include "weapons.h" -#include "soundent.h" - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -// first flag is barney dying for scripted sequences? -#define BARNEY_AE_DRAW (2) -#define BARNEY_AE_SHOOT (3) -#define BARNEY_AE_HOLSTER (4) - -#define BARNEY_BODY_GUNHOLSTERED 0 -#define BARNEY_BODY_GUNDRAWN 1 -#define BARNEY_BODY_GUNGONE 2 - -class CBarney : public CTalkMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int ISoundMask(void); - void BarneyFirePistol(void); - void AlertSound(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - - void RunTask(Task_t *pTask); - void StartTask(Task_t *pTask); - virtual int ObjectCaps(void) { return CTalkMonster ::ObjectCaps() | FCAP_IMPULSE_USE; } - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - BOOL CheckRangeAttack1(float flDot, float flDist); - - void DeclineFollowing(void); - - // Override these to set behavior - Schedule_t *GetScheduleOfType(int Type); - Schedule_t *GetSchedule(void); - MONSTERSTATE GetIdealState(void); - - void DeathSound(void); - void PainSound(void); - - void TalkInit(void); - - void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - void Killed(entvars_t *pevAttacker, int iGib); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - BOOL m_fGunDrawn; - float m_painTime; - float m_checkAttackTime; - BOOL m_lastAttackCheck; - - // UNDONE: What is this for? It isn't used? - float m_flPlayerDamage; // how much pain has the player inflicted on me? - - CUSTOM_SCHEDULES; -}; - -LINK_ENTITY_TO_CLASS(monster_barney, CBarney); - -TYPEDESCRIPTION CBarney::m_SaveData[] = - { - DEFINE_FIELD(CBarney, m_fGunDrawn, FIELD_BOOLEAN), - DEFINE_FIELD(CBarney, m_painTime, FIELD_TIME), - DEFINE_FIELD(CBarney, m_checkAttackTime, FIELD_TIME), - DEFINE_FIELD(CBarney, m_lastAttackCheck, FIELD_BOOLEAN), - DEFINE_FIELD(CBarney, m_flPlayerDamage, FIELD_FLOAT), -}; - -IMPLEMENT_SAVERESTORE(CBarney, CTalkMonster); - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= -Task_t tlBaFollow[] = - { - {TASK_MOVE_TO_TARGET_RANGE, (float)128}, // Move within 128 of target ent (client) - {TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE}, -}; - -Schedule_t slBaFollow[] = - { - {tlBaFollow, - ARRAYSIZE(tlBaFollow), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND | - bits_COND_PROVOKED, - bits_SOUND_DANGER, - "Follow"}, -}; - -//========================================================= -// BarneyDraw- much better looking draw schedule for when -// barney knows who he's gonna attack. -//========================================================= -Task_t tlBarneyEnemyDraw[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_FACE_ENEMY, 0}, - {TASK_PLAY_SEQUENCE_FACE_ENEMY, (float)ACT_ARM}, -}; - -Schedule_t slBarneyEnemyDraw[] = - { - {tlBarneyEnemyDraw, - ARRAYSIZE(tlBarneyEnemyDraw), - 0, - 0, - "Barney Enemy Draw"}}; - -Task_t tlBaFaceTarget[] = - { - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_FACE_TARGET, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_SET_SCHEDULE, (float)SCHED_TARGET_CHASE}, -}; - -Schedule_t slBaFaceTarget[] = - { - {tlBaFaceTarget, - ARRAYSIZE(tlBaFaceTarget), - bits_COND_CLIENT_PUSH | - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND | - bits_COND_PROVOKED, - bits_SOUND_DANGER, - "FaceTarget"}, -}; - -Task_t tlIdleBaStand[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_WAIT, (float)2}, // repick IDLESTAND every two seconds. - {TASK_TLK_HEADRESET, (float)0}, // reset head position -}; - -Schedule_t slIdleBaStand[] = - { - {tlIdleBaStand, - ARRAYSIZE(tlIdleBaStand), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND | - bits_COND_SMELL | - bits_COND_PROVOKED, - - bits_SOUND_COMBAT | // sound flags - change these, and you'll break the talking code. - //bits_SOUND_PLAYER | - //bits_SOUND_WORLD | - - bits_SOUND_DANGER | - bits_SOUND_MEAT | // scents - bits_SOUND_CARCASS | - bits_SOUND_GARBAGE, - "IdleStand"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CBarney){ - slBaFollow, - slBarneyEnemyDraw, - slBaFaceTarget, - slIdleBaStand, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CBarney, CTalkMonster); - -void CBarney ::StartTask(Task_t *pTask) -{ - CTalkMonster::StartTask(pTask); -} - -void CBarney ::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_RANGE_ATTACK1: - if (m_hEnemy != NULL && (m_hEnemy->IsPlayer())) - { - pev->framerate = 1.5; - } - CTalkMonster::RunTask(pTask); - break; - default: - CTalkMonster::RunTask(pTask); - break; - } -} - -//========================================================= -// ISoundMask - returns a bit mask indicating which types -// of sounds this monster regards. -//========================================================= -int CBarney ::ISoundMask(void) -{ - return bits_SOUND_WORLD | - bits_SOUND_COMBAT | - bits_SOUND_CARCASS | - bits_SOUND_MEAT | - bits_SOUND_GARBAGE | - bits_SOUND_DANGER | - bits_SOUND_PLAYER; -} - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CBarney ::Classify(void) -{ - return CLASS_PLAYER_ALLY; -} - -//========================================================= -// ALertSound - barney says "Freeze!" -//========================================================= -void CBarney ::AlertSound(void) -{ - if (m_hEnemy != NULL) - { - if (FOkToSpeak()) - { - PlaySentence("BA_ATTACK", RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE); - } - } -} -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CBarney ::SetYawSpeed(void) -{ - int ys; - - ys = 0; - - switch (m_Activity) - { - case ACT_IDLE: - ys = 70; - break; - case ACT_WALK: - ys = 70; - break; - case ACT_RUN: - ys = 90; - break; - default: - ys = 70; - break; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// CheckRangeAttack1 -//========================================================= -BOOL CBarney ::CheckRangeAttack1(float flDot, float flDist) -{ - if (flDist <= 1024 && flDot >= 0.5) - { - if (gpGlobals->time > m_checkAttackTime) - { - TraceResult tr; - - Vector shootOrigin = pev->origin + Vector(0, 0, 55); - CBaseEntity *pEnemy = m_hEnemy; - Vector shootTarget = ((pEnemy->BodyTarget(shootOrigin) - pEnemy->pev->origin) + m_vecEnemyLKP); - UTIL_TraceLine(shootOrigin, shootTarget, dont_ignore_monsters, ENT(pev), &tr); - m_checkAttackTime = gpGlobals->time + 1; - if (tr.flFraction == 1.0 || (tr.pHit != NULL && CBaseEntity::Instance(tr.pHit) == pEnemy)) - m_lastAttackCheck = TRUE; - else - m_lastAttackCheck = FALSE; - m_checkAttackTime = gpGlobals->time + 1.5; - } - return m_lastAttackCheck; - } - return FALSE; -} - -//========================================================= -// BarneyFirePistol - shoots one round from the pistol at -// the enemy barney is facing. -//========================================================= -void CBarney ::BarneyFirePistol(void) -{ - Vector vecShootOrigin; - - UTIL_MakeVectors(pev->angles); - vecShootOrigin = pev->origin + Vector(0, 0, 55); - Vector vecShootDir = ShootAtEnemy(vecShootOrigin); - - Vector angDir = UTIL_VecToAngles(vecShootDir); - SetBlending(0, angDir.x); - pev->effects = EF_MUZZLEFLASH; - - FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_9MM); - - int pitchShift = RANDOM_LONG(0, 20); - - // Only shift about half the time - if (pitchShift > 10) - pitchShift = 0; - else - pitchShift -= 5; - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "barney/ba_attack2.wav", 1, ATTN_NORM, 0, 100 + pitchShift); - - CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, 384, 0.3); - - // UNDONE: Reload? - m_cAmmoLoaded--; // take away a bullet! -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -// -// Returns number of events handled, 0 if none. -//========================================================= -void CBarney ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case BARNEY_AE_SHOOT: - BarneyFirePistol(); - break; - - case BARNEY_AE_DRAW: - // barney's bodygroup switches here so he can pull gun from holster - pev->body = BARNEY_BODY_GUNDRAWN; - m_fGunDrawn = TRUE; - break; - - case BARNEY_AE_HOLSTER: - // change bodygroup to replace gun in holster - pev->body = BARNEY_BODY_GUNHOLSTERED; - m_fGunDrawn = FALSE; - break; - - default: - CTalkMonster::HandleAnimEvent(pEvent); - } -} - -//========================================================= -// Spawn -//========================================================= -void CBarney ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/barney.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->health = gSkillData.barneyHealth; - pev->view_ofs = Vector(0, 0, 50); // position of the eyes relative to monster's origin. - m_flFieldOfView = VIEW_FIELD_WIDE; // NOTE: we need a wide field of view so npc will notice player and say hello - m_MonsterState = MONSTERSTATE_NONE; - - pev->body = 0; // gun in holster - m_fGunDrawn = FALSE; - - m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP; - - MonsterInit(); - SetUse(FollowerUse); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CBarney ::Precache() -{ - PRECACHE_MODEL("models/barney.mdl"); - - PRECACHE_SOUND("barney/ba_attack1.wav"); - PRECACHE_SOUND("barney/ba_attack2.wav"); - - PRECACHE_SOUND("barney/ba_pain1.wav"); - PRECACHE_SOUND("barney/ba_pain2.wav"); - PRECACHE_SOUND("barney/ba_pain3.wav"); - - PRECACHE_SOUND("barney/ba_die1.wav"); - PRECACHE_SOUND("barney/ba_die2.wav"); - PRECACHE_SOUND("barney/ba_die3.wav"); - - // every new barney must call this, otherwise - // when a level is loaded, nobody will talk (time is reset to 0) - TalkInit(); - CTalkMonster::Precache(); -} - -// Init talk data -void CBarney ::TalkInit() -{ - - CTalkMonster::TalkInit(); - - // scientists speach group names (group names are in sentences.txt) - - m_szGrp[TLK_ANSWER] = "BA_ANSWER"; - m_szGrp[TLK_QUESTION] = "BA_QUESTION"; - m_szGrp[TLK_IDLE] = "BA_IDLE"; - m_szGrp[TLK_STARE] = "BA_STARE"; - m_szGrp[TLK_USE] = "BA_OK"; - m_szGrp[TLK_UNUSE] = "BA_WAIT"; - m_szGrp[TLK_STOP] = "BA_STOP"; - - m_szGrp[TLK_NOSHOOT] = "BA_SCARED"; - m_szGrp[TLK_HELLO] = "BA_HELLO"; - - m_szGrp[TLK_PLHURT1] = "!BA_CUREA"; - m_szGrp[TLK_PLHURT2] = "!BA_CUREB"; - m_szGrp[TLK_PLHURT3] = "!BA_CUREC"; - - m_szGrp[TLK_PHELLO] = NULL; //"BA_PHELLO"; // UNDONE - m_szGrp[TLK_PIDLE] = NULL; //"BA_PIDLE"; // UNDONE - m_szGrp[TLK_PQUESTION] = "BA_PQUEST"; // UNDONE - - m_szGrp[TLK_SMELL] = "BA_SMELL"; - - m_szGrp[TLK_WOUND] = "BA_WOUND"; - m_szGrp[TLK_MORTAL] = "BA_MORTAL"; - - // get voice for head - just one barney voice for now - m_voicePitch = 100; -} - -static BOOL IsFacing(entvars_t *pevTest, const Vector &reference) -{ - Vector vecDir = (reference - pevTest->origin); - vecDir.z = 0; - vecDir = vecDir.Normalize(); - Vector forward, angle; - angle = pevTest->v_angle; - angle.x = 0; - UTIL_MakeVectorsPrivate(angle, forward, NULL, NULL); - // He's facing me, he meant it - if (DotProduct(forward, vecDir) > 0.96) // +/- 15 degrees or so - { - return TRUE; - } - return FALSE; -} - -int CBarney ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - // make sure friends talk about it if player hurts talkmonsters... - int ret = CTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); - if (!IsAlive() || pev->deadflag == DEAD_DYING) - return ret; - - if (m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT)) - { - m_flPlayerDamage += flDamage; - - // This is a heurstic to determine if the player intended to harm me - // If I have an enemy, we can't establish intent (may just be crossfire) - if (m_hEnemy == NULL) - { - // If the player was facing directly at me, or I'm already suspicious, get mad - if ((m_afMemory & bits_MEMORY_SUSPICIOUS) || IsFacing(pevAttacker, pev->origin)) - { - // Alright, now I'm pissed! - PlaySentence("BA_MAD", 4, VOL_NORM, ATTN_NORM); - - Remember(bits_MEMORY_PROVOKED); - StopFollowing(TRUE); - } - else - { - // Hey, be careful with that - PlaySentence("BA_SHOT", 4, VOL_NORM, ATTN_NORM); - Remember(bits_MEMORY_SUSPICIOUS); - } - } - else if (!(m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO) - { - PlaySentence("BA_SHOT", 4, VOL_NORM, ATTN_NORM); - } - } - - return ret; -} - -//========================================================= -// PainSound -//========================================================= -void CBarney ::PainSound(void) -{ - if (gpGlobals->time < m_painTime) - return; - - m_painTime = gpGlobals->time + RANDOM_FLOAT(0.5, 0.75); - - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "barney/ba_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "barney/ba_pain2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - case 2: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "barney/ba_pain3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - } -} - -//========================================================= -// DeathSound -//========================================================= -void CBarney ::DeathSound(void) -{ - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "barney/ba_die1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "barney/ba_die2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - case 2: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "barney/ba_die3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - } -} - -void CBarney::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - switch (ptr->iHitgroup) - { - case HITGROUP_CHEST: - case HITGROUP_STOMACH: - if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST)) - { - flDamage = flDamage / 2; - } - break; - case 10: - if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_CLUB)) - { - flDamage -= 20; - if (flDamage <= 0) - { - UTIL_Ricochet(ptr->vecEndPos, 1.0); - flDamage = 0.01; - } - } - // always a head shot - ptr->iHitgroup = HITGROUP_HEAD; - break; - } - - CTalkMonster::TraceAttack(pevAttacker, flDamage, vecDir, ptr, bitsDamageType); -} - -void CBarney::Killed(entvars_t *pevAttacker, int iGib) -{ - if (pev->body < BARNEY_BODY_GUNGONE) - { // drop the gun! - Vector vecGunPos; - Vector vecGunAngles; - - pev->body = BARNEY_BODY_GUNGONE; - - GetAttachment(0, vecGunPos, vecGunAngles); - - CBaseEntity *pGun = DropItem("weapon_9mmhandgun", vecGunPos, vecGunAngles); - } - - SetUse(NULL); - CTalkMonster::Killed(pevAttacker, iGib); -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - -Schedule_t *CBarney ::GetScheduleOfType(int Type) -{ - Schedule_t *psched; - - switch (Type) - { - case SCHED_ARM_WEAPON: - if (m_hEnemy != NULL) - { - // face enemy, then draw. - return slBarneyEnemyDraw; - } - break; - - // Hook these to make a looping schedule - case SCHED_TARGET_FACE: - // call base class default so that barney will talk - // when 'used' - psched = CTalkMonster::GetScheduleOfType(Type); - - if (psched == slIdleStand) - return slBaFaceTarget; // override this for different target face behavior - else - return psched; - - case SCHED_TARGET_CHASE: - return slBaFollow; - - case SCHED_IDLE_STAND: - // call base class default so that scientist will talk - // when standing during idle - psched = CTalkMonster::GetScheduleOfType(Type); - - if (psched == slIdleStand) - { - // just look straight ahead. - return slIdleBaStand; - } - else - return psched; - } - - return CTalkMonster::GetScheduleOfType(Type); -} - -//========================================================= -// GetSchedule - Decides which type of schedule best suits -// the monster's current state and conditions. Then calls -// monster's member function to get a pointer to a schedule -// of the proper type. -//========================================================= -Schedule_t *CBarney ::GetSchedule(void) -{ - if (HasConditions(bits_COND_HEAR_SOUND)) - { - CSound *pSound; - pSound = PBestSound(); - - ASSERT(pSound != NULL); - if (pSound && (pSound->m_iType & bits_SOUND_DANGER)) - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_BEST_SOUND); - } - if (HasConditions(bits_COND_ENEMY_DEAD) && FOkToSpeak()) - { - PlaySentence("BA_KILL", 4, VOL_NORM, ATTN_NORM); - } - - switch (m_MonsterState) - { - case MONSTERSTATE_COMBAT: - { - // dead enemy - if (HasConditions(bits_COND_ENEMY_DEAD)) - { - // call base class, all code to handle dead enemies is centralized there. - return CBaseMonster ::GetSchedule(); - } - - // always act surprized with a new enemy - if (HasConditions(bits_COND_NEW_ENEMY) && HasConditions(bits_COND_LIGHT_DAMAGE)) - return GetScheduleOfType(SCHED_SMALL_FLINCH); - - // wait for one schedule to draw gun - if (!m_fGunDrawn) - return GetScheduleOfType(SCHED_ARM_WEAPON); - - if (HasConditions(bits_COND_HEAVY_DAMAGE)) - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_ENEMY); - } - break; - - case MONSTERSTATE_ALERT: - case MONSTERSTATE_IDLE: - if (HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE)) - { - // flinch if hurt - return GetScheduleOfType(SCHED_SMALL_FLINCH); - } - - if (m_hEnemy == NULL && IsFollowing()) - { - if (!m_hTargetEnt->IsAlive()) - { - // UNDONE: Comment about the recently dead player here? - StopFollowing(FALSE); - break; - } - else - { - if (HasConditions(bits_COND_CLIENT_PUSH)) - { - return GetScheduleOfType(SCHED_MOVE_AWAY_FOLLOW); - } - return GetScheduleOfType(SCHED_TARGET_FACE); - } - } - - if (HasConditions(bits_COND_CLIENT_PUSH)) - { - return GetScheduleOfType(SCHED_MOVE_AWAY); - } - - // try to say something about smells - TrySmellTalk(); - break; - } - - return CTalkMonster::GetSchedule(); -} - -MONSTERSTATE CBarney ::GetIdealState(void) -{ - return CTalkMonster::GetIdealState(); -} - -void CBarney::DeclineFollowing(void) -{ - PlaySentence("BA_POK", 2, VOL_NORM, ATTN_NORM); -} - -//========================================================= -// DEAD BARNEY PROP -// -// Designer selects a pose in worldcraft, 0 through num_poses-1 -// this value is added to what is selected as the 'first dead pose' -// among the monster's normal animations. All dead poses must -// appear sequentially in the model file. Be sure and set -// the m_iFirstPose properly! -// -//========================================================= -class CDeadBarney : public CBaseMonster -{ -public: - void Spawn(void); - int Classify(void) { return CLASS_PLAYER_ALLY; } - - void KeyValue(KeyValueData *pkvd); - - int m_iPose; // which sequence to display -- temporary, don't need to save - static char *m_szPoses[3]; -}; - -char *CDeadBarney::m_szPoses[] = {"lying_on_back", "lying_on_side", "lying_on_stomach"}; - -void CDeadBarney::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "pose")) - { - m_iPose = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else - CBaseMonster::KeyValue(pkvd); -} - -LINK_ENTITY_TO_CLASS(monster_barney_dead, CDeadBarney); - -//========================================================= -// ********** DeadBarney SPAWN ********** -//========================================================= -void CDeadBarney ::Spawn() -{ - PRECACHE_MODEL("models/barney.mdl"); - SET_MODEL(ENT(pev), "models/barney.mdl"); - - pev->effects = 0; - pev->yaw_speed = 8; - pev->sequence = 0; - m_bloodColor = BLOOD_COLOR_RED; - - pev->sequence = LookupSequence(m_szPoses[m_iPose]); - if (pev->sequence == -1) - { - ALERT(at_console, "Dead barney with bad pose\n"); - } - // Corpses have less health - pev->health = 8; //gSkillData.barneyHealth; - - MonsterInitDead(); -} diff --git a/dlls/Half-life/bigmomma.cpp b/dlls/Half-life/bigmomma.cpp deleted file mode 100644 index 9e70d0b6..00000000 --- a/dlls/Half-life/bigmomma.cpp +++ /dev/null @@ -1,1207 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -//========================================================= -// monster template -//========================================================= -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" -#include "decals.h" -#include "weapons.h" - -#define SF_INFOBM_RUN 0x0001 -#define SF_INFOBM_WAIT 0x0002 - -// AI Nodes for Big Momma -class CInfoBM : public CPointEntity -{ -public: - void Spawn(void); - void KeyValue(KeyValueData *pkvd); - - // name in pev->targetname - // next in pev->target - // radius in pev->scale - // health in pev->health - // Reach target in pev->message - // Reach delay in pev->speed - // Reach sequence in pev->netname - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - int m_preSequence; -}; - -LINK_ENTITY_TO_CLASS(info_bigmomma, CInfoBM); - -TYPEDESCRIPTION CInfoBM::m_SaveData[] = - { - DEFINE_FIELD(CInfoBM, m_preSequence, FIELD_STRING), -}; - -IMPLEMENT_SAVERESTORE(CInfoBM, CPointEntity); - -void CInfoBM::Spawn(void) -{ -} - -void CInfoBM::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "radius")) - { - pev->scale = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "reachdelay")) - { - pev->speed = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "reachtarget")) - { - pev->message = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "reachsequence")) - { - pev->netname = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "presequence")) - { - m_preSequence = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else - CPointEntity::KeyValue(pkvd); -} - -//========================================================= -// Mortar shot entity -//========================================================= -class CBMortar : public CBaseEntity -{ -public: - void Spawn(void); - - static CBMortar *Shoot(edict_t *pOwner, Vector vecStart, Vector vecVelocity); - void Touch(CBaseEntity *pOther); - void EXPORT Animate(void); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - int m_maxFrame; -}; - -LINK_ENTITY_TO_CLASS(bmortar, CBMortar); - -TYPEDESCRIPTION CBMortar::m_SaveData[] = - { - DEFINE_FIELD(CBMortar, m_maxFrame, FIELD_INTEGER), -}; - -IMPLEMENT_SAVERESTORE(CBMortar, CBaseEntity); - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define BIG_AE_STEP1 1 // Footstep left -#define BIG_AE_STEP2 2 // Footstep right -#define BIG_AE_STEP3 3 // Footstep back left -#define BIG_AE_STEP4 4 // Footstep back right -#define BIG_AE_SACK 5 // Sack slosh -#define BIG_AE_DEATHSOUND 6 // Death sound - -#define BIG_AE_MELEE_ATTACKBR 8 // Leg attack -#define BIG_AE_MELEE_ATTACKBL 9 // Leg attack -#define BIG_AE_MELEE_ATTACK1 10 // Leg attack -#define BIG_AE_MORTAR_ATTACK1 11 // Launch a mortar -#define BIG_AE_LAY_CRAB 12 // Lay a headcrab -#define BIG_AE_JUMP_FORWARD 13 // Jump up and forward -#define BIG_AE_SCREAM 14 // alert sound -#define BIG_AE_PAIN_SOUND 15 // pain sound -#define BIG_AE_ATTACK_SOUND 16 // attack sound -#define BIG_AE_BIRTH_SOUND 17 // birth sound -#define BIG_AE_EARLY_TARGET 50 // Fire target early - -// User defined conditions -#define bits_COND_NODE_SEQUENCE (bits_COND_SPECIAL1) // pev->netname contains the name of a sequence to play - -// Attack distance constants -#define BIG_ATTACKDIST 170 -#define BIG_MORTARDIST 800 -#define BIG_MAXCHILDREN 20 // Max # of live headcrab children - -#define bits_MEMORY_CHILDPAIR (bits_MEMORY_CUSTOM1) -#define bits_MEMORY_ADVANCE_NODE (bits_MEMORY_CUSTOM2) -#define bits_MEMORY_COMPLETED_NODE (bits_MEMORY_CUSTOM3) -#define bits_MEMORY_FIRED_NODE (bits_MEMORY_CUSTOM4) - -int gSpitSprite, gSpitDebrisSprite; -Vector VecCheckSplatToss(entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float maxHeight); -void MortarSpray(const Vector &position, const Vector &direction, int spriteModel, int count); - -// UNDONE: -// -#define BIG_CHILDCLASS "monster_babycrab" - -class CBigMomma : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void KeyValue(KeyValueData *pkvd); - void Activate(void); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - - void RunTask(Task_t *pTask); - void StartTask(Task_t *pTask); - Schedule_t *GetSchedule(void); - Schedule_t *GetScheduleOfType(int Type); - void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - - void NodeStart(int iszNextNode); - void NodeReach(void); - BOOL ShouldGoToNode(void); - - void SetYawSpeed(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - void LayHeadcrab(void); - - int GetNodeSequence(void) - { - CBaseEntity *pTarget = m_hTargetEnt; - if (pTarget) - { - return pTarget->pev->netname; // netname holds node sequence - } - return 0; - } - - int GetNodePresequence(void) - { - CInfoBM *pTarget = (CInfoBM *)(CBaseEntity *)m_hTargetEnt; - if (pTarget) - { - return pTarget->m_preSequence; - } - return 0; - } - - float GetNodeDelay(void) - { - CBaseEntity *pTarget = m_hTargetEnt; - if (pTarget) - { - return pTarget->pev->speed; // Speed holds node delay - } - return 0; - } - - float GetNodeRange(void) - { - CBaseEntity *pTarget = m_hTargetEnt; - if (pTarget) - { - return pTarget->pev->scale; // Scale holds node delay - } - return 1e6; - } - - float GetNodeYaw(void) - { - CBaseEntity *pTarget = m_hTargetEnt; - if (pTarget) - { - if (pTarget->pev->angles.y != 0) - return pTarget->pev->angles.y; - } - return pev->angles.y; - } - - // Restart the crab count on each new level - void OverrideReset(void) - { - m_crabCount = 0; - } - - void DeathNotice(entvars_t *pevChild); - - BOOL CanLayCrab(void) - { - if (m_crabTime < gpGlobals->time && m_crabCount < BIG_MAXCHILDREN) - { - // Don't spawn crabs inside each other - Vector mins = pev->origin - Vector(32, 32, 0); - Vector maxs = pev->origin + Vector(32, 32, 0); - - CBaseEntity *pList[2]; - int count = UTIL_EntitiesInBox(pList, 2, mins, maxs, FL_MONSTER); - for (int i = 0; i < count; i++) - { - if (pList[i] != this) // Don't hurt yourself! - return FALSE; - } - return TRUE; - } - - return FALSE; - } - - void LaunchMortar(void); - - void SetObjectCollisionBox(void) - { - pev->absmin = pev->origin + Vector(-95, -95, 0); - pev->absmax = pev->origin + Vector(95, 95, 190); - } - - BOOL CheckMeleeAttack1(float flDot, float flDist); // Slash - BOOL CheckMeleeAttack2(float flDot, float flDist); // Lay a crab - BOOL CheckRangeAttack1(float flDot, float flDist); // Mortar launch - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - static const char *pChildDieSounds[]; - static const char *pSackSounds[]; - static const char *pDeathSounds[]; - static const char *pAttackSounds[]; - static const char *pAttackHitSounds[]; - static const char *pBirthSounds[]; - static const char *pAlertSounds[]; - static const char *pPainSounds[]; - static const char *pFootSounds[]; - - CUSTOM_SCHEDULES; - -private: - float m_nodeTime; - float m_crabTime; - float m_mortarTime; - float m_painSoundTime; - int m_crabCount; -}; -LINK_ENTITY_TO_CLASS(monster_bigmomma, CBigMomma); - -TYPEDESCRIPTION CBigMomma::m_SaveData[] = - { - DEFINE_FIELD(CBigMomma, m_nodeTime, FIELD_TIME), - DEFINE_FIELD(CBigMomma, m_crabTime, FIELD_TIME), - DEFINE_FIELD(CBigMomma, m_mortarTime, FIELD_TIME), - DEFINE_FIELD(CBigMomma, m_painSoundTime, FIELD_TIME), - DEFINE_FIELD(CBigMomma, m_crabCount, FIELD_INTEGER), -}; - -IMPLEMENT_SAVERESTORE(CBigMomma, CBaseMonster); - -const char *CBigMomma::pChildDieSounds[] = - { - "gonarch/gon_childdie1.wav", - "gonarch/gon_childdie2.wav", - "gonarch/gon_childdie3.wav", -}; - -const char *CBigMomma::pSackSounds[] = - { - "gonarch/gon_sack1.wav", - "gonarch/gon_sack2.wav", - "gonarch/gon_sack3.wav", -}; - -const char *CBigMomma::pDeathSounds[] = - { - "gonarch/gon_die1.wav", -}; - -const char *CBigMomma::pAttackSounds[] = - { - "gonarch/gon_attack1.wav", - "gonarch/gon_attack2.wav", - "gonarch/gon_attack3.wav", -}; -const char *CBigMomma::pAttackHitSounds[] = - { - "zombie/claw_strike1.wav", - "zombie/claw_strike2.wav", - "zombie/claw_strike3.wav", -}; - -const char *CBigMomma::pBirthSounds[] = - { - "gonarch/gon_birth1.wav", - "gonarch/gon_birth2.wav", - "gonarch/gon_birth3.wav", -}; - -const char *CBigMomma::pAlertSounds[] = - { - "gonarch/gon_alert1.wav", - "gonarch/gon_alert2.wav", - "gonarch/gon_alert3.wav", -}; - -const char *CBigMomma::pPainSounds[] = - { - "gonarch/gon_pain2.wav", - "gonarch/gon_pain4.wav", - "gonarch/gon_pain5.wav", -}; - -const char *CBigMomma::pFootSounds[] = - { - "gonarch/gon_step1.wav", - "gonarch/gon_step2.wav", - "gonarch/gon_step3.wav", -}; - -void CBigMomma ::KeyValue(KeyValueData *pkvd) -{ -#if 0 - if (FStrEq(pkvd->szKeyName, "volume")) - { - m_volume = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else -#endif - CBaseMonster::KeyValue(pkvd); -} - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CBigMomma ::Classify(void) -{ - return CLASS_ALIEN_MONSTER; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CBigMomma ::SetYawSpeed(void) -{ - int ys; - - switch (m_Activity) - { - case ACT_IDLE: - ys = 100; - break; - default: - ys = 90; - } - pev->yaw_speed = ys; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -// -// Returns number of events handled, 0 if none. -//========================================================= -void CBigMomma ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case BIG_AE_MELEE_ATTACKBR: - case BIG_AE_MELEE_ATTACKBL: - case BIG_AE_MELEE_ATTACK1: - { - Vector forward, right; - - UTIL_MakeVectorsPrivate(pev->angles, forward, right, NULL); - - Vector center = pev->origin + forward * 128; - Vector mins = center - Vector(64, 64, 0); - Vector maxs = center + Vector(64, 64, 64); - - CBaseEntity *pList[8]; - int count = UTIL_EntitiesInBox(pList, 8, mins, maxs, FL_MONSTER | FL_CLIENT); - CBaseEntity *pHurt = NULL; - - for (int i = 0; i < count && !pHurt; i++) - { - if (pList[i] != this) - { - if (pList[i]->pev->owner != edict()) - pHurt = pList[i]; - } - } - - if (pHurt) - { - pHurt->TakeDamage(pev, pev, gSkillData.bigmommaDmgSlash, DMG_CRUSH | DMG_SLASH); - pHurt->pev->punchangle.x = 15; - switch (pEvent->event) - { - case BIG_AE_MELEE_ATTACKBR: - pHurt->pev->velocity = pHurt->pev->velocity + (forward * 150) + Vector(0, 0, 250) - (right * 200); - break; - - case BIG_AE_MELEE_ATTACKBL: - pHurt->pev->velocity = pHurt->pev->velocity + (forward * 150) + Vector(0, 0, 250) + (right * 200); - break; - - case BIG_AE_MELEE_ATTACK1: - pHurt->pev->velocity = pHurt->pev->velocity + (forward * 220) + Vector(0, 0, 200); - break; - } - - pHurt->pev->flags &= ~FL_ONGROUND; - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackHitSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); - } - } - break; - - case BIG_AE_SCREAM: - EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pAlertSounds); - break; - - case BIG_AE_PAIN_SOUND: - EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pPainSounds); - break; - - case BIG_AE_ATTACK_SOUND: - EMIT_SOUND_ARRAY_DYN(CHAN_WEAPON, pAttackSounds); - break; - - case BIG_AE_BIRTH_SOUND: - EMIT_SOUND_ARRAY_DYN(CHAN_BODY, pBirthSounds); - break; - - case BIG_AE_SACK: - if (RANDOM_LONG(0, 100) < 30) - EMIT_SOUND_ARRAY_DYN(CHAN_BODY, pSackSounds); - break; - - case BIG_AE_DEATHSOUND: - EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pDeathSounds); - break; - - case BIG_AE_STEP1: // Footstep left - case BIG_AE_STEP3: // Footstep back left - EMIT_SOUND_ARRAY_DYN(CHAN_ITEM, pFootSounds); - break; - - case BIG_AE_STEP4: // Footstep back right - case BIG_AE_STEP2: // Footstep right - EMIT_SOUND_ARRAY_DYN(CHAN_BODY, pFootSounds); - break; - - case BIG_AE_MORTAR_ATTACK1: - LaunchMortar(); - break; - - case BIG_AE_LAY_CRAB: - LayHeadcrab(); - break; - - case BIG_AE_JUMP_FORWARD: - ClearBits(pev->flags, FL_ONGROUND); - - UTIL_SetOrigin(pev, pev->origin + Vector(0, 0, 1)); // take him off ground so engine doesn't instantly reset onground - UTIL_MakeVectors(pev->angles); - - pev->velocity = (gpGlobals->v_forward * 200) + gpGlobals->v_up * 500; - break; - - case BIG_AE_EARLY_TARGET: - { - CBaseEntity *pTarget = m_hTargetEnt; - if (pTarget && pTarget->pev->message) - FireTargets(STRING(pTarget->pev->message), this, this, USE_TOGGLE, 0); - Remember(bits_MEMORY_FIRED_NODE); - } - break; - - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -void CBigMomma ::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - if (ptr->iHitgroup != 1) - { - // didn't hit the sack? - - if (pev->dmgtime != gpGlobals->time || (RANDOM_LONG(0, 10) < 1)) - { - UTIL_Ricochet(ptr->vecEndPos, RANDOM_FLOAT(1, 2)); - pev->dmgtime = gpGlobals->time; - } - - flDamage = 0.1; // don't hurt the monster much, but allow bits_COND_LIGHT_DAMAGE to be generated - } - else if (gpGlobals->time > m_painSoundTime) - { - m_painSoundTime = gpGlobals->time + RANDOM_LONG(1, 3); - EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pPainSounds); - } - - CBaseMonster::TraceAttack(pevAttacker, flDamage, vecDir, ptr, bitsDamageType); -} - -int CBigMomma ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - // Don't take any acid damage -- BigMomma's mortar is acid - if (bitsDamageType & DMG_ACID) - flDamage = 0; - - if (!HasMemory(bits_MEMORY_PATH_FINISHED)) - { - if (pev->health <= flDamage) - { - pev->health = flDamage + 1; - Remember(bits_MEMORY_ADVANCE_NODE | bits_MEMORY_COMPLETED_NODE); - ALERT(at_aiconsole, "BM: Finished node health!!!\n"); - } - } - - return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -void CBigMomma ::LayHeadcrab(void) -{ - CBaseEntity *pChild = CBaseEntity::Create(BIG_CHILDCLASS, pev->origin, pev->angles, edict()); - - pChild->pev->spawnflags |= SF_MONSTER_FALL_TO_GROUND; - - // Is this the second crab in a pair? - if (HasMemory(bits_MEMORY_CHILDPAIR)) - { - m_crabTime = gpGlobals->time + RANDOM_FLOAT(5, 10); - Forget(bits_MEMORY_CHILDPAIR); - } - else - { - m_crabTime = gpGlobals->time + RANDOM_FLOAT(0.5, 2.5); - Remember(bits_MEMORY_CHILDPAIR); - } - - TraceResult tr; - UTIL_TraceLine(pev->origin, pev->origin - Vector(0, 0, 100), ignore_monsters, edict(), &tr); - UTIL_DecalTrace(&tr, DECAL_MOMMABIRTH); - - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pBirthSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); - m_crabCount++; -} - -void CBigMomma::DeathNotice(entvars_t *pevChild) -{ - if (m_crabCount > 0) // Some babies may cross a transition, but we reset the count then - m_crabCount--; - if (IsAlive()) - { - // Make the "my baby's dead" noise! - EMIT_SOUND_ARRAY_DYN(CHAN_WEAPON, pChildDieSounds); - } -} - -void CBigMomma::LaunchMortar(void) -{ - m_mortarTime = gpGlobals->time + RANDOM_FLOAT(2, 15); - - Vector startPos = pev->origin; - startPos.z += 180; - - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pSackSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); - CBMortar *pBomb = CBMortar::Shoot(edict(), startPos, pev->movedir); - pBomb->pev->gravity = 1.0; - MortarSpray(startPos, Vector(0, 0, 1), gSpitSprite, 24); -} - -//========================================================= -// Spawn -//========================================================= -void CBigMomma ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/big_mom.mdl"); - UTIL_SetSize(pev, Vector(-32, -32, 0), Vector(32, 32, 64)); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->health = 150 * gSkillData.bigmommaHealthFactor; - pev->view_ofs = Vector(0, 0, 128); // position of the eyes relative to monster's origin. - m_flFieldOfView = 0.3; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CBigMomma ::Precache() -{ - PRECACHE_MODEL("models/big_mom.mdl"); - - PRECACHE_SOUND_ARRAY(pChildDieSounds); - PRECACHE_SOUND_ARRAY(pSackSounds); - PRECACHE_SOUND_ARRAY(pDeathSounds); - PRECACHE_SOUND_ARRAY(pAttackSounds); - PRECACHE_SOUND_ARRAY(pAttackHitSounds); - PRECACHE_SOUND_ARRAY(pBirthSounds); - PRECACHE_SOUND_ARRAY(pAlertSounds); - PRECACHE_SOUND_ARRAY(pPainSounds); - PRECACHE_SOUND_ARRAY(pFootSounds); - - UTIL_PrecacheOther(BIG_CHILDCLASS); - - // TEMP: Squid - PRECACHE_MODEL("sprites/mommaspit.spr"); // spit projectile. - gSpitSprite = PRECACHE_MODEL("sprites/mommaspout.spr"); // client side spittle. - gSpitDebrisSprite = PRECACHE_MODEL("sprites/mommablob.spr"); - - PRECACHE_SOUND("bullchicken/bc_acid1.wav"); - PRECACHE_SOUND("bullchicken/bc_spithit1.wav"); - PRECACHE_SOUND("bullchicken/bc_spithit2.wav"); -} - -void CBigMomma::Activate(void) -{ - if (m_hTargetEnt == NULL) - Remember(bits_MEMORY_ADVANCE_NODE); // Start 'er up -} - -void CBigMomma::NodeStart(int iszNextNode) -{ - pev->netname = iszNextNode; - - CBaseEntity *pTarget = NULL; - - if (pev->netname) - { - edict_t *pentTarget = FIND_ENTITY_BY_TARGETNAME(NULL, STRING(pev->netname)); - - if (!FNullEnt(pentTarget)) - pTarget = Instance(pentTarget); - } - - if (!pTarget) - { - ALERT(at_aiconsole, "BM: Finished the path!!\n"); - Remember(bits_MEMORY_PATH_FINISHED); - return; - } - Remember(bits_MEMORY_ON_PATH); - m_hTargetEnt = pTarget; -} - -void CBigMomma::NodeReach(void) -{ - CBaseEntity *pTarget = m_hTargetEnt; - - Forget(bits_MEMORY_ADVANCE_NODE); - - if (!pTarget) - return; - - if (pTarget->pev->health) - pev->max_health = pev->health = pTarget->pev->health * gSkillData.bigmommaHealthFactor; - - if (!HasMemory(bits_MEMORY_FIRED_NODE)) - { - if (pTarget->pev->message) - FireTargets(STRING(pTarget->pev->message), this, this, USE_TOGGLE, 0); - } - Forget(bits_MEMORY_FIRED_NODE); - - pev->netname = pTarget->pev->target; - if (pTarget->pev->health == 0) - Remember(bits_MEMORY_ADVANCE_NODE); // Move on if no health at this node -} - -// Slash -BOOL CBigMomma::CheckMeleeAttack1(float flDot, float flDist) -{ - if (flDot >= 0.7) - { - if (flDist <= BIG_ATTACKDIST) - return TRUE; - } - return FALSE; -} - -// Lay a crab -BOOL CBigMomma::CheckMeleeAttack2(float flDot, float flDist) -{ - return CanLayCrab(); -} - -// Mortar launch -BOOL CBigMomma::CheckRangeAttack1(float flDot, float flDist) -{ - if (flDist <= BIG_MORTARDIST && m_mortarTime < gpGlobals->time) - { - CBaseEntity *pEnemy = m_hEnemy; - - if (pEnemy) - { - Vector startPos = pev->origin; - startPos.z += 180; - pev->movedir = VecCheckSplatToss(pev, startPos, pEnemy->BodyTarget(pev->origin), RANDOM_FLOAT(150, 500)); - if (pev->movedir != g_vecZero) - return TRUE; - } - } - return FALSE; -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - -enum -{ - SCHED_BIG_NODE = LAST_COMMON_SCHEDULE + 1, - SCHED_NODE_FAIL, -}; - -enum -{ - TASK_MOVE_TO_NODE_RANGE = LAST_COMMON_TASK + 1, // Move within node range - TASK_FIND_NODE, // Find my next node - TASK_PLAY_NODE_PRESEQUENCE, // Play node pre-script - TASK_PLAY_NODE_SEQUENCE, // Play node script - TASK_PROCESS_NODE, // Fire targets, etc. - TASK_WAIT_NODE, // Wait at the node - TASK_NODE_DELAY, // Delay walking toward node for a bit. You've failed to get there - TASK_NODE_YAW, // Get the best facing direction for this node -}; - -Task_t tlBigNode[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_NODE_FAIL}, - {TASK_STOP_MOVING, (float)0}, - {TASK_FIND_NODE, (float)0}, // Find my next node - {TASK_PLAY_NODE_PRESEQUENCE, (float)0}, // Play the pre-approach sequence if any - {TASK_MOVE_TO_NODE_RANGE, (float)0}, // Move within node range - {TASK_STOP_MOVING, (float)0}, - {TASK_NODE_YAW, (float)0}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_WAIT_NODE, (float)0}, // Wait for node delay - {TASK_PLAY_NODE_SEQUENCE, (float)0}, // Play the sequence if one exists - {TASK_PROCESS_NODE, (float)0}, // Fire targets, etc. - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, -}; - -Schedule_t slBigNode[] = - { - {tlBigNode, - ARRAYSIZE(tlBigNode), - 0, - 0, - "Big Node"}, -}; - -Task_t tlNodeFail[] = - { - {TASK_NODE_DELAY, (float)10}, // Try to do something else for 10 seconds - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, -}; - -Schedule_t slNodeFail[] = - { - {tlNodeFail, - ARRAYSIZE(tlNodeFail), - 0, - 0, - "NodeFail"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CBigMomma){ - slBigNode, - slNodeFail, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CBigMomma, CBaseMonster); - -Schedule_t *CBigMomma::GetScheduleOfType(int Type) -{ - switch (Type) - { - case SCHED_BIG_NODE: - return slBigNode; - break; - - case SCHED_NODE_FAIL: - return slNodeFail; - break; - } - - return CBaseMonster::GetScheduleOfType(Type); -} - -BOOL CBigMomma::ShouldGoToNode(void) -{ - if (HasMemory(bits_MEMORY_ADVANCE_NODE)) - { - if (m_nodeTime < gpGlobals->time) - return TRUE; - } - return FALSE; -} - -Schedule_t *CBigMomma::GetSchedule(void) -{ - if (ShouldGoToNode()) - { - return GetScheduleOfType(SCHED_BIG_NODE); - } - - return CBaseMonster::GetSchedule(); -} - -void CBigMomma::StartTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_FIND_NODE: - { - CBaseEntity *pTarget = m_hTargetEnt; - if (!HasMemory(bits_MEMORY_ADVANCE_NODE)) - { - if (pTarget) - pev->netname = m_hTargetEnt->pev->target; - } - NodeStart(pev->netname); - TaskComplete(); - ALERT(at_aiconsole, "BM: Found node %s\n", STRING(pev->netname)); - } - break; - - case TASK_NODE_DELAY: - m_nodeTime = gpGlobals->time + pTask->flData; - TaskComplete(); - ALERT(at_aiconsole, "BM: FAIL! Delay %.2f\n", pTask->flData); - break; - - case TASK_PROCESS_NODE: - ALERT(at_aiconsole, "BM: Reached node %s\n", STRING(pev->netname)); - NodeReach(); - TaskComplete(); - break; - - case TASK_PLAY_NODE_PRESEQUENCE: - case TASK_PLAY_NODE_SEQUENCE: - { - int sequence; - if (pTask->iTask == TASK_PLAY_NODE_SEQUENCE) - sequence = GetNodeSequence(); - else - sequence = GetNodePresequence(); - - ALERT(at_aiconsole, "BM: Playing node sequence %s\n", STRING(sequence)); - if (sequence) - { - sequence = LookupSequence(STRING(sequence)); - if (sequence != -1) - { - pev->sequence = sequence; - pev->frame = 0; - ResetSequenceInfo(); - ALERT(at_aiconsole, "BM: Sequence %s\n", STRING(GetNodeSequence())); - return; - } - } - TaskComplete(); - } - break; - - case TASK_NODE_YAW: - pev->ideal_yaw = GetNodeYaw(); - TaskComplete(); - break; - - case TASK_WAIT_NODE: - m_flWait = gpGlobals->time + GetNodeDelay(); - if (m_hTargetEnt->pev->spawnflags & SF_INFOBM_WAIT) - ALERT(at_aiconsole, "BM: Wait at node %s forever\n", STRING(pev->netname)); - else - ALERT(at_aiconsole, "BM: Wait at node %s for %.2f\n", STRING(pev->netname), GetNodeDelay()); - break; - - case TASK_MOVE_TO_NODE_RANGE: - { - CBaseEntity *pTarget = m_hTargetEnt; - if (!pTarget) - TaskFail(); - else - { - if ((pTarget->pev->origin - pev->origin).Length() < GetNodeRange()) - TaskComplete(); - else - { - Activity act = ACT_WALK; - if (pTarget->pev->spawnflags & SF_INFOBM_RUN) - act = ACT_RUN; - - m_vecMoveGoal = pTarget->pev->origin; - if (!MoveToTarget(act, 2)) - { - TaskFail(); - } - } - } - } - ALERT(at_aiconsole, "BM: Moving to node %s\n", STRING(pev->netname)); - - break; - - case TASK_MELEE_ATTACK1: - // Play an attack sound here - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAttackSounds), 1.0, ATTN_NORM, 0, PITCH_NORM); - CBaseMonster::StartTask(pTask); - break; - - default: - CBaseMonster::StartTask(pTask); - break; - } -} - -//========================================================= -// RunTask -//========================================================= -void CBigMomma::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_MOVE_TO_NODE_RANGE: - { - float distance; - - if (m_hTargetEnt == NULL) - TaskFail(); - else - { - distance = (m_vecMoveGoal - pev->origin).Length2D(); - // Set the appropriate activity based on an overlapping range - // overlap the range to prevent oscillation - if ((distance < GetNodeRange()) || MovementIsComplete()) - { - ALERT(at_aiconsole, "BM: Reached node!\n"); - TaskComplete(); - RouteClear(); // Stop moving - } - } - } - - break; - - case TASK_WAIT_NODE: - if (m_hTargetEnt != NULL && (m_hTargetEnt->pev->spawnflags & SF_INFOBM_WAIT)) - return; - - if (gpGlobals->time > m_flWaitFinished) - TaskComplete(); - ALERT(at_aiconsole, "BM: The WAIT is over!\n"); - break; - - case TASK_PLAY_NODE_PRESEQUENCE: - case TASK_PLAY_NODE_SEQUENCE: - if (m_fSequenceFinished) - { - m_Activity = ACT_RESET; - TaskComplete(); - } - break; - - default: - CBaseMonster::RunTask(pTask); - break; - } -} - -Vector VecCheckSplatToss(entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float maxHeight) -{ - TraceResult tr; - Vector vecMidPoint; // halfway point between Spot1 and Spot2 - Vector vecApex; // highest point - Vector vecScale; - Vector vecGrenadeVel; - Vector vecTemp; - float flGravity = CVAR_GET_FLOAT("sv_gravity"); - - // calculate the midpoint and apex of the 'triangle' - vecMidPoint = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5; - UTIL_TraceLine(vecMidPoint, vecMidPoint + Vector(0, 0, maxHeight), ignore_monsters, ENT(pev), &tr); - vecApex = tr.vecEndPos; - - UTIL_TraceLine(vecSpot1, vecApex, dont_ignore_monsters, ENT(pev), &tr); - if (tr.flFraction != 1.0) - { - // fail! - return g_vecZero; - } - - // Don't worry about actually hitting the target, this won't hurt us! - - // How high should the grenade travel (subtract 15 so the grenade doesn't hit the ceiling)? - float height = (vecApex.z - vecSpot1.z) - 15; - // How fast does the grenade need to travel to reach that height given gravity? - float speed = sqrt(2 * flGravity * height); - - // How much time does it take to get there? - float time = speed / flGravity; - vecGrenadeVel = (vecSpot2 - vecSpot1); - vecGrenadeVel.z = 0; - float distance = vecGrenadeVel.Length(); - - // Travel half the distance to the target in that time (apex is at the midpoint) - vecGrenadeVel = vecGrenadeVel * (0.5 / time); - // Speed to offset gravity at the desired height - vecGrenadeVel.z = speed; - - return vecGrenadeVel; -} - -// --------------------------------- -// -// Mortar -// -// --------------------------------- -void MortarSpray(const Vector &position, const Vector &direction, int spriteModel, int count) -{ - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, position); - WRITE_BYTE(TE_SPRITE_SPRAY); - WRITE_COORD(position.x); // pos - WRITE_COORD(position.y); - WRITE_COORD(position.z); - WRITE_COORD(direction.x); // dir - WRITE_COORD(direction.y); - WRITE_COORD(direction.z); - WRITE_SHORT(spriteModel); // model - WRITE_BYTE(count); // count - WRITE_BYTE(130); // speed - WRITE_BYTE(80); // noise ( client will divide by 100 ) - MESSAGE_END(); -} - -// UNDONE: right now this is pretty much a copy of the squid spit with minor changes to the way it does damage -void CBMortar::Spawn(void) -{ - pev->movetype = MOVETYPE_TOSS; - pev->classname = MAKE_STRING("bmortar"); - - pev->solid = SOLID_BBOX; - pev->rendermode = kRenderTransAlpha; - pev->renderamt = 255; - - SET_MODEL(ENT(pev), "sprites/mommaspit.spr"); - pev->frame = 0; - pev->scale = 0.5; - - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); - - m_maxFrame = (float)MODEL_FRAMES(pev->modelindex) - 1; - pev->dmgtime = gpGlobals->time + 0.4; -} - -void CBMortar::Animate(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - if (gpGlobals->time > pev->dmgtime) - { - pev->dmgtime = gpGlobals->time + 0.2; - MortarSpray(pev->origin, -pev->velocity.Normalize(), gSpitSprite, 3); - } - if (pev->frame++) - { - if (pev->frame > m_maxFrame) - { - pev->frame = 0; - } - } -} - -CBMortar *CBMortar::Shoot(edict_t *pOwner, Vector vecStart, Vector vecVelocity) -{ - CBMortar *pSpit = GetClassPtr((CBMortar *)NULL); - pSpit->Spawn(); - - UTIL_SetOrigin(pSpit->pev, vecStart); - pSpit->pev->velocity = vecVelocity; - pSpit->pev->owner = pOwner; - pSpit->pev->scale = 2.5; - pSpit->SetThink(Animate); - pSpit->pev->nextthink = gpGlobals->time + 0.1; - - return pSpit; -} - -void CBMortar::Touch(CBaseEntity *pOther) -{ - TraceResult tr; - int iPitch; - - // splat sound - iPitch = RANDOM_FLOAT(90, 110); - - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "bullchicken/bc_acid1.wav", 1, ATTN_NORM, 0, iPitch); - - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "bullchicken/bc_spithit1.wav", 1, ATTN_NORM, 0, iPitch); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "bullchicken/bc_spithit2.wav", 1, ATTN_NORM, 0, iPitch); - break; - } - - if (pOther->IsBSPModel()) - { - - // make a splat on the wall - UTIL_TraceLine(pev->origin, pev->origin + pev->velocity * 10, dont_ignore_monsters, ENT(pev), &tr); - UTIL_DecalTrace(&tr, DECAL_MOMMASPLAT); - } - else - { - tr.vecEndPos = pev->origin; - tr.vecPlaneNormal = -1 * pev->velocity.Normalize(); - } - // make some flecks - MortarSpray(tr.vecEndPos, tr.vecPlaneNormal, gSpitSprite, 24); - - entvars_t *pevOwner = NULL; - if (pev->owner) - pevOwner = VARS(pev->owner); - - RadiusDamage(pev->origin, pev, pevOwner, gSkillData.bigmommaDmgBlast, gSkillData.bigmommaRadiusBlast, CLASS_NONE, DMG_ACID); - UTIL_Remove(this); -} - -#endif diff --git a/dlls/Half-life/bloater.cpp b/dlls/Half-life/bloater.cpp deleted file mode 100644 index 35416307..00000000 --- a/dlls/Half-life/bloater.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// Bloater -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define BLOATER_AE_ATTACK_MELEE1 0x01 - -class CBloater : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - - void PainSound(void); - void AlertSound(void); - void IdleSound(void); - void AttackSnd(void); - - // No range attacks - BOOL CheckRangeAttack1(float flDot, float flDist) { return FALSE; } - BOOL CheckRangeAttack2(float flDot, float flDist) { return FALSE; } - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); -}; - -LINK_ENTITY_TO_CLASS(monster_bloater, CBloater); - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CBloater ::Classify(void) -{ - return CLASS_ALIEN_MONSTER; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CBloater ::SetYawSpeed(void) -{ - int ys; - - ys = 120; - -#if 0 - switch ( m_Activity ) - { - } -#endif - - pev->yaw_speed = ys; -} - -int CBloater ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - PainSound(); - return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -void CBloater ::PainSound(void) -{ -#if 0 - int pitch = 95 + RANDOM_LONG(0,9); - - switch (RANDOM_LONG(0,5)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_pain1.wav", 1.0, ATTN_NORM, 0, pitch); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_pain2.wav", 1.0, ATTN_NORM, 0, pitch); - break; - default: - break; - } -#endif -} - -void CBloater ::AlertSound(void) -{ -#if 0 - int pitch = 95 + RANDOM_LONG(0,9); - - switch (RANDOM_LONG(0,2)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_alert10.wav", 1.0, ATTN_NORM, 0, pitch); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_alert20.wav", 1.0, ATTN_NORM, 0, pitch); - break; - case 2: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_alert30.wav", 1.0, ATTN_NORM, 0, pitch); - break; - } -#endif -} - -void CBloater ::IdleSound(void) -{ -#if 0 - int pitch = 95 + RANDOM_LONG(0,9); - - switch (RANDOM_LONG(0,2)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_idle1.wav", 1.0, ATTN_NORM, 0, pitch); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_idle2.wav", 1.0, ATTN_NORM, 0, pitch); - break; - case 2: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_idle3.wav", 1.0, ATTN_NORM, 0, pitch); - break; - } -#endif -} - -void CBloater ::AttackSnd(void) -{ -#if 0 - int pitch = 95 + RANDOM_LONG(0,9); - - switch (RANDOM_LONG(0,1)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_attack1.wav", 1.0, ATTN_NORM, 0, pitch); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_attack2.wav", 1.0, ATTN_NORM, 0, pitch); - break; - } -#endif -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CBloater ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case BLOATER_AE_ATTACK_MELEE1: - { - // do stuff for this event. - AttackSnd(); - } - break; - - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CBloater ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/floater.mdl"); - UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_FLY; - pev->spawnflags |= FL_FLY; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->health = 40; - pev->view_ofs = VEC_VIEW; // position of the eyes relative to monster's origin. - m_flFieldOfView = 0.5; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CBloater ::Precache() -{ - PRECACHE_MODEL("models/floater.mdl"); -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= diff --git a/dlls/Half-life/bullsquid.cpp b/dlls/Half-life/bullsquid.cpp deleted file mode 100644 index f1522531..00000000 --- a/dlls/Half-life/bullsquid.cpp +++ /dev/null @@ -1,1251 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// bullsquid - big, spotty tentacle-mouthed meanie. -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" -#include "nodes.h" -#include "effects.h" -#include "decals.h" -#include "soundent.h" - -#define SQUID_SPRINT_DIST 256 // how close the squid has to get before starting to sprint and refusing to swerve - -int iSquidSpitSprite; - -//========================================================= -// monster-specific schedule types -//========================================================= -enum -{ - SCHED_SQUID_HURTHOP = LAST_COMMON_SCHEDULE + 1, - SCHED_SQUID_SMELLFOOD, - SCHED_SQUID_SEECRAB, - SCHED_SQUID_EAT, - SCHED_SQUID_SNIFF_AND_EAT, - SCHED_SQUID_WALLOW, -}; - -//========================================================= -// monster-specific tasks -//========================================================= -enum -{ - TASK_SQUID_HOPTURN = LAST_COMMON_TASK + 1, -}; - -//========================================================= -// Bullsquid's spit projectile -//========================================================= -class CSquidSpit : public CBaseEntity -{ -public: - void Spawn(void); - - static void Shoot(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity); - void Touch(CBaseEntity *pOther); - void EXPORT Animate(void); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - int m_maxFrame; -}; - -LINK_ENTITY_TO_CLASS(squidspit, CSquidSpit); - -TYPEDESCRIPTION CSquidSpit::m_SaveData[] = - { - DEFINE_FIELD(CSquidSpit, m_maxFrame, FIELD_INTEGER), -}; - -IMPLEMENT_SAVERESTORE(CSquidSpit, CBaseEntity); - -void CSquidSpit::Spawn(void) -{ - pev->movetype = MOVETYPE_FLY; - pev->classname = MAKE_STRING("squidspit"); - - pev->solid = SOLID_BBOX; - pev->rendermode = kRenderTransAlpha; - pev->renderamt = 255; - - SET_MODEL(ENT(pev), "sprites/bigspit.spr"); - pev->frame = 0; - pev->scale = 0.5; - - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); - - m_maxFrame = (float)MODEL_FRAMES(pev->modelindex) - 1; -} - -void CSquidSpit::Animate(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - if (pev->frame++) - { - if (pev->frame > m_maxFrame) - { - pev->frame = 0; - } - } -} - -void CSquidSpit::Shoot(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity) -{ - CSquidSpit *pSpit = GetClassPtr((CSquidSpit *)NULL); - pSpit->Spawn(); - - UTIL_SetOrigin(pSpit->pev, vecStart); - pSpit->pev->velocity = vecVelocity; - pSpit->pev->owner = ENT(pevOwner); - - pSpit->SetThink(Animate); - pSpit->pev->nextthink = gpGlobals->time + 0.1; -} - -void CSquidSpit ::Touch(CBaseEntity *pOther) -{ - TraceResult tr; - int iPitch; - - // splat sound - iPitch = RANDOM_FLOAT(90, 110); - - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "bullchicken/bc_acid1.wav", 1, ATTN_NORM, 0, iPitch); - - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "bullchicken/bc_spithit1.wav", 1, ATTN_NORM, 0, iPitch); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "bullchicken/bc_spithit2.wav", 1, ATTN_NORM, 0, iPitch); - break; - } - - if (!pOther->pev->takedamage) - { - - // make a splat on the wall - UTIL_TraceLine(pev->origin, pev->origin + pev->velocity * 10, dont_ignore_monsters, ENT(pev), &tr); - UTIL_DecalTrace(&tr, DECAL_SPIT1 + RANDOM_LONG(0, 1)); - - // make some flecks - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, tr.vecEndPos); - WRITE_BYTE(TE_SPRITE_SPRAY); - WRITE_COORD(tr.vecEndPos.x); // pos - WRITE_COORD(tr.vecEndPos.y); - WRITE_COORD(tr.vecEndPos.z); - WRITE_COORD(tr.vecPlaneNormal.x); // dir - WRITE_COORD(tr.vecPlaneNormal.y); - WRITE_COORD(tr.vecPlaneNormal.z); - WRITE_SHORT(iSquidSpitSprite); // model - WRITE_BYTE(5); // count - WRITE_BYTE(30); // speed - WRITE_BYTE(80); // noise ( client will divide by 100 ) - MESSAGE_END(); - } - else - { - pOther->TakeDamage(pev, pev, gSkillData.bullsquidDmgSpit, DMG_GENERIC); - } - - SetThink(SUB_Remove); - pev->nextthink = gpGlobals->time; -} - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define BSQUID_AE_SPIT (1) -#define BSQUID_AE_BITE (2) -#define BSQUID_AE_BLINK (3) -#define BSQUID_AE_TAILWHIP (4) -#define BSQUID_AE_HOP (5) -#define BSQUID_AE_THROW (6) - -class CBullsquid : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int ISoundMask(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - void IdleSound(void); - void PainSound(void); - void DeathSound(void); - void AlertSound(void); - void AttackSound(void); - void StartTask(Task_t *pTask); - void RunTask(Task_t *pTask); - BOOL CheckMeleeAttack1(float flDot, float flDist); - BOOL CheckMeleeAttack2(float flDot, float flDist); - BOOL CheckRangeAttack1(float flDot, float flDist); - void RunAI(void); - BOOL FValidateHintType(short sHint); - Schedule_t *GetSchedule(void); - Schedule_t *GetScheduleOfType(int Type); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - int IRelationship(CBaseEntity *pTarget); - int IgnoreConditions(void); - MONSTERSTATE GetIdealState(void); - - int Save(CSave &save); - int Restore(CRestore &restore); - - CUSTOM_SCHEDULES; - static TYPEDESCRIPTION m_SaveData[]; - - BOOL m_fCanThreatDisplay; // this is so the squid only does the "I see a headcrab!" dance one time. - - float m_flLastHurtTime; // we keep track of this, because if something hurts a squid, it will forget about its love of headcrabs for a while. - float m_flNextSpitTime; // last time the bullsquid used the spit attack. -}; -LINK_ENTITY_TO_CLASS(monster_bullchicken, CBullsquid); - -TYPEDESCRIPTION CBullsquid::m_SaveData[] = - { - DEFINE_FIELD(CBullsquid, m_fCanThreatDisplay, FIELD_BOOLEAN), - DEFINE_FIELD(CBullsquid, m_flLastHurtTime, FIELD_TIME), - DEFINE_FIELD(CBullsquid, m_flNextSpitTime, FIELD_TIME), -}; - -IMPLEMENT_SAVERESTORE(CBullsquid, CBaseMonster); - -//========================================================= -// IgnoreConditions -//========================================================= -int CBullsquid::IgnoreConditions(void) -{ - int iIgnore = CBaseMonster::IgnoreConditions(); - - if (gpGlobals->time - m_flLastHurtTime <= 20) - { - // haven't been hurt in 20 seconds, so let the squid care about stink. - iIgnore = bits_COND_SMELL | bits_COND_SMELL_FOOD; - } - - if (m_hEnemy != NULL) - { - if (FClassnameIs(m_hEnemy->pev, "monster_headcrab")) - { - // (Unless after a tasty headcrab) - iIgnore = bits_COND_SMELL | bits_COND_SMELL_FOOD; - } - } - - return iIgnore; -} - -//========================================================= -// IRelationship - overridden for bullsquid so that it can -// be made to ignore its love of headcrabs for a while. -//========================================================= -int CBullsquid::IRelationship(CBaseEntity *pTarget) -{ - if (gpGlobals->time - m_flLastHurtTime < 5 && FClassnameIs(pTarget->pev, "monster_headcrab")) - { - // if squid has been hurt in the last 5 seconds, and is getting relationship for a headcrab, - // tell squid to disregard crab. - return R_NO; - } - - return CBaseMonster ::IRelationship(pTarget); -} - -//========================================================= -// TakeDamage - overridden for bullsquid so we can keep track -// of how much time has passed since it was last injured -//========================================================= -int CBullsquid ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - float flDist; - Vector vecApex; - - // if the squid is running, has an enemy, was hurt by the enemy, hasn't been hurt in the last 3 seconds, and isn't too close to the enemy, - // it will swerve. (whew). - if (m_hEnemy != NULL && IsMoving() && pevAttacker == m_hEnemy->pev && gpGlobals->time - m_flLastHurtTime > 3) - { - flDist = (pev->origin - m_hEnemy->pev->origin).Length2D(); - - if (flDist > SQUID_SPRINT_DIST) - { - flDist = (pev->origin - m_Route[m_iRouteIndex].vecLocation).Length2D(); // reusing flDist. - - if (FTriangulate(pev->origin, m_Route[m_iRouteIndex].vecLocation, flDist * 0.5, m_hEnemy, &vecApex)) - { - InsertWaypoint(vecApex, bits_MF_TO_DETOUR | bits_MF_DONT_SIMPLIFY); - } - } - } - - if (!FClassnameIs(pevAttacker, "monster_headcrab")) - { - // don't forget about headcrabs if it was a headcrab that hurt the squid. - m_flLastHurtTime = gpGlobals->time; - } - - return CBaseMonster ::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -//========================================================= -// CheckRangeAttack1 -//========================================================= -BOOL CBullsquid ::CheckRangeAttack1(float flDot, float flDist) -{ - if (IsMoving() && flDist >= 512) - { - // squid will far too far behind if he stops running to spit at this distance from the enemy. - return FALSE; - } - - if (flDist > 64 && flDist <= 784 && flDot >= 0.5 && gpGlobals->time >= m_flNextSpitTime) - { - if (m_hEnemy != NULL) - { - if (fabs(pev->origin.z - m_hEnemy->pev->origin.z) > 256) - { - // don't try to spit at someone up really high or down really low. - return FALSE; - } - } - - if (IsMoving()) - { - // don't spit again for a long time, resume chasing enemy. - m_flNextSpitTime = gpGlobals->time + 5; - } - else - { - // not moving, so spit again pretty soon. - m_flNextSpitTime = gpGlobals->time + 0.5; - } - - return TRUE; - } - - return FALSE; -} - -//========================================================= -// CheckMeleeAttack1 - bullsquid is a big guy, so has a longer -// melee range than most monsters. This is the tailwhip attack -//========================================================= -BOOL CBullsquid ::CheckMeleeAttack1(float flDot, float flDist) -{ - if (m_hEnemy->pev->health <= gSkillData.bullsquidDmgWhip && flDist <= 85 && flDot >= 0.7) - { - return TRUE; - } - return FALSE; -} - -//========================================================= -// CheckMeleeAttack2 - bullsquid is a big guy, so has a longer -// melee range than most monsters. This is the bite attack. -// this attack will not be performed if the tailwhip attack -// is valid. -//========================================================= -BOOL CBullsquid ::CheckMeleeAttack2(float flDot, float flDist) -{ - if (flDist <= 85 && flDot >= 0.7 && !HasConditions(bits_COND_CAN_MELEE_ATTACK1)) // The player & bullsquid can be as much as their bboxes - { // apart (48 * sqrt(3)) and he can still attack (85 is a little more than 48*sqrt(3)) - return TRUE; - } - return FALSE; -} - -//========================================================= -// FValidateHintType -//========================================================= -BOOL CBullsquid ::FValidateHintType(short sHint) -{ - int i; - - static short sSquidHints[] = - { - HINT_WORLD_HUMAN_BLOOD, - }; - - for (i = 0; i < ARRAYSIZE(sSquidHints); i++) - { - if (sSquidHints[i] == sHint) - { - return TRUE; - } - } - - ALERT(at_aiconsole, "Couldn't validate hint type"); - return FALSE; -} - -//========================================================= -// ISoundMask - returns a bit mask indicating which types -// of sounds this monster regards. In the base class implementation, -// monsters care about all sounds, but no scents. -//========================================================= -int CBullsquid ::ISoundMask(void) -{ - return bits_SOUND_WORLD | - bits_SOUND_COMBAT | - bits_SOUND_CARCASS | - bits_SOUND_MEAT | - bits_SOUND_GARBAGE | - bits_SOUND_PLAYER; -} - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CBullsquid ::Classify(void) -{ - return CLASS_ALIEN_PREDATOR; -} - -//========================================================= -// IdleSound -//========================================================= -#define SQUID_ATTN_IDLE (float)1.5 -void CBullsquid ::IdleSound(void) -{ - switch (RANDOM_LONG(0, 4)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_idle1.wav", 1, SQUID_ATTN_IDLE); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_idle2.wav", 1, SQUID_ATTN_IDLE); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_idle3.wav", 1, SQUID_ATTN_IDLE); - break; - case 3: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_idle4.wav", 1, SQUID_ATTN_IDLE); - break; - case 4: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_idle5.wav", 1, SQUID_ATTN_IDLE); - break; - } -} - -//========================================================= -// PainSound -//========================================================= -void CBullsquid ::PainSound(void) -{ - int iPitch = RANDOM_LONG(85, 120); - - switch (RANDOM_LONG(0, 3)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "bullchicken/bc_pain1.wav", 1, ATTN_NORM, 0, iPitch); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "bullchicken/bc_pain2.wav", 1, ATTN_NORM, 0, iPitch); - break; - case 2: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "bullchicken/bc_pain3.wav", 1, ATTN_NORM, 0, iPitch); - break; - case 3: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "bullchicken/bc_pain4.wav", 1, ATTN_NORM, 0, iPitch); - break; - } -} - -//========================================================= -// AlertSound -//========================================================= -void CBullsquid ::AlertSound(void) -{ - int iPitch = RANDOM_LONG(140, 160); - - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "bullchicken/bc_idle1.wav", 1, ATTN_NORM, 0, iPitch); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "bullchicken/bc_idle2.wav", 1, ATTN_NORM, 0, iPitch); - break; - } -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CBullsquid ::SetYawSpeed(void) -{ - int ys; - - ys = 0; - - switch (m_Activity) - { - case ACT_WALK: - ys = 90; - break; - case ACT_RUN: - ys = 90; - break; - case ACT_IDLE: - ys = 90; - break; - case ACT_RANGE_ATTACK1: - ys = 90; - break; - default: - ys = 90; - break; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CBullsquid ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case BSQUID_AE_SPIT: - { - Vector vecSpitOffset; - Vector vecSpitDir; - - UTIL_MakeVectors(pev->angles); - - // !!!HACKHACK - the spot at which the spit originates (in front of the mouth) was measured in 3ds and hardcoded here. - // we should be able to read the position of bones at runtime for this info. - vecSpitOffset = (gpGlobals->v_right * 8 + gpGlobals->v_forward * 37 + gpGlobals->v_up * 23); - vecSpitOffset = (pev->origin + vecSpitOffset); - vecSpitDir = ((m_hEnemy->pev->origin + m_hEnemy->pev->view_ofs) - vecSpitOffset).Normalize(); - - vecSpitDir.x += RANDOM_FLOAT(-0.05, 0.05); - vecSpitDir.y += RANDOM_FLOAT(-0.05, 0.05); - vecSpitDir.z += RANDOM_FLOAT(-0.05, 0); - - // do stuff for this event. - AttackSound(); - - // spew the spittle temporary ents. - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSpitOffset); - WRITE_BYTE(TE_SPRITE_SPRAY); - WRITE_COORD(vecSpitOffset.x); // pos - WRITE_COORD(vecSpitOffset.y); - WRITE_COORD(vecSpitOffset.z); - WRITE_COORD(vecSpitDir.x); // dir - WRITE_COORD(vecSpitDir.y); - WRITE_COORD(vecSpitDir.z); - WRITE_SHORT(iSquidSpitSprite); // model - WRITE_BYTE(15); // count - WRITE_BYTE(210); // speed - WRITE_BYTE(25); // noise ( client will divide by 100 ) - MESSAGE_END(); - - CSquidSpit::Shoot(pev, vecSpitOffset, vecSpitDir * 900); - } - break; - - case BSQUID_AE_BITE: - { - // SOUND HERE! - CBaseEntity *pHurt = CheckTraceHullAttack(70, gSkillData.bullsquidDmgBite, DMG_SLASH); - - if (pHurt) - { - //pHurt->pev->punchangle.z = -15; - //pHurt->pev->punchangle.x = -45; - pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_forward * 100; - pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_up * 100; - } - } - break; - - case BSQUID_AE_TAILWHIP: - { - CBaseEntity *pHurt = CheckTraceHullAttack(70, gSkillData.bullsquidDmgWhip, DMG_CLUB | DMG_ALWAYSGIB); - if (pHurt) - { - pHurt->pev->punchangle.z = -20; - pHurt->pev->punchangle.x = 20; - pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_right * 200; - pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_up * 100; - } - } - break; - - case BSQUID_AE_BLINK: - { - // close eye. - pev->skin = 1; - } - break; - - case BSQUID_AE_HOP: - { - float flGravity = CVAR_GET_FLOAT("sv_gravity"); - - // throw the squid up into the air on this frame. - if (FBitSet(pev->flags, FL_ONGROUND)) - { - pev->flags -= FL_ONGROUND; - } - - // jump into air for 0.8 (24/30) seconds - // pev->velocity.z += (0.875 * flGravity) * 0.5; - pev->velocity.z += (0.625 * flGravity) * 0.5; - } - break; - - case BSQUID_AE_THROW: - { - int iPitch; - - // squid throws its prey IF the prey is a client. - CBaseEntity *pHurt = CheckTraceHullAttack(70, 0, 0); - - if (pHurt) - { - // croonchy bite sound - iPitch = RANDOM_FLOAT(90, 110); - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "bullchicken/bc_bite2.wav", 1, ATTN_NORM, 0, iPitch); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "bullchicken/bc_bite3.wav", 1, ATTN_NORM, 0, iPitch); - break; - } - - //pHurt->pev->punchangle.x = RANDOM_LONG(0,34) - 5; - //pHurt->pev->punchangle.z = RANDOM_LONG(0,49) - 25; - //pHurt->pev->punchangle.y = RANDOM_LONG(0,89) - 45; - - // screeshake transforms the viewmodel as well as the viewangle. No problems with seeing the ends of the viewmodels. - UTIL_ScreenShake(pHurt->pev->origin, 25.0, 1.5, 0.7, 2); - - if (pHurt->IsPlayer()) - { - UTIL_MakeVectors(pev->angles); - pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * 300 + gpGlobals->v_up * 300; - } - } - } - break; - - default: - CBaseMonster::HandleAnimEvent(pEvent); - } -} - -//========================================================= -// Spawn -//========================================================= -void CBullsquid ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/bullsquid.mdl"); - UTIL_SetSize(pev, Vector(-32, -32, 0), Vector(32, 32, 64)); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->effects = 0; - pev->health = gSkillData.bullsquidHealth; - m_flFieldOfView = 0.2; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - - m_fCanThreatDisplay = TRUE; - m_flNextSpitTime = gpGlobals->time; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CBullsquid ::Precache() -{ - PRECACHE_MODEL("models/bullsquid.mdl"); - - PRECACHE_MODEL("sprites/bigspit.spr"); // spit projectile. - - iSquidSpitSprite = PRECACHE_MODEL("sprites/tinyspit.spr"); // client side spittle. - - PRECACHE_SOUND("zombie/claw_miss2.wav"); // because we use the basemonster SWIPE animation event - - PRECACHE_SOUND("bullchicken/bc_attack2.wav"); - PRECACHE_SOUND("bullchicken/bc_attack3.wav"); - - PRECACHE_SOUND("bullchicken/bc_die1.wav"); - PRECACHE_SOUND("bullchicken/bc_die2.wav"); - PRECACHE_SOUND("bullchicken/bc_die3.wav"); - - PRECACHE_SOUND("bullchicken/bc_idle1.wav"); - PRECACHE_SOUND("bullchicken/bc_idle2.wav"); - PRECACHE_SOUND("bullchicken/bc_idle3.wav"); - PRECACHE_SOUND("bullchicken/bc_idle4.wav"); - PRECACHE_SOUND("bullchicken/bc_idle5.wav"); - - PRECACHE_SOUND("bullchicken/bc_pain1.wav"); - PRECACHE_SOUND("bullchicken/bc_pain2.wav"); - PRECACHE_SOUND("bullchicken/bc_pain3.wav"); - PRECACHE_SOUND("bullchicken/bc_pain4.wav"); - - PRECACHE_SOUND("bullchicken/bc_attackgrowl.wav"); - PRECACHE_SOUND("bullchicken/bc_attackgrowl2.wav"); - PRECACHE_SOUND("bullchicken/bc_attackgrowl3.wav"); - - PRECACHE_SOUND("bullchicken/bc_acid1.wav"); - - PRECACHE_SOUND("bullchicken/bc_bite2.wav"); - PRECACHE_SOUND("bullchicken/bc_bite3.wav"); - - PRECACHE_SOUND("bullchicken/bc_spithit1.wav"); - PRECACHE_SOUND("bullchicken/bc_spithit2.wav"); -} - -//========================================================= -// DeathSound -//========================================================= -void CBullsquid ::DeathSound(void) -{ - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_die1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_die2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_die3.wav", 1, ATTN_NORM); - break; - } -} - -//========================================================= -// AttackSound -//========================================================= -void CBullsquid ::AttackSound(void) -{ - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "bullchicken/bc_attack2.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "bullchicken/bc_attack3.wav", 1, ATTN_NORM); - break; - } -} - -//======================================================== -// RunAI - overridden for bullsquid because there are things -// that need to be checked every think. -//======================================================== -void CBullsquid ::RunAI(void) -{ - // first, do base class stuff - CBaseMonster ::RunAI(); - - if (pev->skin != 0) - { - // close eye if it was open. - pev->skin = 0; - } - - if (RANDOM_LONG(0, 39) == 0) - { - pev->skin = 1; - } - - if (m_hEnemy != NULL && m_Activity == ACT_RUN) - { - // chasing enemy. Sprint for last bit - if ((pev->origin - m_hEnemy->pev->origin).Length2D() < SQUID_SPRINT_DIST) - { - pev->framerate = 1.25; - } - } -} - -//======================================================== -// AI Schedules Specific to this monster -//========================================================= - -// primary range attack -Task_t tlSquidRangeAttack1[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, -}; - -Schedule_t slSquidRangeAttack1[] = - { - {tlSquidRangeAttack1, - ARRAYSIZE(tlSquidRangeAttack1), - bits_COND_NEW_ENEMY | - bits_COND_ENEMY_DEAD | - bits_COND_HEAVY_DAMAGE | - bits_COND_ENEMY_OCCLUDED | - bits_COND_NO_AMMO_LOADED, - 0, - "Squid Range Attack1"}, -}; - -// Chase enemy schedule -Task_t tlSquidChaseEnemy1[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_RANGE_ATTACK1}, // !!!OEM - this will stop nasty squid oscillation. - {TASK_GET_PATH_TO_ENEMY, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, -}; - -Schedule_t slSquidChaseEnemy[] = - { - {tlSquidChaseEnemy1, - ARRAYSIZE(tlSquidChaseEnemy1), - bits_COND_NEW_ENEMY | - bits_COND_ENEMY_DEAD | - bits_COND_SMELL_FOOD | - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_MELEE_ATTACK1 | - bits_COND_CAN_MELEE_ATTACK2 | - bits_COND_TASK_FAILED | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER | - bits_SOUND_MEAT, - "Squid Chase Enemy"}, -}; - -Task_t tlSquidHurtHop[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_SOUND_WAKE, (float)0}, - {TASK_SQUID_HOPTURN, (float)0}, - {TASK_FACE_ENEMY, (float)0}, // in case squid didn't turn all the way in the air. -}; - -Schedule_t slSquidHurtHop[] = - { - {tlSquidHurtHop, - ARRAYSIZE(tlSquidHurtHop), - 0, - 0, - "SquidHurtHop"}}; - -Task_t tlSquidSeeCrab[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_SOUND_WAKE, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_EXCITED}, - {TASK_FACE_ENEMY, (float)0}, -}; - -Schedule_t slSquidSeeCrab[] = - { - {tlSquidSeeCrab, - ARRAYSIZE(tlSquidSeeCrab), - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "SquidSeeCrab"}}; - -// squid walks to something tasty and eats it. -Task_t tlSquidEat[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_EAT, (float)10}, // this is in case the squid can't get to the food - {TASK_STORE_LASTPOSITION, (float)0}, - {TASK_GET_PATH_TO_BESTSCENT, (float)0}, - {TASK_WALK_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_EAT}, - {TASK_PLAY_SEQUENCE, (float)ACT_EAT}, - {TASK_PLAY_SEQUENCE, (float)ACT_EAT}, - {TASK_EAT, (float)50}, - {TASK_GET_PATH_TO_LASTPOSITION, (float)0}, - {TASK_WALK_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_CLEAR_LASTPOSITION, (float)0}, -}; - -Schedule_t slSquidEat[] = - { - {tlSquidEat, - ARRAYSIZE(tlSquidEat), - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_NEW_ENEMY, - - // even though HEAR_SOUND/SMELL FOOD doesn't break this schedule, we need this mask - // here or the monster won't detect these sounds at ALL while running this schedule. - bits_SOUND_MEAT | - bits_SOUND_CARCASS, - "SquidEat"}}; - -// this is a bit different than just Eat. We use this schedule when the food is far away, occluded, or behind -// the squid. This schedule plays a sniff animation before going to the source of food. -Task_t tlSquidSniffAndEat[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_EAT, (float)10}, // this is in case the squid can't get to the food - {TASK_PLAY_SEQUENCE, (float)ACT_DETECT_SCENT}, - {TASK_STORE_LASTPOSITION, (float)0}, - {TASK_GET_PATH_TO_BESTSCENT, (float)0}, - {TASK_WALK_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_EAT}, - {TASK_PLAY_SEQUENCE, (float)ACT_EAT}, - {TASK_PLAY_SEQUENCE, (float)ACT_EAT}, - {TASK_EAT, (float)50}, - {TASK_GET_PATH_TO_LASTPOSITION, (float)0}, - {TASK_WALK_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_CLEAR_LASTPOSITION, (float)0}, -}; - -Schedule_t slSquidSniffAndEat[] = - { - {tlSquidSniffAndEat, - ARRAYSIZE(tlSquidSniffAndEat), - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_NEW_ENEMY, - - // even though HEAR_SOUND/SMELL FOOD doesn't break this schedule, we need this mask - // here or the monster won't detect these sounds at ALL while running this schedule. - bits_SOUND_MEAT | - bits_SOUND_CARCASS, - "SquidSniffAndEat"}}; - -// squid does this to stinky things. -Task_t tlSquidWallow[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_EAT, (float)10}, // this is in case the squid can't get to the stinkiness - {TASK_STORE_LASTPOSITION, (float)0}, - {TASK_GET_PATH_TO_BESTSCENT, (float)0}, - {TASK_WALK_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_INSPECT_FLOOR}, - {TASK_EAT, (float)50}, // keeps squid from eating or sniffing anything else for a while. - {TASK_GET_PATH_TO_LASTPOSITION, (float)0}, - {TASK_WALK_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_CLEAR_LASTPOSITION, (float)0}, -}; - -Schedule_t slSquidWallow[] = - { - {tlSquidWallow, - ARRAYSIZE(tlSquidWallow), - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_NEW_ENEMY, - - // even though HEAR_SOUND/SMELL FOOD doesn't break this schedule, we need this mask - // here or the monster won't detect these sounds at ALL while running this schedule. - bits_SOUND_GARBAGE, - - "SquidWallow"}}; - -DEFINE_CUSTOM_SCHEDULES(CBullsquid){ - slSquidRangeAttack1, - slSquidChaseEnemy, - slSquidHurtHop, - slSquidSeeCrab, - slSquidEat, - slSquidSniffAndEat, - slSquidWallow}; - -IMPLEMENT_CUSTOM_SCHEDULES(CBullsquid, CBaseMonster); - -//========================================================= -// GetSchedule -//========================================================= -Schedule_t *CBullsquid ::GetSchedule(void) -{ - switch (m_MonsterState) - { - case MONSTERSTATE_ALERT: - { - if (HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE)) - { - return GetScheduleOfType(SCHED_SQUID_HURTHOP); - } - - if (HasConditions(bits_COND_SMELL_FOOD)) - { - CSound *pSound; - - pSound = PBestScent(); - - if (pSound && (!FInViewCone(&pSound->m_vecOrigin) || !FVisible(pSound->m_vecOrigin))) - { - // scent is behind or occluded - return GetScheduleOfType(SCHED_SQUID_SNIFF_AND_EAT); - } - - // food is right out in the open. Just go get it. - return GetScheduleOfType(SCHED_SQUID_EAT); - } - - if (HasConditions(bits_COND_SMELL)) - { - // there's something stinky. - CSound *pSound; - - pSound = PBestScent(); - if (pSound) - return GetScheduleOfType(SCHED_SQUID_WALLOW); - } - - break; - } - case MONSTERSTATE_COMBAT: - { - // dead enemy - if (HasConditions(bits_COND_ENEMY_DEAD)) - { - // call base class, all code to handle dead enemies is centralized there. - return CBaseMonster ::GetSchedule(); - } - - if (HasConditions(bits_COND_NEW_ENEMY)) - { - if (m_fCanThreatDisplay && IRelationship(m_hEnemy) == R_HT) - { - // this means squid sees a headcrab! - m_fCanThreatDisplay = FALSE; // only do the headcrab dance once per lifetime. - return GetScheduleOfType(SCHED_SQUID_SEECRAB); - } - else - { - return GetScheduleOfType(SCHED_WAKE_ANGRY); - } - } - - if (HasConditions(bits_COND_SMELL_FOOD)) - { - CSound *pSound; - - pSound = PBestScent(); - - if (pSound && (!FInViewCone(&pSound->m_vecOrigin) || !FVisible(pSound->m_vecOrigin))) - { - // scent is behind or occluded - return GetScheduleOfType(SCHED_SQUID_SNIFF_AND_EAT); - } - - // food is right out in the open. Just go get it. - return GetScheduleOfType(SCHED_SQUID_EAT); - } - - if (HasConditions(bits_COND_CAN_RANGE_ATTACK1)) - { - return GetScheduleOfType(SCHED_RANGE_ATTACK1); - } - - if (HasConditions(bits_COND_CAN_MELEE_ATTACK1)) - { - return GetScheduleOfType(SCHED_MELEE_ATTACK1); - } - - if (HasConditions(bits_COND_CAN_MELEE_ATTACK2)) - { - return GetScheduleOfType(SCHED_MELEE_ATTACK2); - } - - return GetScheduleOfType(SCHED_CHASE_ENEMY); - - break; - } - } - - return CBaseMonster ::GetSchedule(); -} - -//========================================================= -// GetScheduleOfType -//========================================================= -Schedule_t *CBullsquid ::GetScheduleOfType(int Type) -{ - switch (Type) - { - case SCHED_RANGE_ATTACK1: - return &slSquidRangeAttack1[0]; - break; - case SCHED_SQUID_HURTHOP: - return &slSquidHurtHop[0]; - break; - case SCHED_SQUID_SEECRAB: - return &slSquidSeeCrab[0]; - break; - case SCHED_SQUID_EAT: - return &slSquidEat[0]; - break; - case SCHED_SQUID_SNIFF_AND_EAT: - return &slSquidSniffAndEat[0]; - break; - case SCHED_SQUID_WALLOW: - return &slSquidWallow[0]; - break; - case SCHED_CHASE_ENEMY: - return &slSquidChaseEnemy[0]; - break; - } - - return CBaseMonster ::GetScheduleOfType(Type); -} - -//========================================================= -// Start task - selects the correct activity and performs -// any necessary calculations to start the next task on the -// schedule. OVERRIDDEN for bullsquid because it needs to -// know explicitly when the last attempt to chase the enemy -// failed, since that impacts its attack choices. -//========================================================= -void CBullsquid ::StartTask(Task_t *pTask) -{ - m_iTaskStatus = TASKSTATUS_RUNNING; - - switch (pTask->iTask) - { - case TASK_MELEE_ATTACK2: - { - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_attackgrowl.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_attackgrowl2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "bullchicken/bc_attackgrowl3.wav", 1, ATTN_NORM); - break; - } - - CBaseMonster ::StartTask(pTask); - break; - } - case TASK_SQUID_HOPTURN: - { - SetActivity(ACT_HOP); - MakeIdealYaw(m_vecEnemyLKP); - break; - } - case TASK_GET_PATH_TO_ENEMY: - { - if (BuildRoute(m_hEnemy->pev->origin, bits_MF_TO_ENEMY, m_hEnemy)) - { - m_iTaskStatus = TASKSTATUS_COMPLETE; - } - else - { - ALERT(at_aiconsole, "GetPathToEnemy failed!!\n"); - TaskFail(); - } - break; - } - default: - { - CBaseMonster ::StartTask(pTask); - break; - } - } -} - -//========================================================= -// RunTask -//========================================================= -void CBullsquid ::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_SQUID_HOPTURN: - { - MakeIdealYaw(m_vecEnemyLKP); - ChangeYaw(pev->yaw_speed); - - if (m_fSequenceFinished) - { - m_iTaskStatus = TASKSTATUS_COMPLETE; - } - break; - } - default: - { - CBaseMonster ::RunTask(pTask); - break; - } - } -} - -//========================================================= -// GetIdealState - Overridden for Bullsquid to deal with -// the feature that makes it lose interest in headcrabs for -// a while if something injures it. -//========================================================= -MONSTERSTATE CBullsquid ::GetIdealState(void) -{ - int iConditions; - - iConditions = IScheduleFlags(); - - // If no schedule conditions, the new ideal state is probably the reason we're in here. - switch (m_MonsterState) - { - case MONSTERSTATE_COMBAT: - /* - COMBAT goes to ALERT upon death of enemy - */ - { - if (m_hEnemy != NULL && (iConditions & bits_COND_LIGHT_DAMAGE || iConditions & bits_COND_HEAVY_DAMAGE) && FClassnameIs(m_hEnemy->pev, "monster_headcrab")) - { - // if the squid has a headcrab enemy and something hurts it, it's going to forget about the crab for a while. - m_hEnemy = NULL; - m_IdealMonsterState = MONSTERSTATE_ALERT; - } - break; - } - } - - m_IdealMonsterState = CBaseMonster ::GetIdealState(); - - return m_IdealMonsterState; -} diff --git a/dlls/Half-life/controller.cpp b/dlls/Half-life/controller.cpp deleted file mode 100644 index d2a55687..00000000 --- a/dlls/Half-life/controller.cpp +++ /dev/null @@ -1,1357 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -//========================================================= -// CONTROLLER -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "effects.h" -#include "schedule.h" -#include "weapons.h" -#include "squadmonster.h" - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define CONTROLLER_AE_HEAD_OPEN 1 -#define CONTROLLER_AE_BALL_SHOOT 2 -#define CONTROLLER_AE_SMALL_SHOOT 3 -#define CONTROLLER_AE_POWERUP_FULL 4 -#define CONTROLLER_AE_POWERUP_HALF 5 - -#define CONTROLLER_FLINCH_DELAY 2 // at most one flinch every n secs - -class CController : public CSquadMonster -{ -public: - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - - void RunAI(void); - BOOL CheckRangeAttack1(float flDot, float flDist); // balls - BOOL CheckRangeAttack2(float flDot, float flDist); // head - BOOL CheckMeleeAttack1(float flDot, float flDist); // block, throw - Schedule_t *GetSchedule(void); - Schedule_t *GetScheduleOfType(int Type); - void StartTask(Task_t *pTask); - void RunTask(Task_t *pTask); - CUSTOM_SCHEDULES; - - void Stop(void); - void Move(float flInterval); - int CheckLocalMove(const Vector &vecStart, const Vector &vecEnd, CBaseEntity *pTarget, float *pflDist); - void MoveExecute(CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval); - void SetActivity(Activity NewActivity); - BOOL ShouldAdvanceRoute(float flWaypointDist); - int LookupFloat(); - - float m_flNextFlinch; - - float m_flShootTime; - float m_flShootEnd; - - void PainSound(void); - void AlertSound(void); - void IdleSound(void); - void AttackSound(void); - void DeathSound(void); - - static const char *pAttackSounds[]; - static const char *pIdleSounds[]; - static const char *pAlertSounds[]; - static const char *pPainSounds[]; - static const char *pDeathSounds[]; - - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - void Killed(entvars_t *pevAttacker, int iGib); - void GibMonster(void); - - CSprite *m_pBall[2]; // hand balls - int m_iBall[2]; // how bright it should be - float m_iBallTime[2]; // when it should be that color - int m_iBallCurrent[2]; // current brightness - - Vector m_vecEstVelocity; - - Vector m_velocity; - int m_fInCombat; -}; - -LINK_ENTITY_TO_CLASS(monster_alien_controller, CController); - -TYPEDESCRIPTION CController::m_SaveData[] = - { - DEFINE_ARRAY(CController, m_pBall, FIELD_CLASSPTR, 2), - DEFINE_ARRAY(CController, m_iBall, FIELD_INTEGER, 2), - DEFINE_ARRAY(CController, m_iBallTime, FIELD_TIME, 2), - DEFINE_ARRAY(CController, m_iBallCurrent, FIELD_INTEGER, 2), - DEFINE_FIELD(CController, m_vecEstVelocity, FIELD_VECTOR), -}; -IMPLEMENT_SAVERESTORE(CController, CSquadMonster); - -const char *CController::pAttackSounds[] = - { - "controller/con_attack1.wav", - "controller/con_attack2.wav", - "controller/con_attack3.wav", -}; - -const char *CController::pIdleSounds[] = - { - "controller/con_idle1.wav", - "controller/con_idle2.wav", - "controller/con_idle3.wav", - "controller/con_idle4.wav", - "controller/con_idle5.wav", -}; - -const char *CController::pAlertSounds[] = - { - "controller/con_alert1.wav", - "controller/con_alert2.wav", - "controller/con_alert3.wav", -}; - -const char *CController::pPainSounds[] = - { - "controller/con_pain1.wav", - "controller/con_pain2.wav", - "controller/con_pain3.wav", -}; - -const char *CController::pDeathSounds[] = - { - "controller/con_die1.wav", - "controller/con_die2.wav", -}; - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CController ::Classify(void) -{ - return CLASS_ALIEN_MILITARY; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CController ::SetYawSpeed(void) -{ - int ys; - - ys = 120; - -#if 0 - switch ( m_Activity ) - { - } -#endif - - pev->yaw_speed = ys; -} - -int CController ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - // HACK HACK -- until we fix this. - if (IsAlive()) - PainSound(); - return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -void CController::Killed(entvars_t *pevAttacker, int iGib) -{ - // shut off balls - /* - m_iBall[0] = 0; - m_iBallTime[0] = gpGlobals->time + 4.0; - m_iBall[1] = 0; - m_iBallTime[1] = gpGlobals->time + 4.0; - */ - - // fade balls - if (m_pBall[0]) - { - m_pBall[0]->SUB_StartFadeOut(); - m_pBall[0] = NULL; - } - if (m_pBall[1]) - { - m_pBall[1]->SUB_StartFadeOut(); - m_pBall[1] = NULL; - } - - CSquadMonster::Killed(pevAttacker, iGib); -} - -void CController::GibMonster(void) -{ - // delete balls - if (m_pBall[0]) - { - UTIL_Remove(m_pBall[0]); - m_pBall[0] = NULL; - } - if (m_pBall[1]) - { - UTIL_Remove(m_pBall[1]); - m_pBall[1] = NULL; - } - CSquadMonster::GibMonster(); -} - -void CController ::PainSound(void) -{ - if (RANDOM_LONG(0, 5) < 2) - EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pPainSounds); -} - -void CController ::AlertSound(void) -{ - EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pAlertSounds); -} - -void CController ::IdleSound(void) -{ - EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pIdleSounds); -} - -void CController ::AttackSound(void) -{ - EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pAttackSounds); -} - -void CController ::DeathSound(void) -{ - EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pDeathSounds); -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CController ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case CONTROLLER_AE_HEAD_OPEN: - { - Vector vecStart, angleGun; - - GetAttachment(0, vecStart, angleGun); - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex() + 0x1000); // entity, attachment - WRITE_COORD(vecStart.x); // origin - WRITE_COORD(vecStart.y); - WRITE_COORD(vecStart.z); - WRITE_COORD(1); // radius - WRITE_BYTE(255); // R - WRITE_BYTE(192); // G - WRITE_BYTE(64); // B - WRITE_BYTE(20); // life * 10 - WRITE_COORD(-32); // decay - MESSAGE_END(); - - m_iBall[0] = 192; - m_iBallTime[0] = gpGlobals->time + atoi(pEvent->options) / 15.0; - m_iBall[1] = 255; - m_iBallTime[1] = gpGlobals->time + atoi(pEvent->options) / 15.0; - } - break; - - case CONTROLLER_AE_BALL_SHOOT: - { - Vector vecStart, angleGun; - - GetAttachment(0, vecStart, angleGun); - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex() + 0x1000); // entity, attachment - WRITE_COORD(0); // origin - WRITE_COORD(0); - WRITE_COORD(0); - WRITE_COORD(32); // radius - WRITE_BYTE(255); // R - WRITE_BYTE(192); // G - WRITE_BYTE(64); // B - WRITE_BYTE(10); // life * 10 - WRITE_COORD(32); // decay - MESSAGE_END(); - - CBaseMonster *pBall = (CBaseMonster *)Create("controller_head_ball", vecStart, pev->angles, edict()); - - pBall->pev->velocity = Vector(0, 0, 32); - pBall->m_hEnemy = m_hEnemy; - - m_iBall[0] = 0; - m_iBall[1] = 0; - } - break; - - case CONTROLLER_AE_SMALL_SHOOT: - { - AttackSound(); - m_flShootTime = gpGlobals->time; - m_flShootEnd = m_flShootTime + atoi(pEvent->options) / 15.0; - } - break; - case CONTROLLER_AE_POWERUP_FULL: - { - m_iBall[0] = 255; - m_iBallTime[0] = gpGlobals->time + atoi(pEvent->options) / 15.0; - m_iBall[1] = 255; - m_iBallTime[1] = gpGlobals->time + atoi(pEvent->options) / 15.0; - } - break; - case CONTROLLER_AE_POWERUP_HALF: - { - m_iBall[0] = 192; - m_iBallTime[0] = gpGlobals->time + atoi(pEvent->options) / 15.0; - m_iBall[1] = 192; - m_iBallTime[1] = gpGlobals->time + atoi(pEvent->options) / 15.0; - } - break; - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CController ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/controller.mdl"); - UTIL_SetSize(pev, Vector(-32, -32, 0), Vector(32, 32, 64)); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_FLY; - pev->flags |= FL_FLY; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->health = gSkillData.controllerHealth; - pev->view_ofs = Vector(0, 0, -2); // position of the eyes relative to monster's origin. - m_flFieldOfView = VIEW_FIELD_FULL; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CController ::Precache() -{ - PRECACHE_MODEL("models/controller.mdl"); - - PRECACHE_SOUND_ARRAY(pAttackSounds); - PRECACHE_SOUND_ARRAY(pIdleSounds); - PRECACHE_SOUND_ARRAY(pAlertSounds); - PRECACHE_SOUND_ARRAY(pPainSounds); - PRECACHE_SOUND_ARRAY(pDeathSounds); - - PRECACHE_MODEL("sprites/xspark4.spr"); - - UTIL_PrecacheOther("controller_energy_ball"); - UTIL_PrecacheOther("controller_head_ball"); -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - -// Chase enemy schedule -Task_t tlControllerChaseEnemy[] = - { - {TASK_GET_PATH_TO_ENEMY, (float)128}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - -}; - -Schedule_t slControllerChaseEnemy[] = - { - {tlControllerChaseEnemy, - ARRAYSIZE(tlControllerChaseEnemy), - bits_COND_NEW_ENEMY | - bits_COND_TASK_FAILED, - 0, - "ControllerChaseEnemy"}, -}; - -Task_t tlControllerStrafe[] = - { - {TASK_WAIT, (float)0.2}, - {TASK_GET_PATH_TO_ENEMY, (float)128}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_WAIT, (float)1}, -}; - -Schedule_t slControllerStrafe[] = - { - {tlControllerStrafe, - ARRAYSIZE(tlControllerStrafe), - bits_COND_NEW_ENEMY, - 0, - "ControllerStrafe"}, -}; - -Task_t tlControllerTakeCover[] = - { - {TASK_WAIT, (float)0.2}, - {TASK_FIND_COVER_FROM_ENEMY, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_WAIT, (float)1}, -}; - -Schedule_t slControllerTakeCover[] = - { - {tlControllerTakeCover, - ARRAYSIZE(tlControllerTakeCover), - bits_COND_NEW_ENEMY, - 0, - "ControllerTakeCover"}, -}; - -Task_t tlControllerFail[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_WAIT, (float)2}, - {TASK_WAIT_PVS, (float)0}, -}; - -Schedule_t slControllerFail[] = - { - {tlControllerFail, - ARRAYSIZE(tlControllerFail), - 0, - 0, - "ControllerFail"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CController){ - slControllerChaseEnemy, - slControllerStrafe, - slControllerTakeCover, - slControllerFail, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CController, CSquadMonster); - -//========================================================= -// StartTask -//========================================================= -void CController ::StartTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_RANGE_ATTACK1: - CSquadMonster ::StartTask(pTask); - break; - case TASK_GET_PATH_TO_ENEMY_LKP: - { - if (BuildNearestRoute(m_vecEnemyLKP, pev->view_ofs, pTask->flData, (m_vecEnemyLKP - pev->origin).Length() + 1024)) - { - TaskComplete(); - } - else - { - // no way to get there =( - ALERT(at_aiconsole, "GetPathToEnemyLKP failed!!\n"); - TaskFail(); - } - break; - } - case TASK_GET_PATH_TO_ENEMY: - { - CBaseEntity *pEnemy = m_hEnemy; - - if (pEnemy == NULL) - { - TaskFail(); - return; - } - - if (BuildNearestRoute(pEnemy->pev->origin, pEnemy->pev->view_ofs, pTask->flData, (pEnemy->pev->origin - pev->origin).Length() + 1024)) - { - TaskComplete(); - } - else - { - // no way to get there =( - ALERT(at_aiconsole, "GetPathToEnemy failed!!\n"); - TaskFail(); - } - break; - } - default: - CSquadMonster ::StartTask(pTask); - break; - } -} - -Vector Intersect(Vector vecSrc, Vector vecDst, Vector vecMove, float flSpeed) -{ - Vector vecTo = vecDst - vecSrc; - - float a = DotProduct(vecMove, vecMove) - flSpeed * flSpeed; - float b = 0 * DotProduct(vecTo, vecMove); // why does this work? - float c = DotProduct(vecTo, vecTo); - - float t; - if (a == 0) - { - t = c / (flSpeed * flSpeed); - } - else - { - t = b * b - 4 * a * c; - t = sqrt(t) / (2.0 * a); - float t1 = -b + t; - float t2 = -b - t; - - if (t1 < 0 || t2 < t1) - t = t2; - else - t = t1; - } - - // ALERT( at_console, "Intersect %f\n", t ); - - if (t < 0.1) - t = 0.1; - if (t > 10.0) - t = 10.0; - - Vector vecHit = vecTo + vecMove * t; - return vecHit.Normalize() * flSpeed; -} - -int CController::LookupFloat() -{ - if (m_velocity.Length() < 32.0) - { - return LookupSequence("up"); - } - - UTIL_MakeAimVectors(pev->angles); - float x = DotProduct(gpGlobals->v_forward, m_velocity); - float y = DotProduct(gpGlobals->v_right, m_velocity); - float z = DotProduct(gpGlobals->v_up, m_velocity); - - if (fabs(x) > fabs(y) && fabs(x) > fabs(z)) - { - if (x > 0) - return LookupSequence("forward"); - else - return LookupSequence("backward"); - } - else if (fabs(y) > fabs(z)) - { - if (y > 0) - return LookupSequence("right"); - else - return LookupSequence("left"); - } - else - { - if (z > 0) - return LookupSequence("up"); - else - return LookupSequence("down"); - } -} - -//========================================================= -// RunTask -//========================================================= -void CController ::RunTask(Task_t *pTask) -{ - - if (m_flShootEnd > gpGlobals->time) - { - Vector vecHand, vecAngle; - - GetAttachment(2, vecHand, vecAngle); - - while (m_flShootTime < m_flShootEnd && m_flShootTime < gpGlobals->time) - { - Vector vecSrc = vecHand + pev->velocity * (m_flShootTime - gpGlobals->time); - Vector vecDir; - - if (m_hEnemy != NULL) - { - if (HasConditions(bits_COND_SEE_ENEMY)) - { - m_vecEstVelocity = m_vecEstVelocity * 0.5 + m_hEnemy->pev->velocity * 0.5; - } - else - { - m_vecEstVelocity = m_vecEstVelocity * 0.8; - } - vecDir = Intersect(vecSrc, m_hEnemy->BodyTarget(pev->origin), m_vecEstVelocity, gSkillData.controllerSpeedBall); - float delta = 0.03490; // +-2 degree - vecDir = vecDir + Vector(RANDOM_FLOAT(-delta, delta), RANDOM_FLOAT(-delta, delta), RANDOM_FLOAT(-delta, delta)) * gSkillData.controllerSpeedBall; - - vecSrc = vecSrc + vecDir * (gpGlobals->time - m_flShootTime); - CBaseMonster *pBall = (CBaseMonster *)Create("controller_energy_ball", vecSrc, pev->angles, edict()); - pBall->pev->velocity = vecDir; - } - m_flShootTime += 0.2; - } - - if (m_flShootTime > m_flShootEnd) - { - m_iBall[0] = 64; - m_iBallTime[0] = m_flShootEnd; - m_iBall[1] = 64; - m_iBallTime[1] = m_flShootEnd; - m_fInCombat = FALSE; - } - } - - switch (pTask->iTask) - { - case TASK_WAIT_FOR_MOVEMENT: - case TASK_WAIT: - case TASK_WAIT_FACE_ENEMY: - case TASK_WAIT_PVS: - MakeIdealYaw(m_vecEnemyLKP); - ChangeYaw(pev->yaw_speed); - - if (m_fSequenceFinished) - { - m_fInCombat = FALSE; - } - - CSquadMonster ::RunTask(pTask); - - if (!m_fInCombat) - { - if (HasConditions(bits_COND_CAN_RANGE_ATTACK1)) - { - pev->sequence = LookupActivity(ACT_RANGE_ATTACK1); - pev->frame = 0; - ResetSequenceInfo(); - m_fInCombat = TRUE; - } - else if (HasConditions(bits_COND_CAN_RANGE_ATTACK2)) - { - pev->sequence = LookupActivity(ACT_RANGE_ATTACK2); - pev->frame = 0; - ResetSequenceInfo(); - m_fInCombat = TRUE; - } - else - { - int iFloat = LookupFloat(); - if (m_fSequenceFinished || iFloat != pev->sequence) - { - pev->sequence = iFloat; - pev->frame = 0; - ResetSequenceInfo(); - } - } - } - break; - default: - CSquadMonster ::RunTask(pTask); - break; - } -} - -//========================================================= -// GetSchedule - Decides which type of schedule best suits -// the monster's current state and conditions. Then calls -// monster's member function to get a pointer to a schedule -// of the proper type. -//========================================================= -Schedule_t *CController ::GetSchedule(void) -{ - switch (m_MonsterState) - { - case MONSTERSTATE_IDLE: - break; - - case MONSTERSTATE_ALERT: - break; - - case MONSTERSTATE_COMBAT: - { - Vector vecTmp = Intersect(Vector(0, 0, 0), Vector(100, 4, 7), Vector(2, 10, -3), 20.0); - - // dead enemy - if (HasConditions(bits_COND_LIGHT_DAMAGE)) - { - // m_iFrustration++; - } - if (HasConditions(bits_COND_HEAVY_DAMAGE)) - { - // m_iFrustration++; - } - } - break; - } - - return CSquadMonster ::GetSchedule(); -} - -//========================================================= -//========================================================= -Schedule_t *CController ::GetScheduleOfType(int Type) -{ - // ALERT( at_console, "%d\n", m_iFrustration ); - switch (Type) - { - case SCHED_CHASE_ENEMY: - return slControllerChaseEnemy; - case SCHED_RANGE_ATTACK1: - return slControllerStrafe; - case SCHED_RANGE_ATTACK2: - case SCHED_MELEE_ATTACK1: - case SCHED_MELEE_ATTACK2: - case SCHED_TAKE_COVER_FROM_ENEMY: - return slControllerTakeCover; - case SCHED_FAIL: - return slControllerFail; - } - - return CBaseMonster ::GetScheduleOfType(Type); -} - -//========================================================= -// CheckRangeAttack1 - shoot a bigass energy ball out of their head -// -//========================================================= -BOOL CController ::CheckRangeAttack1(float flDot, float flDist) -{ - if (flDot > 0.5 && flDist > 256 && flDist <= 2048) - { - return TRUE; - } - return FALSE; -} - -BOOL CController ::CheckRangeAttack2(float flDot, float flDist) -{ - if (flDot > 0.5 && flDist > 64 && flDist <= 2048) - { - return TRUE; - } - return FALSE; -} - -BOOL CController ::CheckMeleeAttack1(float flDot, float flDist) -{ - return FALSE; -} - -void CController ::SetActivity(Activity NewActivity) -{ - CBaseMonster::SetActivity(NewActivity); - - switch (m_Activity) - { - case ACT_WALK: - m_flGroundSpeed = 100; - break; - default: - m_flGroundSpeed = 100; - break; - } -} - -//========================================================= -// RunAI -//========================================================= -void CController ::RunAI(void) -{ - CBaseMonster ::RunAI(); - Vector vecStart, angleGun; - - if (HasMemory(bits_MEMORY_KILLED)) - return; - - for (int i = 0; i < 2; i++) - { - if (m_pBall[i] == NULL) - { - m_pBall[i] = CSprite::SpriteCreate("sprites/xspark4.spr", pev->origin, TRUE); - m_pBall[i]->SetTransparency(kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation); - m_pBall[i]->SetAttachment(edict(), (i + 3)); - m_pBall[i]->SetScale(1.0); - } - - float t = m_iBallTime[i] - gpGlobals->time; - if (t > 0.1) - t = 0.1 / t; - else - t = 1.0; - - m_iBallCurrent[i] += (m_iBall[i] - m_iBallCurrent[i]) * t; - - m_pBall[i]->SetBrightness(m_iBallCurrent[i]); - - GetAttachment(i + 2, vecStart, angleGun); - UTIL_SetOrigin(m_pBall[i]->pev, vecStart); - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex() + 0x1000 * (i + 3)); // entity, attachment - WRITE_COORD(vecStart.x); // origin - WRITE_COORD(vecStart.y); - WRITE_COORD(vecStart.z); - WRITE_COORD(m_iBallCurrent[i] / 8); // radius - WRITE_BYTE(255); // R - WRITE_BYTE(192); // G - WRITE_BYTE(64); // B - WRITE_BYTE(5); // life * 10 - WRITE_COORD(0); // decay - MESSAGE_END(); - } -} - -extern void DrawRoute(entvars_t *pev, WayPoint_t *m_Route, int m_iRouteIndex, int r, int g, int b); - -void CController::Stop(void) -{ - m_IdealActivity = GetStoppedActivity(); -} - -#define DIST_TO_CHECK 200 -void CController ::Move(float flInterval) -{ - float flWaypointDist; - float flCheckDist; - float flDist; // how far the lookahead check got before hitting an object. - float flMoveDist; - Vector vecDir; - Vector vecApex; - CBaseEntity *pTargetEnt; - - // Don't move if no valid route - if (FRouteClear()) - { - ALERT(at_aiconsole, "Tried to move with no route!\n"); - TaskFail(); - return; - } - - if (m_flMoveWaitFinished > gpGlobals->time) - return; - -// Debug, test movement code -#if 0 -// if ( CVAR_GET_FLOAT("stopmove" ) != 0 ) - { - if ( m_movementGoal == MOVEGOAL_ENEMY ) - RouteSimplify( m_hEnemy ); - else - RouteSimplify( m_hTargetEnt ); - FRefreshRoute(); - return; - } -#else -// Debug, draw the route -// DrawRoute( pev, m_Route, m_iRouteIndex, 0, 0, 255 ); -#endif - - // if the monster is moving directly towards an entity (enemy for instance), we'll set this pointer - // to that entity for the CheckLocalMove and Triangulate functions. - pTargetEnt = NULL; - - if (m_flGroundSpeed == 0) - { - m_flGroundSpeed = 100; - // TaskFail( ); - // return; - } - - flMoveDist = m_flGroundSpeed * flInterval; - - do - { - // local move to waypoint. - vecDir = (m_Route[m_iRouteIndex].vecLocation - pev->origin).Normalize(); - flWaypointDist = (m_Route[m_iRouteIndex].vecLocation - pev->origin).Length(); - - // MakeIdealYaw ( m_Route[ m_iRouteIndex ].vecLocation ); - // ChangeYaw ( pev->yaw_speed ); - - // if the waypoint is closer than CheckDist, CheckDist is the dist to waypoint - if (flWaypointDist < DIST_TO_CHECK) - { - flCheckDist = flWaypointDist; - } - else - { - flCheckDist = DIST_TO_CHECK; - } - - if ((m_Route[m_iRouteIndex].iType & (~bits_MF_NOT_TO_MASK)) == bits_MF_TO_ENEMY) - { - // only on a PURE move to enemy ( i.e., ONLY MF_TO_ENEMY set, not MF_TO_ENEMY and DETOUR ) - pTargetEnt = m_hEnemy; - } - else if ((m_Route[m_iRouteIndex].iType & ~bits_MF_NOT_TO_MASK) == bits_MF_TO_TARGETENT) - { - pTargetEnt = m_hTargetEnt; - } - - // !!!BUGBUG - CheckDist should be derived from ground speed. - // If this fails, it should be because of some dynamic entity blocking this guy. - // We've already checked this path, so we should wait and time out if the entity doesn't move - flDist = 0; - if (CheckLocalMove(pev->origin, pev->origin + vecDir * flCheckDist, pTargetEnt, &flDist) != LOCALMOVE_VALID) - { - CBaseEntity *pBlocker; - - // Can't move, stop - Stop(); - // Blocking entity is in global trace_ent - pBlocker = CBaseEntity::Instance(gpGlobals->trace_ent); - if (pBlocker) - { - DispatchBlocked(edict(), pBlocker->edict()); - } - if (pBlocker && m_moveWaitTime > 0 && pBlocker->IsMoving() && !pBlocker->IsPlayer() && (gpGlobals->time - m_flMoveWaitFinished) > 3.0) - { - // Can we still move toward our target? - if (flDist < m_flGroundSpeed) - { - // Wait for a second - m_flMoveWaitFinished = gpGlobals->time + m_moveWaitTime; - // ALERT( at_aiconsole, "Move %s!!!\n", STRING( pBlocker->pev->classname ) ); - return; - } - } - else - { - // try to triangulate around whatever is in the way. - if (FTriangulate(pev->origin, m_Route[m_iRouteIndex].vecLocation, flDist, pTargetEnt, &vecApex)) - { - InsertWaypoint(vecApex, bits_MF_TO_DETOUR); - RouteSimplify(pTargetEnt); - } - else - { - ALERT(at_aiconsole, "Couldn't Triangulate\n"); - Stop(); - if (m_moveWaitTime > 0) - { - FRefreshRoute(); - m_flMoveWaitFinished = gpGlobals->time + m_moveWaitTime * 0.5; - } - else - { - TaskFail(); - ALERT(at_aiconsole, "Failed to move!\n"); - //ALERT( at_aiconsole, "%f, %f, %f\n", pev->origin.z, (pev->origin + (vecDir * flCheckDist)).z, m_Route[m_iRouteIndex].vecLocation.z ); - } - return; - } - } - } - - // UNDONE: this is a hack to quit moving farther than it has looked ahead. - if (flCheckDist < flMoveDist) - { - MoveExecute(pTargetEnt, vecDir, flCheckDist / m_flGroundSpeed); - - // ALERT( at_console, "%.02f\n", flInterval ); - AdvanceRoute(flWaypointDist); - flMoveDist -= flCheckDist; - } - else - { - MoveExecute(pTargetEnt, vecDir, flMoveDist / m_flGroundSpeed); - - if (ShouldAdvanceRoute(flWaypointDist - flMoveDist)) - { - AdvanceRoute(flWaypointDist); - } - flMoveDist = 0; - } - - if (MovementIsComplete()) - { - Stop(); - RouteClear(); - } - } while (flMoveDist > 0 && flCheckDist > 0); - - // cut corner? - if (flWaypointDist < 128) - { - if (m_movementGoal == MOVEGOAL_ENEMY) - RouteSimplify(m_hEnemy); - else - RouteSimplify(m_hTargetEnt); - FRefreshRoute(); - - if (m_flGroundSpeed > 100) - m_flGroundSpeed -= 40; - } - else - { - if (m_flGroundSpeed < 400) - m_flGroundSpeed += 10; - } -} - -BOOL CController::ShouldAdvanceRoute(float flWaypointDist) -{ - if (flWaypointDist <= 32) - { - return TRUE; - } - - return FALSE; -} - -int CController ::CheckLocalMove(const Vector &vecStart, const Vector &vecEnd, CBaseEntity *pTarget, float *pflDist) -{ - TraceResult tr; - - UTIL_TraceHull(vecStart + Vector(0, 0, 32), vecEnd + Vector(0, 0, 32), dont_ignore_monsters, large_hull, edict(), &tr); - - // ALERT( at_console, "%.0f %.0f %.0f : ", vecStart.x, vecStart.y, vecStart.z ); - // ALERT( at_console, "%.0f %.0f %.0f\n", vecEnd.x, vecEnd.y, vecEnd.z ); - - if (pflDist) - { - *pflDist = ((tr.vecEndPos - Vector(0, 0, 32)) - vecStart).Length(); // get the distance. - } - - // ALERT( at_console, "check %d %d %f\n", tr.fStartSolid, tr.fAllSolid, tr.flFraction ); - if (tr.fStartSolid || tr.flFraction < 1.0) - { - if (pTarget && pTarget->edict() == gpGlobals->trace_ent) - return LOCALMOVE_VALID; - return LOCALMOVE_INVALID; - } - - return LOCALMOVE_VALID; -} - -void CController::MoveExecute(CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval) -{ - if (m_IdealActivity != m_movementActivity) - m_IdealActivity = m_movementActivity; - - // ALERT( at_console, "move %.4f %.4f %.4f : %f\n", vecDir.x, vecDir.y, vecDir.z, flInterval ); - - // float flTotal = m_flGroundSpeed * pev->framerate * flInterval; - // UTIL_MoveToOrigin ( ENT(pev), m_Route[ m_iRouteIndex ].vecLocation, flTotal, MOVE_STRAFE ); - - m_velocity = m_velocity * 0.8 + m_flGroundSpeed * vecDir * 0.2; - - UTIL_MoveToOrigin(ENT(pev), pev->origin + m_velocity, m_velocity.Length() * flInterval, MOVE_STRAFE); -} - -//========================================================= -// Controller bouncy ball attack -//========================================================= -class CControllerHeadBall : public CBaseMonster -{ - void Spawn(void); - void Precache(void); - void EXPORT HuntThink(void); - void EXPORT DieThink(void); - void EXPORT BounceTouch(CBaseEntity *pOther); - void MovetoTarget(Vector vecTarget); - void Crawl(void); - int m_iTrail; - int m_flNextAttack; - Vector m_vecIdeal; - EHANDLE m_hOwner; -}; -LINK_ENTITY_TO_CLASS(controller_head_ball, CControllerHeadBall); - -void CControllerHeadBall ::Spawn(void) -{ - Precache(); - // motor - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - SET_MODEL(ENT(pev), "sprites/xspark4.spr"); - pev->rendermode = kRenderTransAdd; - pev->rendercolor.x = 255; - pev->rendercolor.y = 255; - pev->rendercolor.z = 255; - pev->renderamt = 255; - pev->scale = 2.0; - - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); - UTIL_SetOrigin(pev, pev->origin); - - SetThink(HuntThink); - SetTouch(BounceTouch); - - m_vecIdeal = Vector(0, 0, 0); - - pev->nextthink = gpGlobals->time + 0.1; - - m_hOwner = Instance(pev->owner); - pev->dmgtime = gpGlobals->time; -} - -void CControllerHeadBall ::Precache(void) -{ - PRECACHE_MODEL("sprites/xspark1.spr"); - PRECACHE_SOUND("debris/zap4.wav"); - PRECACHE_SOUND("weapons/electro4.wav"); -} - -void CControllerHeadBall ::HuntThink(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - pev->renderamt -= 5; - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex()); // entity, attachment - WRITE_COORD(pev->origin.x); // origin - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(pev->renderamt / 16); // radius - WRITE_BYTE(255); // R - WRITE_BYTE(255); // G - WRITE_BYTE(255); // B - WRITE_BYTE(2); // life * 10 - WRITE_COORD(0); // decay - MESSAGE_END(); - - // check world boundaries - if (gpGlobals->time - pev->dmgtime > 5 || pev->renderamt < 64 || m_hEnemy == NULL || m_hOwner == NULL || pev->origin.x < -4096 || pev->origin.x > 4096 || pev->origin.y < -4096 || pev->origin.y > 4096 || pev->origin.z < -4096 || pev->origin.z > 4096) - { - SetTouch(NULL); - UTIL_Remove(this); - return; - } - - MovetoTarget(m_hEnemy->Center()); - - if ((m_hEnemy->Center() - pev->origin).Length() < 64) - { - TraceResult tr; - - UTIL_TraceLine(pev->origin, m_hEnemy->Center(), dont_ignore_monsters, ENT(pev), &tr); - - CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); - if (pEntity != NULL && pEntity->pev->takedamage) - { - ClearMultiDamage(); - pEntity->TraceAttack(m_hOwner->pev, gSkillData.controllerDmgZap, pev->velocity, &tr, DMG_SHOCK); - ApplyMultiDamage(pev, m_hOwner->pev); - } - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_BEAMENTPOINT); - WRITE_SHORT(entindex()); - WRITE_COORD(tr.vecEndPos.x); - WRITE_COORD(tr.vecEndPos.y); - WRITE_COORD(tr.vecEndPos.z); - WRITE_SHORT(g_sModelIndexLaser); - WRITE_BYTE(0); // frame start - WRITE_BYTE(10); // framerate - WRITE_BYTE(3); // life - WRITE_BYTE(20); // width - WRITE_BYTE(0); // noise - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // brightness - WRITE_BYTE(10); // speed - MESSAGE_END(); - - UTIL_EmitAmbientSound(ENT(pev), tr.vecEndPos, "weapons/electro4.wav", 0.5, ATTN_NORM, 0, RANDOM_LONG(140, 160)); - - m_flNextAttack = gpGlobals->time + 3.0; - - SetThink(DieThink); - pev->nextthink = gpGlobals->time + 0.3; - } - - // Crawl( ); -} - -void CControllerHeadBall ::DieThink(void) -{ - UTIL_Remove(this); -} - -void CControllerHeadBall ::MovetoTarget(Vector vecTarget) -{ - // accelerate - float flSpeed = m_vecIdeal.Length(); - if (flSpeed == 0) - { - m_vecIdeal = pev->velocity; - flSpeed = m_vecIdeal.Length(); - } - - if (flSpeed > 400) - { - m_vecIdeal = m_vecIdeal.Normalize() * 400; - } - m_vecIdeal = m_vecIdeal + (vecTarget - pev->origin).Normalize() * 100; - pev->velocity = m_vecIdeal; -} - -void CControllerHeadBall ::Crawl(void) -{ - - Vector vecAim = Vector(RANDOM_FLOAT(-1, 1), RANDOM_FLOAT(-1, 1), RANDOM_FLOAT(-1, 1)).Normalize(); - Vector vecPnt = pev->origin + pev->velocity * 0.3 + vecAim * 64; - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_BEAMENTPOINT); - WRITE_SHORT(entindex()); - WRITE_COORD(vecPnt.x); - WRITE_COORD(vecPnt.y); - WRITE_COORD(vecPnt.z); - WRITE_SHORT(g_sModelIndexLaser); - WRITE_BYTE(0); // frame start - WRITE_BYTE(10); // framerate - WRITE_BYTE(3); // life - WRITE_BYTE(20); // width - WRITE_BYTE(0); // noise - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // brightness - WRITE_BYTE(10); // speed - MESSAGE_END(); -} - -void CControllerHeadBall::BounceTouch(CBaseEntity *pOther) -{ - Vector vecDir = m_vecIdeal.Normalize(); - - TraceResult tr = UTIL_GetGlobalTrace(); - - float n = -DotProduct(tr.vecPlaneNormal, vecDir); - - vecDir = 2.0 * tr.vecPlaneNormal * n + vecDir; - - m_vecIdeal = vecDir * m_vecIdeal.Length(); -} - -class CControllerZapBall : public CBaseMonster -{ - void Spawn(void); - void Precache(void); - void EXPORT AnimateThink(void); - void EXPORT ExplodeTouch(CBaseEntity *pOther); - - EHANDLE m_hOwner; -}; -LINK_ENTITY_TO_CLASS(controller_energy_ball, CControllerZapBall); - -void CControllerZapBall ::Spawn(void) -{ - Precache(); - // motor - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - SET_MODEL(ENT(pev), "sprites/xspark4.spr"); - pev->rendermode = kRenderTransAdd; - pev->rendercolor.x = 255; - pev->rendercolor.y = 255; - pev->rendercolor.z = 255; - pev->renderamt = 255; - pev->scale = 0.5; - - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); - UTIL_SetOrigin(pev, pev->origin); - - SetThink(AnimateThink); - SetTouch(ExplodeTouch); - - m_hOwner = Instance(pev->owner); - pev->dmgtime = gpGlobals->time; // keep track of when ball spawned - pev->nextthink = gpGlobals->time + 0.1; -} - -void CControllerZapBall ::Precache(void) -{ - PRECACHE_MODEL("sprites/xspark4.spr"); - // PRECACHE_SOUND("debris/zap4.wav"); - // PRECACHE_SOUND("weapons/electro4.wav"); -} - -void CControllerZapBall ::AnimateThink(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - pev->frame = ((int)pev->frame + 1) % 11; - - if (gpGlobals->time - pev->dmgtime > 5 || pev->velocity.Length() < 10) - { - SetTouch(NULL); - UTIL_Remove(this); - } -} - -void CControllerZapBall::ExplodeTouch(CBaseEntity *pOther) -{ - if (pOther->pev->takedamage) - { - TraceResult tr = UTIL_GetGlobalTrace(); - - entvars_t *pevOwner; - if (m_hOwner != NULL) - { - pevOwner = m_hOwner->pev; - } - else - { - pevOwner = pev; - } - - ClearMultiDamage(); - pOther->TraceAttack(pevOwner, gSkillData.controllerDmgBall, pev->velocity.Normalize(), &tr, DMG_ENERGYBEAM); - ApplyMultiDamage(pevOwner, pevOwner); - - UTIL_EmitAmbientSound(ENT(pev), tr.vecEndPos, "weapons/electro4.wav", 0.3, ATTN_NORM, 0, RANDOM_LONG(90, 99)); - } - - UTIL_Remove(this); -} - -#endif // !OEM && !HLDEMO diff --git a/dlls/Half-life/crossbow.cpp b/dlls/Half-life/crossbow.cpp deleted file mode 100644 index 4eac8b97..00000000 --- a/dlls/Half-life/crossbow.cpp +++ /dev/null @@ -1,592 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "gamerules.h" - -#define BOLT_AIR_VELOCITY 2000 -#define BOLT_WATER_VELOCITY 1000 - -// UNDONE: Save/restore this? Don't forget to set classname and LINK_ENTITY_TO_CLASS() -// -// OVERLOADS SOME ENTVARS: -// -// speed - the ideal magnitude of my velocity -class CCrossbowBolt : public CBaseEntity -{ - void Spawn(void); - void Precache(void); - int Classify(void); - void EXPORT BubbleThink(void); - void EXPORT BoltTouch(CBaseEntity *pOther); - void EXPORT ExplodeThink(void); - - int m_iTrail; - -public: - static CCrossbowBolt *BoltCreate(void); -}; -LINK_ENTITY_TO_CLASS(crossbow_bolt, CCrossbowBolt); - -CCrossbowBolt *CCrossbowBolt::BoltCreate(void) -{ - // Create a new entity with CCrossbowBolt private data - CCrossbowBolt *pBolt = GetClassPtr((CCrossbowBolt *)NULL); - pBolt->pev->classname = MAKE_STRING("bolt"); - pBolt->Spawn(); - - return pBolt; -} - -void CCrossbowBolt::Spawn() -{ - Precache(); - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - pev->gravity = 0.5; - - SET_MODEL(ENT(pev), "models/crossbow_bolt.mdl"); - - UTIL_SetOrigin(pev, pev->origin); - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); - - SetTouch(BoltTouch); - SetThink(BubbleThink); - pev->nextthink = gpGlobals->time + 0.2; -} - -void CCrossbowBolt::Precache() -{ - PRECACHE_MODEL("models/crossbow_bolt.mdl"); - PRECACHE_SOUND("weapons/xbow_hitbod1.wav"); - PRECACHE_SOUND("weapons/xbow_hitbod2.wav"); - PRECACHE_SOUND("weapons/xbow_fly1.wav"); - PRECACHE_SOUND("weapons/xbow_hit1.wav"); - PRECACHE_SOUND("fvox/beep.wav"); - m_iTrail = PRECACHE_MODEL("sprites/streak.spr"); -} - -int CCrossbowBolt ::Classify(void) -{ - return CLASS_NONE; -} - -void CCrossbowBolt::BoltTouch(CBaseEntity *pOther) -{ - SetTouch(NULL); - SetThink(NULL); - - if (pOther->pev->takedamage) - { - TraceResult tr = UTIL_GetGlobalTrace(); - entvars_t *pevOwner; - - pevOwner = VARS(pev->owner); - - // UNDONE: this needs to call TraceAttack instead - ClearMultiDamage(); - - if (pOther->IsPlayer()) - { - pOther->TraceAttack(pevOwner, gSkillData.plrDmgCrossbowClient, pev->velocity.Normalize(), &tr, DMG_NEVERGIB); - } - else - { - pOther->TraceAttack(pevOwner, gSkillData.plrDmgCrossbowMonster, pev->velocity.Normalize(), &tr, DMG_BULLET | DMG_NEVERGIB); - } - - ApplyMultiDamage(pev, pevOwner); - - pev->velocity = Vector(0, 0, 0); - // play body "thwack" sound - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM); - break; - } - - if (!g_pGameRules->IsMultiplayer()) - { - Killed(pev, GIB_NEVER); - } - } - else - { - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "weapons/xbow_hit1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 98 + RANDOM_LONG(0, 7)); - - SetThink(SUB_Remove); - pev->nextthink = gpGlobals->time; // this will get changed below if the bolt is allowed to stick in what it hit. - - if (FClassnameIs(pOther->pev, "worldspawn")) - { - // if what we hit is static architecture, can stay around for a while. - Vector vecDir = pev->velocity.Normalize(); - UTIL_SetOrigin(pev, pev->origin - vecDir * 12); - pev->angles = UTIL_VecToAngles(vecDir); - pev->solid = SOLID_NOT; - pev->movetype = MOVETYPE_FLY; - pev->velocity = Vector(0, 0, 0); - pev->avelocity.z = 0; - pev->angles.z = RANDOM_LONG(0, 360); - pev->nextthink = gpGlobals->time + 10.0; - } - - if (UTIL_PointContents(pev->origin) != CONTENTS_WATER) - { - UTIL_Sparks(pev->origin); - } - } - - if (g_pGameRules->IsMultiplayer()) - { - SetThink(ExplodeThink); - pev->nextthink = gpGlobals->time + 0.1; - } -} - -void CCrossbowBolt::BubbleThink(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - if (pev->waterlevel == 0) - return; - - UTIL_BubbleTrail(pev->origin - pev->velocity * 0.1, pev->origin, 1); -} - -void CCrossbowBolt::ExplodeThink(void) -{ - int iContents = UTIL_PointContents(pev->origin); - int iScale; - - pev->dmg = 40; - iScale = 10; - - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_EXPLOSION); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - if (iContents != CONTENTS_WATER) - { - WRITE_SHORT(g_sModelIndexFireball); - } - else - { - WRITE_SHORT(g_sModelIndexWExplosion); - } - WRITE_BYTE(iScale); // scale * 10 - WRITE_BYTE(15); // framerate - WRITE_BYTE(TE_EXPLFLAG_NONE); - MESSAGE_END(); - - entvars_t *pevOwner; - - if (pev->owner) - pevOwner = VARS(pev->owner); - else - pevOwner = NULL; - - pev->owner = NULL; // can't traceline attack owner if this is set - - ::RadiusDamage(pev->origin, pev, pevOwner, pev->dmg, 128, CLASS_NONE, DMG_BLAST | DMG_ALWAYSGIB); - - UTIL_Remove(this); -} - -enum crossbow_e -{ - CROSSBOW_IDLE1 = 0, // full - CROSSBOW_IDLE2, // empty - CROSSBOW_FIDGET1, // full - CROSSBOW_FIDGET2, // empty - CROSSBOW_FIRE1, // full - CROSSBOW_FIRE2, // reload - CROSSBOW_FIRE3, // empty - CROSSBOW_RELOAD, // from empty - CROSSBOW_DRAW1, // full - CROSSBOW_DRAW2, // empty - CROSSBOW_HOLSTER1, // full - CROSSBOW_HOLSTER2, // empty -}; - -class CCrossbow : public CBasePlayerWeapon -{ -public: - void Spawn(void); - void Precache(void); - int iItemSlot() { return 3; } - int GetItemInfo(ItemInfo *p); - - void FireBolt(void); - void FireSniperBolt(void); - void PrimaryAttack(void); - void SecondaryAttack(void); - int AddToPlayer(CBasePlayer *pPlayer); - BOOL Deploy(); - void Holster(int skiplocal = 0); - void Reload(void); - void WeaponIdle(void); - - int m_fInZoom; // don't save this -}; -LINK_ENTITY_TO_CLASS(weapon_crossbow, CCrossbow); - -void CCrossbow::Spawn() -{ - Precache(); - m_iId = WEAPON_CROSSBOW; - SET_MODEL(ENT(pev), "models/w_crossbow.mdl"); - - m_iDefaultAmmo = CROSSBOW_DEFAULT_GIVE; - - FallInit(); // get ready to fall down. -} - -int CCrossbow::AddToPlayer(CBasePlayer *pPlayer) -{ - if (CBasePlayerWeapon::AddToPlayer(pPlayer)) - { - MESSAGE_BEGIN(MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev); - WRITE_BYTE(m_iId); - MESSAGE_END(); - return TRUE; - } - return FALSE; -} - -void CCrossbow::Precache(void) -{ - PRECACHE_MODEL("models/w_crossbow.mdl"); - PRECACHE_MODEL("models/v_crossbow.mdl"); - PRECACHE_MODEL("models/p_crossbow.mdl"); - - PRECACHE_SOUND("weapons/xbow_fire1.wav"); - PRECACHE_SOUND("weapons/xbow_reload1.wav"); - - UTIL_PrecacheOther("crossbow_bolt"); -} - -int CCrossbow::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "bolts"; - p->iMaxAmmo1 = BOLT_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = CROSSBOW_MAX_CLIP; - p->iSlot = 2; - p->iPosition = 2; - p->iId = WEAPON_CROSSBOW; - p->iFlags = 0; - p->iWeight = CROSSBOW_WEIGHT; - return 1; -} - -BOOL CCrossbow::Deploy() -{ - if (m_iClip) - return DefaultDeploy("models/v_crossbow.mdl", "models/p_crossbow.mdl", CROSSBOW_DRAW1, "bow"); - return DefaultDeploy("models/v_crossbow.mdl", "models/p_crossbow.mdl", CROSSBOW_DRAW2, "bow"); -} - -void CCrossbow::Holster(int skiplocal /* = 0 */) -{ - m_fInReload = FALSE; // cancel any reload in progress. - - if (m_fInZoom) - { - SecondaryAttack(); - } - - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - if (m_iClip) - SendWeaponAnim(CROSSBOW_HOLSTER1); - else - SendWeaponAnim(CROSSBOW_HOLSTER2); -} - -void CCrossbow::PrimaryAttack(void) -{ - if (m_fInZoom && g_pGameRules->IsMultiplayer()) - { - FireSniperBolt(); - return; - } - - FireBolt(); -} - -// this function only gets called in multiplayer -void CCrossbow::FireSniperBolt() -{ - m_flNextPrimaryAttack = gpGlobals->time + 0.75; - - if (m_iClip == 0) - { - PlayEmptySound(); - return; - } - - TraceResult tr; - - m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; - m_iClip--; - - // make twang sound - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/xbow_fire1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0, 0xF)); - - if (m_iClip) - { - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/xbow_reload1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0, 0xF)); - SendWeaponAnim(CROSSBOW_FIRE1); - } - else if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0) - { - SendWeaponAnim(CROSSBOW_FIRE3); - } - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - Vector anglesAim = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle; - UTIL_MakeVectors(anglesAim); - Vector vecSrc = m_pPlayer->GetGunPosition() - gpGlobals->v_up * 2; - Vector vecDir = gpGlobals->v_forward; - - UTIL_TraceLine(vecSrc, vecSrc + vecDir * 8192, dont_ignore_monsters, m_pPlayer->edict(), &tr); - - if (tr.pHit->v.takedamage) - { - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND(tr.pHit, CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(tr.pHit, CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM); - break; - } - - ClearMultiDamage(); - CBaseEntity::Instance(tr.pHit)->TraceAttack(m_pPlayer->pev, 120, vecDir, &tr, DMG_BULLET | DMG_NEVERGIB); - ApplyMultiDamage(pev, m_pPlayer->pev); - } - else - { - // create a bolt - CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate(); - pBolt->pev->origin = tr.vecEndPos - vecDir * 10; - pBolt->pev->angles = UTIL_VecToAngles(vecDir); - pBolt->pev->solid = SOLID_NOT; - pBolt->SetTouch(NULL); - pBolt->SetThink(SUB_Remove); - - EMIT_SOUND(pBolt->edict(), CHAN_WEAPON, "weapons/xbow_hit1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM); - - if (UTIL_PointContents(tr.vecEndPos) != CONTENTS_WATER) - { - UTIL_Sparks(tr.vecEndPos); - } - - if (FClassnameIs(tr.pHit, "worldspawn")) - { - // let the bolt sit around for a while if it hit static architecture - pBolt->pev->nextthink = gpGlobals->time + 5.0; - } - else - { - pBolt->pev->nextthink = gpGlobals->time; - } - } -} - -void CCrossbow::FireBolt() -{ - TraceResult tr; - - if (m_iClip == 0) - { - PlayEmptySound(); - return; - } - - m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; - - m_iClip--; - - // make twang sound - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/xbow_fire1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0, 0xF)); - - if (m_iClip) - { - - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/xbow_reload1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0, 0xF)); - SendWeaponAnim(CROSSBOW_FIRE1); - } - else if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0) - { - SendWeaponAnim(CROSSBOW_FIRE3); - } - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - Vector anglesAim = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle; - UTIL_MakeVectors(anglesAim); - - // Vector vecSrc = pev->origin + gpGlobals->v_up * 16 + gpGlobals->v_forward * 20 + gpGlobals->v_right * 4; - anglesAim.x = -anglesAim.x; - Vector vecSrc = m_pPlayer->GetGunPosition() - gpGlobals->v_up * 2; - Vector vecDir = gpGlobals->v_forward; - - //CBaseEntity *pBolt = CBaseEntity::Create( "crossbow_bolt", vecSrc, anglesAim, m_pPlayer->edict() ); - CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate(); - pBolt->pev->origin = vecSrc; - pBolt->pev->angles = anglesAim; - pBolt->pev->owner = m_pPlayer->edict(); - - if (m_pPlayer->pev->waterlevel == 3) - { - pBolt->pev->velocity = vecDir * BOLT_WATER_VELOCITY; - pBolt->pev->speed = BOLT_WATER_VELOCITY; - } - else - { - pBolt->pev->velocity = vecDir * BOLT_AIR_VELOCITY; - pBolt->pev->speed = BOLT_AIR_VELOCITY; - } - pBolt->pev->avelocity.z = 10; - - if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - // HEV suit - indicate out of ammo condition - m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - - m_flNextPrimaryAttack = gpGlobals->time + 0.75; - - m_flNextSecondaryAttack = gpGlobals->time + 0.75; - if (m_iClip != 0) - m_flTimeWeaponIdle = gpGlobals->time + 5.0; - else - m_flTimeWeaponIdle = 0.75; - - m_pPlayer->pev->punchangle.x -= 2; -} - -void CCrossbow::SecondaryAttack() -{ - if (m_fInZoom) - { - m_pPlayer->m_iFOV = 0; // 0 means reset to default fov - m_fInZoom = 0; - } - else - { - m_pPlayer->m_iFOV = 20; - m_fInZoom = 1; - } - - pev->nextthink = gpGlobals->time + 0.1; - m_flNextSecondaryAttack = gpGlobals->time + 1.0; -} - -void CCrossbow::Reload(void) -{ - if (m_fInZoom) - { - SecondaryAttack(); - } - - if (DefaultReload(5, CROSSBOW_RELOAD, 4.5)) - { - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/xbow_reload1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0, 0xF)); - } -} - -void CCrossbow::WeaponIdle(void) -{ - m_pPlayer->GetAutoaimVector(AUTOAIM_2DEGREES); // get the autoaim vector but ignore it; used for autoaim crosshair in DM - - ResetEmptySound(); - - if (m_flTimeWeaponIdle < gpGlobals->time) - { - float flRand = RANDOM_FLOAT(0, 1); - if (flRand <= 0.75) - { - if (m_iClip) - { - SendWeaponAnim(CROSSBOW_IDLE1); - } - else - { - SendWeaponAnim(CROSSBOW_IDLE2); - } - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); - } - else - { - if (m_iClip) - { - SendWeaponAnim(CROSSBOW_FIDGET1); - m_flTimeWeaponIdle = gpGlobals->time + 90.0 / 30.0; - } - else - { - SendWeaponAnim(CROSSBOW_FIDGET2); - m_flTimeWeaponIdle = gpGlobals->time + 80.0 / 30.0; - } - } - } -} - -class CCrossbowAmmo : public CBasePlayerAmmo -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_crossbow_clip.mdl"); - CBasePlayerAmmo::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_crossbow_clip.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - } - BOOL AddAmmo(CBaseEntity *pOther) - { - if (pOther->GiveAmmo(AMMO_CROSSBOWCLIP_GIVE, "bolts", BOLT_MAX_CARRY) != -1) - { - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); - return TRUE; - } - return FALSE; - } -}; -LINK_ENTITY_TO_CLASS(ammo_crossbow, CCrossbowAmmo); - -#endif \ No newline at end of file diff --git a/dlls/Half-life/crowbar.cpp b/dlls/Half-life/crowbar.cpp deleted file mode 100644 index 9621091f..00000000 --- a/dlls/Half-life/crowbar.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "gamerules.h" - -#define CROWBAR_BODYHIT_VOLUME 128 -#define CROWBAR_WALLHIT_VOLUME 512 - -class CCrowbar : public CBasePlayerWeapon -{ -public: - void Spawn(void); - void Precache(void); - int iItemSlot(void) { return 1; } - void EXPORT SwingAgain(void); - void EXPORT Smack(void); - int GetItemInfo(ItemInfo *p); - - void PrimaryAttack(void); - int Swing(int fFirst); - BOOL Deploy(void); - void Holster(int skiplocal = 0); - int m_iSwing; - TraceResult m_trHit; -}; -LINK_ENTITY_TO_CLASS(weapon_crowbar, CCrowbar); - -enum gauss_e -{ - CROWBAR_IDLE = 0, - CROWBAR_DRAW, - CROWBAR_HOLSTER, - CROWBAR_ATTACK1HIT, - CROWBAR_ATTACK1MISS, - CROWBAR_ATTACK2MISS, - CROWBAR_ATTACK2HIT, - CROWBAR_ATTACK3MISS, - CROWBAR_ATTACK3HIT -}; - -void CCrowbar::Spawn() -{ - Precache(); - m_iId = WEAPON_CROWBAR; - SET_MODEL(ENT(pev), "models/w_crowbar.mdl"); - m_iClip = -1; - - FallInit(); // get ready to fall down. -} - -void CCrowbar::Precache(void) -{ - PRECACHE_MODEL("models/v_crowbar.mdl"); - PRECACHE_MODEL("models/w_crowbar.mdl"); - PRECACHE_MODEL("models/p_crowbar.mdl"); - PRECACHE_SOUND("weapons/cbar_hit1.wav"); - PRECACHE_SOUND("weapons/cbar_hit2.wav"); - PRECACHE_SOUND("weapons/cbar_hitbod1.wav"); - PRECACHE_SOUND("weapons/cbar_hitbod2.wav"); - PRECACHE_SOUND("weapons/cbar_hitbod3.wav"); - PRECACHE_SOUND("weapons/cbar_miss1.wav"); -} - -int CCrowbar::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = NULL; - p->iMaxAmmo1 = -1; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = WEAPON_NOCLIP; - p->iSlot = 0; - p->iPosition = 0; - p->iId = WEAPON_CROWBAR; - p->iWeight = CROWBAR_WEIGHT; - return 1; -} - -BOOL CCrowbar::Deploy() -{ - return DefaultDeploy("models/v_crowbar.mdl", "models/p_crowbar.mdl", CROWBAR_DRAW, "crowbar"); -} - -void CCrowbar::Holster(int skiplocal /* = 0 */) -{ - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - SendWeaponAnim(CROWBAR_HOLSTER); -} - -void FindHullIntersection(const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity) -{ - int i, j, k; - float distance; - float *minmaxs[2] = {mins, maxs}; - TraceResult tmpTrace; - Vector vecHullEnd = tr.vecEndPos; - Vector vecEnd; - - distance = 1e6f; - - vecHullEnd = vecSrc + ((vecHullEnd - vecSrc) * 2); - UTIL_TraceLine(vecSrc, vecHullEnd, dont_ignore_monsters, pEntity, &tmpTrace); - if (tmpTrace.flFraction < 1.0) - { - tr = tmpTrace; - return; - } - - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - vecEnd.x = vecHullEnd.x + minmaxs[i][0]; - vecEnd.y = vecHullEnd.y + minmaxs[j][1]; - vecEnd.z = vecHullEnd.z + minmaxs[k][2]; - - UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, pEntity, &tmpTrace); - if (tmpTrace.flFraction < 1.0) - { - float thisDistance = (tmpTrace.vecEndPos - vecSrc).Length(); - if (thisDistance < distance) - { - tr = tmpTrace; - distance = thisDistance; - } - } - } - } - } -} - -void CCrowbar::PrimaryAttack() -{ - if (!Swing(1)) - { - SetThink(SwingAgain); - pev->nextthink = gpGlobals->time + 0.1; - } -} - -void CCrowbar::Smack() -{ - DecalGunshot(&m_trHit, BULLET_PLAYER_CROWBAR); -} - -void CCrowbar::SwingAgain(void) -{ - Swing(0); -} - -int CCrowbar::Swing(int fFirst) -{ - int fDidHit = FALSE; - - TraceResult tr; - - UTIL_MakeVectors(m_pPlayer->pev->v_angle); - Vector vecSrc = m_pPlayer->GetGunPosition(); - Vector vecEnd = vecSrc + gpGlobals->v_forward * 32; - - UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr); - - if (tr.flFraction >= 1.0) - { - UTIL_TraceHull(vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT(m_pPlayer->pev), &tr); - if (tr.flFraction < 1.0) - { - // Calculate the point of intersection of the line (or hull) and the object we hit - // This is and approximation of the "best" intersection - CBaseEntity *pHit = CBaseEntity::Instance(tr.pHit); - if (!pHit || pHit->IsBSPModel()) - FindHullIntersection(vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict()); - vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space) - } - } - - if (tr.flFraction >= 1.0) - { - if (fFirst) - { - // miss - switch ((m_iSwing++) % 3) - { - case 0: - SendWeaponAnim(CROWBAR_ATTACK1MISS); - break; - case 1: - SendWeaponAnim(CROWBAR_ATTACK2MISS); - break; - case 2: - SendWeaponAnim(CROWBAR_ATTACK3MISS); - break; - } - m_flNextPrimaryAttack = gpGlobals->time + 0.5; - // play wiff or swish sound - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0, 0xF)); - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - } - } - else - { - // hit - fDidHit = TRUE; - - CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); - - switch (((m_iSwing++) % 2) + 1) - { - case 0: - SendWeaponAnim(CROWBAR_ATTACK1HIT); - break; - case 1: - SendWeaponAnim(CROWBAR_ATTACK2HIT); - break; - case 2: - SendWeaponAnim(CROWBAR_ATTACK3HIT); - break; - } - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - ClearMultiDamage(); - if ((m_flNextPrimaryAttack + 1 < gpGlobals->time) || g_pGameRules->IsMultiplayer()) - { - // first swing does full damage - pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar, gpGlobals->v_forward, &tr, DMG_CLUB); - } - else - { - // subsequent swings do half - pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar / 2, gpGlobals->v_forward, &tr, DMG_CLUB); - } - ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev); - - m_flNextPrimaryAttack = gpGlobals->time + 0.25; - - // play thwack, smack, or dong sound - float flVol = 1.0; - int fHitWorld = TRUE; - - if (pEntity) - { - if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE) - { - // play thwack or smack sound - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM); - break; - } - m_pPlayer->m_iWeaponVolume = CROWBAR_BODYHIT_VOLUME; - if (!pEntity->IsAlive()) - return TRUE; - else - flVol = 0.1; - - fHitWorld = FALSE; - } - } - - // play texture hit sound - // UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line - - if (fHitWorld) - { - float fvolbar = TEXTURETYPE_PlaySound(&tr, vecSrc, vecSrc + (vecEnd - vecSrc) * 2, BULLET_PLAYER_CROWBAR); - - if (g_pGameRules->IsMultiplayer()) - { - // override the volume here, cause we don't play texture sounds in multiplayer, - // and fvolbar is going to be 0 from the above call. - - fvolbar = 1; - } - - // also play crowbar strike - switch (RANDOM_LONG(0, 1)) - { - case 0: - //UTIL_EmitAmbientSound(ENT(0), ptr->vecEndPos, "weapons/cbar_hit1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0, 3)); - break; - case 1: - //UTIL_EmitAmbientSound(ENT(0), ptr->vecEndPos, "weapons/cbar_hit2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0, 3)); - break; - } - } - - // delay the decal a bit - m_trHit = tr; - SetThink(Smack); - pev->nextthink = gpGlobals->time + 0.2; - - m_pPlayer->m_iWeaponVolume = flVol * CROWBAR_WALLHIT_VOLUME; - } - return fDidHit; -} diff --git a/dlls/Half-life/egon.cpp b/dlls/Half-life/egon.cpp deleted file mode 100644 index 354a4ad5..00000000 --- a/dlls/Half-life/egon.cpp +++ /dev/null @@ -1,623 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD ) - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "player.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "effects.h" -#include "customentity.h" -#include "gamerules.h" - -#define EGON_PRIMARY_VOLUME 450 -#define EGON_BEAM_SPRITE "sprites/xbeam1.spr" -#define EGON_FLARE_SPRITE "sprites/XSpark1.spr" -#define EGON_SOUND_OFF "weapons/egon_off1.wav" -#define EGON_SOUND_RUN "weapons/egon_run3.wav" -#define EGON_SOUND_STARTUP "weapons/egon_windup2.wav" - -#define EGON_SWITCH_NARROW_TIME 0.75 // Time it takes to switch fire modes -#define EGON_SWITCH_WIDE_TIME 1.5 - - -enum egon_e { - EGON_IDLE1 = 0, - EGON_FIDGET1, - EGON_ALTFIREON, - EGON_ALTFIRECYCLE, - EGON_ALTFIREOFF, - EGON_FIRE1, - EGON_FIRE2, - EGON_FIRE3, - EGON_FIRE4, - EGON_DRAW, - EGON_HOLSTER -}; - - -class CEgon : public CBasePlayerWeapon -{ -public: - int Save( CSave &save ); - int Restore( CRestore &restore ); - static TYPEDESCRIPTION m_SaveData[]; - - void Spawn( void ); - void Precache( void ); - int iItemSlot( void ) { return 4; } - int GetItemInfo(ItemInfo *p); - int AddToPlayer( CBasePlayer *pPlayer ); - - BOOL Deploy( void ); - void Holster( int skiplocal = 0 ); - - void CreateEffect( void ); - void UpdateEffect( const Vector &startPoint, const Vector &endPoint, float timeBlend ); - void DestroyEffect( void ); - - void EndAttack( void ); - void Attack( void ); - void PrimaryAttack( void ); - void WeaponIdle( void ); - static int g_fireAnims1[]; - static int g_fireAnims2[]; - - float m_flAmmoUseTime;// since we use < 1 point of ammo per update, we subtract ammo on a timer. - - float GetPulseInterval( void ); - float GetDischargeInterval( void ); - - void Fire( const Vector &vecOrigSrc, const Vector &vecDir ); - - BOOL HasAmmo( void ) - { - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - return FALSE; - return TRUE; - } - - void UseAmmo( int count ) - { - if ( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] >= count ) - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= count; - else - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] = 0; - } - - enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE }; - enum EGON_FIREMODE { FIRE_NARROW, FIRE_WIDE}; - -private: - float m_shootTime; - CBeam *m_pBeam; - CBeam *m_pNoise; - CSprite *m_pSprite; - EGON_FIRESTATE m_fireState; - EGON_FIREMODE m_fireMode; - float m_shakeTime; - BOOL m_deployed; -}; - -LINK_ENTITY_TO_CLASS( weapon_egon, CEgon ); - -int CEgon::g_fireAnims1[] = { EGON_FIRE1, EGON_FIRE2, EGON_FIRE3, EGON_FIRE4 }; -int CEgon::g_fireAnims2[] = { EGON_ALTFIRECYCLE }; - - -TYPEDESCRIPTION CEgon::m_SaveData[] = -{ - DEFINE_FIELD( CEgon, m_pBeam, FIELD_CLASSPTR ), - DEFINE_FIELD( CEgon, m_pNoise, FIELD_CLASSPTR ), - DEFINE_FIELD( CEgon, m_pSprite, FIELD_CLASSPTR ), - DEFINE_FIELD( CEgon, m_shootTime, FIELD_TIME ), - DEFINE_FIELD( CEgon, m_fireState, FIELD_INTEGER ), - DEFINE_FIELD( CEgon, m_fireMode, FIELD_INTEGER ), - DEFINE_FIELD( CEgon, m_shakeTime, FIELD_TIME ), - DEFINE_FIELD( CEgon, m_flAmmoUseTime, FIELD_TIME ), -}; -IMPLEMENT_SAVERESTORE( CEgon, CBasePlayerWeapon ); - - -void CEgon::Spawn( ) -{ - Precache( ); - m_iId = WEAPON_EGON; - SET_MODEL(ENT(pev), "models/w_egon.mdl"); - - m_iDefaultAmmo = EGON_DEFAULT_GIVE; - - FallInit();// get ready to fall down. -} - - -void CEgon::Precache( void ) -{ - PRECACHE_MODEL("models/w_egon.mdl"); - PRECACHE_MODEL("models/v_egon.mdl"); - PRECACHE_MODEL("models/p_egon.mdl"); - - PRECACHE_MODEL("models/w_9mmclip.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - - PRECACHE_SOUND( EGON_SOUND_OFF ); - PRECACHE_SOUND( EGON_SOUND_RUN ); - PRECACHE_SOUND( EGON_SOUND_STARTUP ); - - PRECACHE_MODEL( EGON_BEAM_SPRITE ); - PRECACHE_MODEL( EGON_FLARE_SPRITE ); - - PRECACHE_SOUND ("weapons/357_cock1.wav"); -} - - -BOOL CEgon::Deploy( void ) -{ - m_deployed = FALSE; - return DefaultDeploy( "models/v_egon.mdl", "models/p_egon.mdl", EGON_DRAW, "egon" ); -} - -int CEgon::AddToPlayer( CBasePlayer *pPlayer ) -{ - if ( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) - { - MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); - WRITE_BYTE( m_iId ); - MESSAGE_END(); - return TRUE; - } - return FALSE; -} - - - -void CEgon::Holster( int skiplocal /* = 0 */ ) -{ - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - // m_flTimeWeaponIdle = gpGlobals->time + UTIL_RandomFloat ( 10, 15 ); - SendWeaponAnim( EGON_HOLSTER ); - - if ( m_fireState != FIRE_OFF ) - EndAttack(); -} - -int CEgon::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "uranium"; - p->iMaxAmmo1 = URANIUM_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = WEAPON_NOCLIP; - p->iSlot = 3; - p->iPosition = 2; - p->iId = m_iId = WEAPON_EGON; - p->iFlags = 0; - p->iWeight = EGON_WEIGHT; - - return 1; -} - - -//#define EGON_PULSE_INTERVAL 0.25 -//#define EGON_DISCHARGE_INTERVAL 0.5 - -#define EGON_PULSE_INTERVAL 0.1 -#define EGON_DISCHARGE_INTERVAL 0.1 - -float CEgon::GetPulseInterval( void ) -{ - if ( g_pGameRules->IsMultiplayer() ) - { - return 0.1; - } - - return EGON_PULSE_INTERVAL; -} - -float CEgon::GetDischargeInterval( void ) -{ - if ( g_pGameRules->IsMultiplayer() ) - { - return 0.1; - } - - return EGON_DISCHARGE_INTERVAL; -} - -void CEgon::Attack( void ) -{ - // don't fire underwater - if (m_pPlayer->pev->waterlevel == 3) - { - if ( m_pBeam ) - { - EndAttack(); - } - else - { - PlayEmptySound( ); - } - return; - } - - UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle ); - Vector vecAiming = gpGlobals->v_forward; - Vector vecSrc = m_pPlayer->GetGunPosition( ); - - switch( m_fireState ) - { - case FIRE_OFF: - { - if ( !HasAmmo() ) - { - m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->time + 0.25; - PlayEmptySound( ); - return; - } - - m_flAmmoUseTime = gpGlobals->time;// start using ammo ASAP. - - SendWeaponAnim( g_fireAnims1[ RANDOM_LONG(0,ARRAYSIZE(g_fireAnims1)-1) ] ); - m_shakeTime = 0; - - m_pPlayer->m_iWeaponVolume = EGON_PRIMARY_VOLUME; - m_flTimeWeaponIdle = gpGlobals->time + 0.1; - m_shootTime = gpGlobals->time + 2; - - if ( m_fireMode == FIRE_WIDE ) - { - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, EGON_SOUND_STARTUP, 0.98, ATTN_NORM, 0, 125 ); - } - else - { - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, EGON_SOUND_STARTUP, 0.9, ATTN_NORM, 0, 100 ); - } - - pev->dmgtime = gpGlobals->time + GetPulseInterval(); - m_fireState = FIRE_CHARGE; - } - break; - - case FIRE_CHARGE: - { - Fire( vecSrc, vecAiming ); - m_pPlayer->m_iWeaponVolume = EGON_PRIMARY_VOLUME; - - if ( m_shootTime != 0 && gpGlobals->time > m_shootTime ) - { - if ( m_fireMode == FIRE_WIDE ) - { - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_STATIC, EGON_SOUND_RUN, 0.98, ATTN_NORM, 0, 125 ); - } - else - { - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_STATIC, EGON_SOUND_RUN, 0.9, ATTN_NORM, 0, 100 ); - } - - m_shootTime = 0; - } - if ( !HasAmmo() ) - { - EndAttack(); - m_fireState = FIRE_OFF; - m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->time + 1.0; - } - - } - break; - } -} - -void CEgon::PrimaryAttack( void ) -{ - m_fireMode = FIRE_WIDE; - Attack(); - -} - -void CEgon::Fire( const Vector &vecOrigSrc, const Vector &vecDir ) -{ - Vector vecDest = vecOrigSrc + vecDir * 2048; - edict_t *pentIgnore; - TraceResult tr; - - pentIgnore = m_pPlayer->edict(); - Vector tmpSrc = vecOrigSrc + gpGlobals->v_up * -8 + gpGlobals->v_right * 3; - - // ALERT( at_console, "." ); - - UTIL_TraceLine( vecOrigSrc, vecDest, dont_ignore_monsters, pentIgnore, &tr ); - - if (tr.fAllSolid) - return; - - CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); - - if (pEntity == NULL) - return; - - if ( g_pGameRules->IsMultiplayer() ) - { - if ( m_pSprite && pEntity->pev->takedamage ) - { - m_pSprite->pev->effects &= ~EF_NODRAW; - } - else if ( m_pSprite ) - { - m_pSprite->pev->effects |= EF_NODRAW; - } - } - - float timedist; - - switch ( m_fireMode ) - { - case FIRE_NARROW: - if ( pev->dmgtime < gpGlobals->time ) - { - // Narrow mode only does damage to the entity it hits - ClearMultiDamage(); - if (pEntity->pev->takedamage) - { - pEntity->TraceAttack( m_pPlayer->pev, gSkillData.plrDmgEgonNarrow, vecDir, &tr, DMG_ENERGYBEAM ); - } - ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev); - - if ( g_pGameRules->IsMultiplayer() ) - { - // multiplayer uses 1 ammo every 1/10th second - if ( gpGlobals->time >= m_flAmmoUseTime ) - { - UseAmmo( 1 ); - m_flAmmoUseTime = gpGlobals->time + 0.1; - } - } - else - { - // single player, use 3 ammo/second - if ( gpGlobals->time >= m_flAmmoUseTime ) - { - UseAmmo( 1 ); - m_flAmmoUseTime = gpGlobals->time + 0.166; - } - } - - pev->dmgtime = gpGlobals->time + GetPulseInterval(); - } - timedist = ( pev->dmgtime - gpGlobals->time ) / GetPulseInterval(); - break; - - case FIRE_WIDE: - if ( pev->dmgtime < gpGlobals->time ) - { - // wide mode does damage to the ent, and radius damage - ClearMultiDamage(); - if (pEntity->pev->takedamage) - { - pEntity->TraceAttack( m_pPlayer->pev, gSkillData.plrDmgEgonWide, vecDir, &tr, DMG_ENERGYBEAM | DMG_ALWAYSGIB); - } - ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev); - - if ( g_pGameRules->IsMultiplayer() ) - { - // radius damage a little more potent in multiplayer. - ::RadiusDamage( tr.vecEndPos, pev, m_pPlayer->pev, gSkillData.plrDmgEgonWide/4, 128, CLASS_NONE, DMG_ENERGYBEAM | DMG_BLAST | DMG_ALWAYSGIB ); - } - - if ( !m_pPlayer->IsAlive() ) - return; - - if ( g_pGameRules->IsMultiplayer() ) - { - //multiplayer uses 5 ammo/second - if ( gpGlobals->time >= m_flAmmoUseTime ) - { - UseAmmo( 1 ); - m_flAmmoUseTime = gpGlobals->time + 0.2; - } - } - else - { - // Wide mode uses 10 charges per second in single player - if ( gpGlobals->time >= m_flAmmoUseTime ) - { - UseAmmo( 1 ); - m_flAmmoUseTime = gpGlobals->time + 0.1; - } - } - - pev->dmgtime = gpGlobals->time + GetDischargeInterval(); - if ( m_shakeTime < gpGlobals->time ) - { - UTIL_ScreenShake( tr.vecEndPos, 5.0, 150.0, 0.75, 250.0 ); - m_shakeTime = gpGlobals->time + 1.5; - } - } - timedist = ( pev->dmgtime - gpGlobals->time ) / GetDischargeInterval(); - break; - } - - if ( timedist < 0 ) - timedist = 0; - else if ( timedist > 1 ) - timedist = 1; - timedist = 1-timedist; - - UpdateEffect( tmpSrc, tr.vecEndPos, timedist ); -} - - -void CEgon::UpdateEffect( const Vector &startPoint, const Vector &endPoint, float timeBlend ) -{ - if ( !m_pBeam ) - { - CreateEffect(); - } - - m_pBeam->SetStartPos( endPoint ); - m_pBeam->SetBrightness( 255 - (timeBlend*180) ); - m_pBeam->SetWidth( 40 - (timeBlend*20) ); - - if ( m_fireMode == FIRE_WIDE ) - m_pBeam->SetColor( 30 + (25*timeBlend), 30 + (30*timeBlend), 64 + 80*fabs(sin(gpGlobals->time*10)) ); - else - m_pBeam->SetColor( 60 + (25*timeBlend), 120 + (30*timeBlend), 64 + 80*fabs(sin(gpGlobals->time*10)) ); - - - UTIL_SetOrigin( m_pSprite->pev, endPoint ); - m_pSprite->pev->frame += 8 * gpGlobals->frametime; - if ( m_pSprite->pev->frame > m_pSprite->Frames() ) - m_pSprite->pev->frame = 0; - - m_pNoise->SetStartPos( endPoint ); -} - - -void CEgon::CreateEffect( void ) -{ - DestroyEffect(); - - m_pBeam = CBeam::BeamCreate( EGON_BEAM_SPRITE, 40 ); - m_pBeam->PointEntInit( pev->origin, m_pPlayer->entindex() ); - m_pBeam->SetFlags( BEAM_FSINE ); - m_pBeam->SetEndAttachment( 1 ); - m_pBeam->pev->spawnflags |= SF_BEAM_TEMPORARY; // Flag these to be destroyed on save/restore or level transition - - m_pNoise = CBeam::BeamCreate( EGON_BEAM_SPRITE, 55 ); - m_pNoise->PointEntInit( pev->origin, m_pPlayer->entindex() ); - m_pNoise->SetScrollRate( 25 ); - m_pNoise->SetBrightness( 100 ); - m_pNoise->SetEndAttachment( 1 ); - m_pNoise->pev->spawnflags |= SF_BEAM_TEMPORARY; - - m_pSprite = CSprite::SpriteCreate( EGON_FLARE_SPRITE, pev->origin, FALSE ); - m_pSprite->pev->scale = 1.0; - m_pSprite->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation ); - m_pSprite->pev->spawnflags |= SF_SPRITE_TEMPORARY; - - if ( m_fireMode == FIRE_WIDE ) - { - m_pBeam->SetScrollRate( 50 ); - m_pBeam->SetNoise( 20 ); - m_pNoise->SetColor( 50, 50, 255 ); - m_pNoise->SetNoise( 8 ); - } - else - { - m_pBeam->SetScrollRate( 110 ); - m_pBeam->SetNoise( 5 ); - m_pNoise->SetColor( 80, 120, 255 ); - m_pNoise->SetNoise( 2 ); - } -} - - -void CEgon::DestroyEffect( void ) -{ - if ( m_pBeam ) - { - UTIL_Remove( m_pBeam ); - m_pBeam = NULL; - } - if ( m_pNoise ) - { - UTIL_Remove( m_pNoise ); - m_pNoise = NULL; - } - if ( m_pSprite ) - { - if ( m_fireMode == FIRE_WIDE ) - m_pSprite->Expand( 10, 500 ); - else - UTIL_Remove( m_pSprite ); - m_pSprite = NULL; - } -} - - -void CEgon::WeaponIdle( void ) -{ - ResetEmptySound( ); - - if ( m_flTimeWeaponIdle > gpGlobals->time ) - return; - - if ( m_fireState != FIRE_OFF ) - EndAttack(); - - - int iAnim; - - float flRand = RANDOM_FLOAT(0,1); - - if ( flRand <= 0.5 ) - { - iAnim = EGON_IDLE1; - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10,15); - } - else - { - iAnim = EGON_FIDGET1; - m_flTimeWeaponIdle = gpGlobals->time + 3; - } - - SendWeaponAnim( iAnim ); - m_deployed = TRUE; -} - - - -void CEgon::EndAttack( void ) -{ - STOP_SOUND( ENT(m_pPlayer->pev), CHAN_STATIC, EGON_SOUND_RUN ); - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, EGON_SOUND_OFF, 0.98, ATTN_NORM, 0, 100); - m_fireState = FIRE_OFF; - m_flTimeWeaponIdle = gpGlobals->time + 2.0; - m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->time + 0.5; - DestroyEffect(); -} - - - -class CEgonAmmo : public CBasePlayerAmmo -{ - void Spawn( void ) - { - Precache( ); - SET_MODEL(ENT(pev), "models/w_chainammo.mdl"); - CBasePlayerAmmo::Spawn( ); - } - void Precache( void ) - { - PRECACHE_MODEL ("models/w_chainammo.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - } - BOOL AddAmmo( CBaseEntity *pOther ) - { - if (pOther->GiveAmmo( AMMO_URANIUMBOX_GIVE, "uranium", URANIUM_MAX_CARRY ) != -1) - { - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); - return TRUE; - } - return FALSE; - } -}; -LINK_ENTITY_TO_CLASS( ammo_egonclip, CEgonAmmo ); - -#endif \ No newline at end of file diff --git a/dlls/Half-life/flyingmonster.cpp b/dlls/Half-life/flyingmonster.cpp deleted file mode 100644 index 50edc9f2..00000000 --- a/dlls/Half-life/flyingmonster.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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 "schedule.h" -#include "flyingmonster.h" - -#define FLYING_AE_FLAP (8) -#define FLYING_AE_FLAPSOUND (9) - -extern DLL_GLOBAL edict_t *g_pBodyQueueHead; - -int CFlyingMonster ::CheckLocalMove(const Vector &vecStart, const Vector &vecEnd, CBaseEntity *pTarget, float *pflDist) -{ - // UNDONE: need to check more than the endpoint - if (FBitSet(pev->flags, FL_SWIM) && (UTIL_PointContents(vecEnd) != CONTENTS_WATER)) - { - // ALERT(at_aiconsole, "can't swim out of water\n"); - return FALSE; - } - - TraceResult tr; - - UTIL_TraceHull(vecStart + Vector(0, 0, 32), vecEnd + Vector(0, 0, 32), dont_ignore_monsters, large_hull, edict(), &tr); - - // ALERT( at_console, "%.0f %.0f %.0f : ", vecStart.x, vecStart.y, vecStart.z ); - // ALERT( at_console, "%.0f %.0f %.0f\n", vecEnd.x, vecEnd.y, vecEnd.z ); - - if (pflDist) - { - *pflDist = ((tr.vecEndPos - Vector(0, 0, 32)) - vecStart).Length(); // get the distance. - } - - // ALERT( at_console, "check %d %d %f\n", tr.fStartSolid, tr.fAllSolid, tr.flFraction ); - if (tr.fStartSolid || tr.flFraction < 1.0) - { - if (pTarget && pTarget->edict() == gpGlobals->trace_ent) - return LOCALMOVE_VALID; - return LOCALMOVE_INVALID; - } - - return LOCALMOVE_VALID; -} - -BOOL CFlyingMonster ::FTriangulate(const Vector &vecStart, const Vector &vecEnd, float flDist, CBaseEntity *pTargetEnt, Vector *pApex) -{ - return CBaseMonster::FTriangulate(vecStart, vecEnd, flDist, pTargetEnt, pApex); -} - -Activity CFlyingMonster ::GetStoppedActivity(void) -{ - if (pev->movetype != MOVETYPE_FLY) // UNDONE: Ground idle here, IDLE may be something else - return ACT_IDLE; - - return ACT_HOVER; -} - -void CFlyingMonster ::Stop(void) -{ - Activity stopped = GetStoppedActivity(); - if (m_IdealActivity != stopped) - { - m_flightSpeed = 0; - m_IdealActivity = stopped; - } - pev->angles.z = 0; - pev->angles.x = 0; - m_vecTravel = g_vecZero; -} - -float CFlyingMonster ::ChangeYaw(int speed) -{ - if (pev->movetype == MOVETYPE_FLY) - { - float diff = FlYawDiff(); - float target = 0; - - if (m_IdealActivity != GetStoppedActivity()) - { - if (diff < -20) - target = 90; - else if (diff > 20) - target = -90; - } - pev->angles.z = UTIL_Approach(target, pev->angles.z, 220.0 * gpGlobals->frametime); - } - return CBaseMonster::ChangeYaw(speed); -} - -void CFlyingMonster ::Killed(entvars_t *pevAttacker, int iGib) -{ - pev->movetype = MOVETYPE_STEP; - ClearBits(pev->flags, FL_ONGROUND); - pev->angles.z = 0; - pev->angles.x = 0; - CBaseMonster::Killed(pevAttacker, iGib); -} - -void CFlyingMonster ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case FLYING_AE_FLAP: - m_flightSpeed = 400; - break; - - case FLYING_AE_FLAPSOUND: - if (m_pFlapSound) - EMIT_SOUND(edict(), CHAN_BODY, m_pFlapSound, 1, ATTN_NORM); - break; - - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -void CFlyingMonster ::Move(float flInterval) -{ - if (pev->movetype == MOVETYPE_FLY) - m_flGroundSpeed = m_flightSpeed; - CBaseMonster::Move(flInterval); -} - -BOOL CFlyingMonster::ShouldAdvanceRoute(float flWaypointDist) -{ - // Get true 3D distance to the goal so we actually reach the correct height - if (m_Route[m_iRouteIndex].iType & bits_MF_IS_GOAL) - flWaypointDist = (m_Route[m_iRouteIndex].vecLocation - pev->origin).Length(); - - if (flWaypointDist <= 64 + (m_flGroundSpeed * gpGlobals->frametime)) - return TRUE; - - return FALSE; -} - -void CFlyingMonster::MoveExecute(CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval) -{ - if (pev->movetype == MOVETYPE_FLY) - { - if (gpGlobals->time - m_stopTime > 1.0) - { - if (m_IdealActivity != m_movementActivity) - { - m_IdealActivity = m_movementActivity; - m_flGroundSpeed = m_flightSpeed = 200; - } - } - Vector vecMove = pev->origin + ((vecDir + (m_vecTravel * m_momentum)).Normalize() * (m_flGroundSpeed * flInterval)); - - if (m_IdealActivity != m_movementActivity) - { - m_flightSpeed = UTIL_Approach(100, m_flightSpeed, 75 * gpGlobals->frametime); - if (m_flightSpeed < 100) - m_stopTime = gpGlobals->time; - } - else - m_flightSpeed = UTIL_Approach(20, m_flightSpeed, 300 * gpGlobals->frametime); - - if (CheckLocalMove(pev->origin, vecMove, pTargetEnt, NULL)) - { - m_vecTravel = (vecMove - pev->origin); - m_vecTravel = m_vecTravel.Normalize(); - UTIL_MoveToOrigin(ENT(pev), vecMove, (m_flGroundSpeed * flInterval), MOVE_STRAFE); - } - else - { - m_IdealActivity = GetStoppedActivity(); - m_stopTime = gpGlobals->time; - m_vecTravel = g_vecZero; - } - } - else - CBaseMonster::MoveExecute(pTargetEnt, vecDir, flInterval); -} - -float CFlyingMonster::CeilingZ(const Vector &position) -{ - TraceResult tr; - - Vector minUp = position; - Vector maxUp = position; - maxUp.z += 4096.0; - - UTIL_TraceLine(position, maxUp, ignore_monsters, NULL, &tr); - if (tr.flFraction != 1.0) - maxUp.z = tr.vecEndPos.z; - - if ((pev->flags) & FL_SWIM) - { - return UTIL_WaterLevel(position, minUp.z, maxUp.z); - } - return maxUp.z; -} - -BOOL CFlyingMonster::ProbeZ(const Vector &position, const Vector &probe, float *pFraction) -{ - int conPosition = UTIL_PointContents(position); - if ((((pev->flags) & FL_SWIM) == FL_SWIM) ^ (conPosition == CONTENTS_WATER)) - { - // SWIMING & !WATER - // or FLYING & WATER - // - *pFraction = 0.0; - return TRUE; // We hit a water boundary because we are where we don't belong. - } - int conProbe = UTIL_PointContents(probe); - if (conProbe == conPosition) - { - // The probe is either entirely inside the water (for fish) or entirely - // outside the water (for birds). - // - *pFraction = 1.0; - return FALSE; - } - - Vector ProbeUnit = (probe - position).Normalize(); - float ProbeLength = (probe - position).Length(); - float maxProbeLength = ProbeLength; - float minProbeLength = 0; - - float diff = maxProbeLength - minProbeLength; - while (diff > 1.0) - { - float midProbeLength = minProbeLength + diff / 2.0; - Vector midProbeVec = midProbeLength * ProbeUnit; - if (UTIL_PointContents(position + midProbeVec) == conPosition) - { - minProbeLength = midProbeLength; - } - else - { - maxProbeLength = midProbeLength; - } - diff = maxProbeLength - minProbeLength; - } - *pFraction = minProbeLength / ProbeLength; - - return TRUE; -} - -float CFlyingMonster::FloorZ(const Vector &position) -{ - TraceResult tr; - - Vector down = position; - down.z -= 2048; - - UTIL_TraceLine(position, down, ignore_monsters, NULL, &tr); - - if (tr.flFraction != 1.0) - return tr.vecEndPos.z; - - return down.z; -} diff --git a/dlls/Half-life/flyingmonster.h b/dlls/Half-life/flyingmonster.h deleted file mode 100644 index 24cd8052..00000000 --- a/dlls/Half-life/flyingmonster.h +++ /dev/null @@ -1,50 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -// Base class for flying monsters. This overrides the movement test & execution code from CBaseMonster - -#ifndef FLYINGMONSTER_H -#define FLYINGMONSTER_H - -class CFlyingMonster : public CBaseMonster -{ -public: - int CheckLocalMove(const Vector &vecStart, const Vector &vecEnd, CBaseEntity *pTarget, float *pflDist); // check validity of a straight move through space - BOOL FTriangulate(const Vector &vecStart, const Vector &vecEnd, float flDist, CBaseEntity *pTargetEnt, Vector *pApex); - Activity GetStoppedActivity(void); - void Killed(entvars_t *pevAttacker, int iGib); - void Stop(void); - float ChangeYaw(int speed); - void HandleAnimEvent(MonsterEvent_t *pEvent); - void MoveExecute(CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval); - void Move(float flInterval = 0.1); - BOOL ShouldAdvanceRoute(float flWaypointDist); - - inline void SetFlyingMomentum(float momentum) { m_momentum = momentum; } - inline void SetFlyingFlapSound(const char *pFlapSound) { m_pFlapSound = pFlapSound; } - inline void SetFlyingSpeed(float speed) { m_flightSpeed = speed; } - float CeilingZ(const Vector &position); - float FloorZ(const Vector &position); - BOOL ProbeZ(const Vector &position, const Vector &probe, float *pFraction); - - // UNDONE: Save/restore this stuff!!! -protected: - Vector m_vecTravel; // Current direction - float m_flightSpeed; // Current flight speed (decays when not flapping or gliding) - float m_stopTime; // Last time we stopped (to avoid switching states too soon) - float m_momentum; // Weight for desired vs. momentum velocity - const char *m_pFlapSound; -}; - -#endif //FLYINGMONSTER_H diff --git a/dlls/Half-life/gargantua.cpp b/dlls/Half-life/gargantua.cpp deleted file mode 100644 index 5af54808..00000000 --- a/dlls/Half-life/gargantua.cpp +++ /dev/null @@ -1,1317 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -#ifndef OEM_BUILD - -//========================================================= -// Gargantua -//========================================================= -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "nodes.h" -#include "monsters.h" -#include "schedule.h" -#include "customentity.h" -#include "weapons.h" -#include "effects.h" -#include "soundent.h" -#include "decals.h" -#include "explode.h" -#include "func_break.h" - -//========================================================= -// Gargantua Monster -//========================================================= -const float GARG_ATTACKDIST = 80.0; - -// Garg animation events -#define GARG_AE_SLASH_LEFT 1 -//#define GARG_AE_BEAM_ATTACK_RIGHT 2 // No longer used -#define GARG_AE_LEFT_FOOT 3 -#define GARG_AE_RIGHT_FOOT 4 -#define GARG_AE_STOMP 5 -#define GARG_AE_BREATHE 6 - -// Gargantua is immune to any damage but this -#define GARG_DAMAGE (DMG_ENERGYBEAM | DMG_CRUSH | DMG_MORTAR | DMG_BLAST) -#define GARG_EYE_SPRITE_NAME "sprites/gargeye1.spr" -#define GARG_BEAM_SPRITE_NAME "sprites/xbeam3.spr" -#define GARG_BEAM_SPRITE2 "sprites/xbeam3.spr" -#define GARG_STOMP_SPRITE_NAME "sprites/gargeye1.spr" -#define GARG_STOMP_BUZZ_SOUND "weapons/mine_charge.wav" -#define GARG_FLAME_LENGTH 330 -#define GARG_GIB_MODEL "models/metalplategibs.mdl" - -#define ATTN_GARG (ATTN_NORM) - -#define STOMP_SPRITE_COUNT 10 - -int gStompSprite = 0, gGargGibModel = 0; -void SpawnExplosion(Vector center, float randomRange, float time, int magnitude); - -class CSmoker; - -// Spiral Effect -class CSpiral : public CBaseEntity -{ -public: - void Spawn(void); - void Think(void); - int ObjectCaps(void) { return FCAP_DONT_SAVE; } - static CSpiral *Create(const Vector &origin, float height, float radius, float duration); -}; -LINK_ENTITY_TO_CLASS(streak_spiral, CSpiral); - -class CStomp : public CBaseEntity -{ -public: - void Spawn(void); - void Think(void); - static CStomp *StompCreate(const Vector &origin, const Vector &end, float speed); - -private: - // UNDONE: re-use this sprite list instead of creating new ones all the time - // CSprite *m_pSprites[ STOMP_SPRITE_COUNT ]; -}; - -LINK_ENTITY_TO_CLASS(garg_stomp, CStomp); -CStomp *CStomp::StompCreate(const Vector &origin, const Vector &end, float speed) -{ - CStomp *pStomp = GetClassPtr((CStomp *)NULL); - - pStomp->pev->origin = origin; - Vector dir = (end - origin); - pStomp->pev->scale = dir.Length(); - pStomp->pev->movedir = dir.Normalize(); - pStomp->pev->speed = speed; - pStomp->Spawn(); - - return pStomp; -} - -void CStomp::Spawn(void) -{ - pev->nextthink = gpGlobals->time; - pev->classname = MAKE_STRING("garg_stomp"); - pev->dmgtime = gpGlobals->time; - - pev->framerate = 30; - pev->model = MAKE_STRING(GARG_STOMP_SPRITE_NAME); - pev->rendermode = kRenderTransTexture; - pev->renderamt = 0; - EMIT_SOUND_DYN(edict(), CHAN_BODY, GARG_STOMP_BUZZ_SOUND, 1, ATTN_NORM, 0, PITCH_NORM * 0.55); -} - -#define STOMP_INTERVAL 0.025 - -void CStomp::Think(void) -{ - TraceResult tr; - - pev->nextthink = gpGlobals->time + 0.1; - - // Do damage for this frame - Vector vecStart = pev->origin; - vecStart.z += 30; - Vector vecEnd = vecStart + (pev->movedir * pev->speed * gpGlobals->frametime); - - UTIL_TraceHull(vecStart, vecEnd, dont_ignore_monsters, head_hull, ENT(pev), &tr); - - if (tr.pHit && tr.pHit != pev->owner) - { - CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); - entvars_t *pevOwner = pev; - if (pev->owner) - pevOwner = VARS(pev->owner); - - if (pEntity) - pEntity->TakeDamage(pev, pevOwner, gSkillData.gargantuaDmgStomp, DMG_SONIC); - } - - // Accelerate the effect - pev->speed = pev->speed + (gpGlobals->frametime) * pev->framerate; - pev->framerate = pev->framerate + (gpGlobals->frametime) * 1500; - - // Move and spawn trails - while (gpGlobals->time - pev->dmgtime > STOMP_INTERVAL) - { - pev->origin = pev->origin + pev->movedir * pev->speed * STOMP_INTERVAL; - for (int i = 0; i < 2; i++) - { - CSprite *pSprite = CSprite::SpriteCreate(GARG_STOMP_SPRITE_NAME, pev->origin, TRUE); - if (pSprite) - { - UTIL_TraceLine(pev->origin, pev->origin - Vector(0, 0, 500), ignore_monsters, edict(), &tr); - pSprite->pev->origin = tr.vecEndPos; - pSprite->pev->velocity = Vector(RANDOM_FLOAT(-200, 200), RANDOM_FLOAT(-200, 200), 175); - // pSprite->AnimateAndDie( RANDOM_FLOAT( 8.0, 12.0 ) ); - pSprite->pev->nextthink = gpGlobals->time + 0.3; - pSprite->SetThink(SUB_Remove); - pSprite->SetTransparency(kRenderTransAdd, 255, 255, 255, 255, kRenderFxFadeFast); - } - } - pev->dmgtime += STOMP_INTERVAL; - // Scale has the "life" of this effect - pev->scale -= STOMP_INTERVAL * pev->speed; - if (pev->scale <= 0) - { - // Life has run out - UTIL_Remove(this); - STOP_SOUND(edict(), CHAN_BODY, GARG_STOMP_BUZZ_SOUND); - } - } -} - -void StreakSplash(const Vector &origin, const Vector &direction, int color, int count, int speed, int velocityRange) -{ - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, origin); - WRITE_BYTE(TE_STREAK_SPLASH); - WRITE_COORD(origin.x); // origin - WRITE_COORD(origin.y); - WRITE_COORD(origin.z); - WRITE_COORD(direction.x); // direction - WRITE_COORD(direction.y); - WRITE_COORD(direction.z); - WRITE_BYTE(color); // Streak color 6 - WRITE_SHORT(count); // count - WRITE_SHORT(speed); - WRITE_SHORT(velocityRange); // Random velocity modifier - MESSAGE_END(); -} - -class CGargantua : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int Classify(void); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - void HandleAnimEvent(MonsterEvent_t *pEvent); - - BOOL CheckMeleeAttack1(float flDot, float flDist); // Swipe - BOOL CheckMeleeAttack2(float flDot, float flDist); // Flames - BOOL CheckRangeAttack1(float flDot, float flDist); // Stomp attack - void SetObjectCollisionBox(void) - { - pev->absmin = pev->origin + Vector(-80, -80, 0); - pev->absmax = pev->origin + Vector(80, 80, 214); - } - - Schedule_t *GetScheduleOfType(int Type); - void StartTask(Task_t *pTask); - void RunTask(Task_t *pTask); - - void PrescheduleThink(void); - - void Killed(entvars_t *pevAttacker, int iGib); - void DeathEffect(void); - - void EyeOff(void); - void EyeOn(int level); - void EyeUpdate(void); - void Leap(void); - void StompAttack(void); - void FlameCreate(void); - void FlameUpdate(void); - void FlameControls(float angleX, float angleY); - void FlameDestroy(void); - inline BOOL FlameIsOn(void) { return m_pFlame[0] != NULL; } - - void FlameDamage(Vector vecStart, Vector vecEnd, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - CUSTOM_SCHEDULES; - -private: - static const char *pAttackHitSounds[]; - static const char *pBeamAttackSounds[]; - static const char *pAttackMissSounds[]; - static const char *pRicSounds[]; - static const char *pFootSounds[]; - static const char *pIdleSounds[]; - static const char *pAlertSounds[]; - static const char *pPainSounds[]; - static const char *pAttackSounds[]; - static const char *pStompSounds[]; - static const char *pBreatheSounds[]; - - CBaseEntity *GargantuaCheckTraceHullAttack(float flDist, int iDamage, int iDmgType); - - CSprite *m_pEyeGlow; // Glow around the eyes - CBeam *m_pFlame[4]; // Flame beams - - int m_eyeBrightness; // Brightness target - float m_seeTime; // Time to attack (when I see the enemy, I set this) - float m_flameTime; // Time of next flame attack - float m_painSoundTime; // Time of next pain sound - float m_streakTime; // streak timer (don't send too many) - float m_flameX; // Flame thrower aim - float m_flameY; -}; - -LINK_ENTITY_TO_CLASS(monster_gargantua, CGargantua); - -TYPEDESCRIPTION CGargantua::m_SaveData[] = - { - DEFINE_FIELD(CGargantua, m_pEyeGlow, FIELD_CLASSPTR), - DEFINE_FIELD(CGargantua, m_eyeBrightness, FIELD_INTEGER), - DEFINE_FIELD(CGargantua, m_seeTime, FIELD_TIME), - DEFINE_FIELD(CGargantua, m_flameTime, FIELD_TIME), - DEFINE_FIELD(CGargantua, m_streakTime, FIELD_TIME), - DEFINE_FIELD(CGargantua, m_painSoundTime, FIELD_TIME), - DEFINE_ARRAY(CGargantua, m_pFlame, FIELD_CLASSPTR, 4), - DEFINE_FIELD(CGargantua, m_flameX, FIELD_FLOAT), - DEFINE_FIELD(CGargantua, m_flameY, FIELD_FLOAT), -}; - -IMPLEMENT_SAVERESTORE(CGargantua, CBaseMonster); - -const char *CGargantua::pAttackHitSounds[] = - { - "zombie/claw_strike1.wav", - "zombie/claw_strike2.wav", - "zombie/claw_strike3.wav", -}; - -const char *CGargantua::pBeamAttackSounds[] = - { - "garg/gar_flameoff1.wav", - "garg/gar_flameon1.wav", - "garg/gar_flamerun1.wav", -}; - -const char *CGargantua::pAttackMissSounds[] = - { - "zombie/claw_miss1.wav", - "zombie/claw_miss2.wav", -}; - -const char *CGargantua::pRicSounds[] = - { -#if 0 - "weapons/ric1.wav", - "weapons/ric2.wav", - "weapons/ric3.wav", - "weapons/ric4.wav", - "weapons/ric5.wav", -#else - "debris/metal4.wav", - "debris/metal6.wav", - "weapons/ric4.wav", - "weapons/ric5.wav", -#endif -}; - -const char *CGargantua::pFootSounds[] = - { - "garg/gar_step1.wav", - "garg/gar_step2.wav", -}; - -const char *CGargantua::pIdleSounds[] = - { - "garg/gar_idle1.wav", - "garg/gar_idle2.wav", - "garg/gar_idle3.wav", - "garg/gar_idle4.wav", - "garg/gar_idle5.wav", -}; - -const char *CGargantua::pAttackSounds[] = - { - "garg/gar_attack1.wav", - "garg/gar_attack2.wav", - "garg/gar_attack3.wav", -}; - -const char *CGargantua::pAlertSounds[] = - { - "garg/gar_alert1.wav", - "garg/gar_alert2.wav", - "garg/gar_alert3.wav", -}; - -const char *CGargantua::pPainSounds[] = - { - "garg/gar_pain1.wav", - "garg/gar_pain2.wav", - "garg/gar_pain3.wav", -}; - -const char *CGargantua::pStompSounds[] = - { - "garg/gar_stomp1.wav", -}; - -const char *CGargantua::pBreatheSounds[] = - { - "garg/gar_breathe1.wav", - "garg/gar_breathe2.wav", - "garg/gar_breathe3.wav", -}; -//========================================================= -// AI Schedules Specific to this monster -//========================================================= -#if 0 -enum -{ - SCHED_ = LAST_COMMON_SCHEDULE + 1, -}; -#endif - -enum -{ - TASK_SOUND_ATTACK = LAST_COMMON_TASK + 1, - TASK_FLAME_SWEEP, -}; - -Task_t tlGargFlame[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_SOUND_ATTACK, (float)0}, - // { TASK_PLAY_SEQUENCE, (float)ACT_SIGNAL1 }, - {TASK_SET_ACTIVITY, (float)ACT_MELEE_ATTACK2}, - {TASK_FLAME_SWEEP, (float)4.5}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, -}; - -Schedule_t slGargFlame[] = - { - {tlGargFlame, - ARRAYSIZE(tlGargFlame), - 0, - 0, - "GargFlame"}, -}; - -// primary melee attack -Task_t tlGargSwipe[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_MELEE_ATTACK1, (float)0}, -}; - -Schedule_t slGargSwipe[] = - { - {tlGargSwipe, - ARRAYSIZE(tlGargSwipe), - bits_COND_CAN_MELEE_ATTACK2, - 0, - "GargSwipe"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CGargantua){ - slGargFlame, - slGargSwipe, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CGargantua, CBaseMonster); - -void CGargantua::EyeOn(int level) -{ - m_eyeBrightness = level; -} - -void CGargantua::EyeOff(void) -{ - m_eyeBrightness = 0; -} - -void CGargantua::EyeUpdate(void) -{ - if (m_pEyeGlow) - { - m_pEyeGlow->pev->renderamt = UTIL_Approach(m_eyeBrightness, m_pEyeGlow->pev->renderamt, 26); - if (m_pEyeGlow->pev->renderamt == 0) - m_pEyeGlow->pev->effects |= EF_NODRAW; - else - m_pEyeGlow->pev->effects &= ~EF_NODRAW; - UTIL_SetOrigin(m_pEyeGlow->pev, pev->origin); - } -} - -void CGargantua::StompAttack(void) -{ - TraceResult trace; - - UTIL_MakeVectors(pev->angles); - Vector vecStart = pev->origin + Vector(0, 0, 60) + 35 * gpGlobals->v_forward; - Vector vecAim = ShootAtEnemy(vecStart); - Vector vecEnd = (vecAim * 1024) + vecStart; - - UTIL_TraceLine(vecStart, vecEnd, ignore_monsters, edict(), &trace); - CStomp::StompCreate(vecStart, trace.vecEndPos, 0); - UTIL_ScreenShake(pev->origin, 12.0, 100.0, 2.0, 1000); - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, pStompSounds[RANDOM_LONG(0, ARRAYSIZE(pStompSounds) - 1)], 1.0, ATTN_GARG, 0, PITCH_NORM + RANDOM_LONG(-10, 10)); - - UTIL_TraceLine(pev->origin, pev->origin - Vector(0, 0, 20), ignore_monsters, edict(), &trace); - if (trace.flFraction < 1.0) - UTIL_DecalTrace(&trace, DECAL_GARGSTOMP1); -} - -void CGargantua ::FlameCreate(void) -{ - int i; - Vector posGun, angleGun; - TraceResult trace; - - UTIL_MakeVectors(pev->angles); - - for (i = 0; i < 4; i++) - { - if (i < 2) - m_pFlame[i] = CBeam::BeamCreate(GARG_BEAM_SPRITE_NAME, 240); - else - m_pFlame[i] = CBeam::BeamCreate(GARG_BEAM_SPRITE2, 140); - if (m_pFlame[i]) - { - int attach = i % 2; - // attachment is 0 based in GetAttachment - GetAttachment(attach + 1, posGun, angleGun); - - Vector vecEnd = (gpGlobals->v_forward * GARG_FLAME_LENGTH) + posGun; - UTIL_TraceLine(posGun, vecEnd, dont_ignore_monsters, edict(), &trace); - - m_pFlame[i]->PointEntInit(trace.vecEndPos, entindex()); - if (i < 2) - m_pFlame[i]->SetColor(255, 130, 90); - else - m_pFlame[i]->SetColor(0, 120, 255); - m_pFlame[i]->SetBrightness(190); - m_pFlame[i]->SetFlags(BEAM_FSHADEIN); - m_pFlame[i]->SetScrollRate(20); - // attachment is 1 based in SetEndAttachment - m_pFlame[i]->SetEndAttachment(attach + 2); - CSoundEnt::InsertSound(bits_SOUND_COMBAT, posGun, 384, 0.3); - } - } - EMIT_SOUND_DYN(edict(), CHAN_BODY, pBeamAttackSounds[1], 1.0, ATTN_NORM, 0, PITCH_NORM); - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, pBeamAttackSounds[2], 1.0, ATTN_NORM, 0, PITCH_NORM); -} - -void CGargantua ::FlameControls(float angleX, float angleY) -{ - if (angleY < -180) - angleY += 360; - else if (angleY > 180) - angleY -= 360; - - if (angleY < -45) - angleY = -45; - else if (angleY > 45) - angleY = 45; - - m_flameX = UTIL_ApproachAngle(angleX, m_flameX, 4); - m_flameY = UTIL_ApproachAngle(angleY, m_flameY, 8); - SetBoneController(0, m_flameY); - SetBoneController(1, m_flameX); -} - -void CGargantua ::FlameUpdate(void) -{ - int i; - static float offset[2] = {60, -60}; - TraceResult trace; - Vector vecStart, angleGun; - BOOL streaks = FALSE; - - for (i = 0; i < 2; i++) - { - if (m_pFlame[i]) - { - Vector vecAim = pev->angles; - vecAim.x += m_flameX; - vecAim.y += m_flameY; - - UTIL_MakeVectors(vecAim); - - GetAttachment(i + 1, vecStart, angleGun); - Vector vecEnd = vecStart + (gpGlobals->v_forward * GARG_FLAME_LENGTH); // - offset[i] * gpGlobals->v_right; - - UTIL_TraceLine(vecStart, vecEnd, dont_ignore_monsters, edict(), &trace); - - m_pFlame[i]->SetStartPos(trace.vecEndPos); - m_pFlame[i + 2]->SetStartPos((vecStart * 0.6) + (trace.vecEndPos * 0.4)); - - if (trace.flFraction != 1.0 && gpGlobals->time > m_streakTime) - { - StreakSplash(trace.vecEndPos, trace.vecPlaneNormal, 6, 20, 50, 400); - streaks = TRUE; - UTIL_DecalTrace(&trace, DECAL_SMALLSCORCH1 + RANDOM_LONG(0, 2)); - } - // RadiusDamage( trace.vecEndPos, pev, pev, gSkillData.gargantuaDmgFire, CLASS_ALIEN_MONSTER, DMG_BURN ); - FlameDamage(vecStart, trace.vecEndPos, pev, pev, gSkillData.gargantuaDmgFire, CLASS_ALIEN_MONSTER, DMG_BURN); - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex() + 0x1000 * (i + 2)); // entity, attachment - WRITE_COORD(vecStart.x); // origin - WRITE_COORD(vecStart.y); - WRITE_COORD(vecStart.z); - WRITE_COORD(RANDOM_FLOAT(32, 48)); // radius - WRITE_BYTE(255); // R - WRITE_BYTE(255); // G - WRITE_BYTE(255); // B - WRITE_BYTE(2); // life * 10 - WRITE_COORD(0); // decay - MESSAGE_END(); - } - } - if (streaks) - m_streakTime = gpGlobals->time; -} - -void CGargantua ::FlameDamage(Vector vecStart, Vector vecEnd, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType) -{ - CBaseEntity *pEntity = NULL; - TraceResult tr; - float flAdjustedDamage; - Vector vecSpot; - - Vector vecMid = (vecStart + vecEnd) * 0.5; - - float searchRadius = (vecStart - vecMid).Length(); - - Vector vecAim = (vecEnd - vecStart).Normalize(); - - // iterate on all entities in the vicinity. - while ((pEntity = UTIL_FindEntityInSphere(pEntity, vecMid, searchRadius)) != NULL) - { - if (pEntity->pev->takedamage != DAMAGE_NO) - { - // UNDONE: this should check a damage mask, not an ignore - if (iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore) - { // houndeyes don't hurt other houndeyes with their attack - continue; - } - - vecSpot = pEntity->BodyTarget(vecMid); - - float dist = DotProduct(vecAim, vecSpot - vecMid); - if (dist > searchRadius) - dist = searchRadius; - else if (dist < -searchRadius) - dist = searchRadius; - - Vector vecSrc = vecMid + dist * vecAim; - - UTIL_TraceLine(vecSrc, vecSpot, dont_ignore_monsters, ENT(pev), &tr); - - if (tr.flFraction == 1.0 || tr.pHit == pEntity->edict()) - { // the explosion can 'see' this entity, so hurt them! - // decrease damage for an ent that's farther from the flame. - dist = (vecSrc - tr.vecEndPos).Length(); - - if (dist > 64) - { - flAdjustedDamage = flDamage - (dist - 64) * 0.4; - if (flAdjustedDamage <= 0) - continue; - } - else - { - flAdjustedDamage = flDamage; - } - - // ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) ); - if (tr.flFraction != 1.0) - { - ClearMultiDamage(); - pEntity->TraceAttack(pevInflictor, flAdjustedDamage, (tr.vecEndPos - vecSrc).Normalize(), &tr, bitsDamageType); - ApplyMultiDamage(pevInflictor, pevAttacker); - } - else - { - pEntity->TakeDamage(pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType); - } - } - } - } -} - -void CGargantua ::FlameDestroy(void) -{ - int i; - - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, pBeamAttackSounds[0], 1.0, ATTN_NORM, 0, PITCH_NORM); - for (i = 0; i < 4; i++) - { - if (m_pFlame[i]) - { - UTIL_Remove(m_pFlame[i]); - m_pFlame[i] = NULL; - } - } -} - -void CGargantua ::PrescheduleThink(void) -{ - if (!HasConditions(bits_COND_SEE_ENEMY)) - { - m_seeTime = gpGlobals->time + 5; - EyeOff(); - } - else - EyeOn(200); - - EyeUpdate(); -} - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CGargantua ::Classify(void) -{ - return CLASS_ALIEN_MONSTER; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CGargantua ::SetYawSpeed(void) -{ - int ys; - - switch (m_Activity) - { - case ACT_IDLE: - ys = 60; - break; - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - ys = 180; - break; - case ACT_WALK: - case ACT_RUN: - ys = 60; - break; - - default: - ys = 60; - break; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// Spawn -//========================================================= -void CGargantua ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/garg.mdl"); - UTIL_SetSize(pev, Vector(-32, -32, 0), Vector(32, 32, 64)); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->health = gSkillData.gargantuaHealth; - //pev->view_ofs = Vector ( 0, 0, 96 );// taken from mdl file - m_flFieldOfView = -0.2; // width of forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - - MonsterInit(); - - m_pEyeGlow = CSprite::SpriteCreate(GARG_EYE_SPRITE_NAME, pev->origin, FALSE); - m_pEyeGlow->SetTransparency(kRenderGlow, 255, 255, 255, 0, kRenderFxNoDissipation); - m_pEyeGlow->SetAttachment(edict(), 1); - EyeOff(); - m_seeTime = gpGlobals->time + 5; - m_flameTime = gpGlobals->time + 2; -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CGargantua ::Precache() -{ - int i; - - PRECACHE_MODEL("models/garg.mdl"); - PRECACHE_MODEL(GARG_EYE_SPRITE_NAME); - PRECACHE_MODEL(GARG_BEAM_SPRITE_NAME); - PRECACHE_MODEL(GARG_BEAM_SPRITE2); - gStompSprite = PRECACHE_MODEL(GARG_STOMP_SPRITE_NAME); - gGargGibModel = PRECACHE_MODEL(GARG_GIB_MODEL); - PRECACHE_SOUND(GARG_STOMP_BUZZ_SOUND); - - for (i = 0; i < ARRAYSIZE(pAttackHitSounds); i++) - PRECACHE_SOUND((char *)pAttackHitSounds[i]); - - for (i = 0; i < ARRAYSIZE(pBeamAttackSounds); i++) - PRECACHE_SOUND((char *)pBeamAttackSounds[i]); - - for (i = 0; i < ARRAYSIZE(pAttackMissSounds); i++) - PRECACHE_SOUND((char *)pAttackMissSounds[i]); - - for (i = 0; i < ARRAYSIZE(pRicSounds); i++) - PRECACHE_SOUND((char *)pRicSounds[i]); - - for (i = 0; i < ARRAYSIZE(pFootSounds); i++) - PRECACHE_SOUND((char *)pFootSounds[i]); - - for (i = 0; i < ARRAYSIZE(pIdleSounds); i++) - PRECACHE_SOUND((char *)pIdleSounds[i]); - - for (i = 0; i < ARRAYSIZE(pAlertSounds); i++) - PRECACHE_SOUND((char *)pAlertSounds[i]); - - for (i = 0; i < ARRAYSIZE(pPainSounds); i++) - PRECACHE_SOUND((char *)pPainSounds[i]); - - for (i = 0; i < ARRAYSIZE(pAttackSounds); i++) - PRECACHE_SOUND((char *)pAttackSounds[i]); - - for (i = 0; i < ARRAYSIZE(pStompSounds); i++) - PRECACHE_SOUND((char *)pStompSounds[i]); - - for (i = 0; i < ARRAYSIZE(pBreatheSounds); i++) - PRECACHE_SOUND((char *)pBreatheSounds[i]); -} - -void CGargantua::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - ALERT(at_aiconsole, "CGargantua::TraceAttack\n"); - - if (!IsAlive()) - { - CBaseMonster::TraceAttack(pevAttacker, flDamage, vecDir, ptr, bitsDamageType); - return; - } - - // UNDONE: Hit group specific damage? - if (bitsDamageType & (GARG_DAMAGE | DMG_BLAST)) - { - if (m_painSoundTime < gpGlobals->time) - { - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, pPainSounds[RANDOM_LONG(0, ARRAYSIZE(pPainSounds) - 1)], 1.0, ATTN_GARG, 0, PITCH_NORM); - m_painSoundTime = gpGlobals->time + RANDOM_FLOAT(2.5, 4); - } - } - - bitsDamageType &= GARG_DAMAGE; - - if (bitsDamageType == 0) - { - if (pev->dmgtime != gpGlobals->time || (RANDOM_LONG(0, 100) < 20)) - { - UTIL_Ricochet(ptr->vecEndPos, RANDOM_FLOAT(0.5, 1.5)); - pev->dmgtime = gpGlobals->time; - // if ( RANDOM_LONG(0,100) < 25 ) - // EMIT_SOUND_DYN( ENT(pev), CHAN_BODY, pRicSounds[ RANDOM_LONG(0,ARRAYSIZE(pRicSounds)-1) ], 1.0, ATTN_NORM, 0, PITCH_NORM ); - } - flDamage = 0; - } - - CBaseMonster::TraceAttack(pevAttacker, flDamage, vecDir, ptr, bitsDamageType); -} - -int CGargantua::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - ALERT(at_aiconsole, "CGargantua::TakeDamage\n"); - - if (IsAlive()) - { - if (!(bitsDamageType & GARG_DAMAGE)) - flDamage *= 0.01; - if (bitsDamageType & DMG_BLAST) - SetConditions(bits_COND_LIGHT_DAMAGE); - } - - return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -void CGargantua::DeathEffect(void) -{ - int i; - UTIL_MakeVectors(pev->angles); - Vector deathPos = pev->origin + gpGlobals->v_forward * 100; - - // Create a spiral of streaks - CSpiral::Create(deathPos, (pev->absmax.z - pev->absmin.z) * 0.6, 125, 1.5); - - Vector position = pev->origin; - position.z += 32; - for (i = 0; i < 7; i += 2) - { - SpawnExplosion(position, 70, (i * 0.3), 60 + (i * 20)); - position.z += 15; - } - - CBaseEntity *pSmoker = CBaseEntity::Create("env_smoker", pev->origin, g_vecZero, NULL); - pSmoker->pev->health = 1; // 1 smoke balls - pSmoker->pev->scale = 46; // 4.6X normal size - pSmoker->pev->dmg = 0; // 0 radial distribution - pSmoker->pev->nextthink = gpGlobals->time + 2.5; // Start in 2.5 seconds -} - -void CGargantua::Killed(entvars_t *pevAttacker, int iGib) -{ - EyeOff(); - UTIL_Remove(m_pEyeGlow); - m_pEyeGlow = NULL; - CBaseMonster::Killed(pevAttacker, GIB_NEVER); -} - -//========================================================= -// CheckMeleeAttack1 -// Garg swipe attack -// -//========================================================= -BOOL CGargantua::CheckMeleeAttack1(float flDot, float flDist) -{ - // ALERT(at_aiconsole, "CheckMelee(%f, %f)\n", flDot, flDist); - - if (flDot >= 0.7) - { - if (flDist <= GARG_ATTACKDIST) - return TRUE; - } - return FALSE; -} - -// Flame thrower madness! -BOOL CGargantua::CheckMeleeAttack2(float flDot, float flDist) -{ - // ALERT(at_aiconsole, "CheckMelee(%f, %f)\n", flDot, flDist); - - if (gpGlobals->time > m_flameTime) - { - if (flDot >= 0.8 && flDist > GARG_ATTACKDIST) - { - if (flDist <= GARG_FLAME_LENGTH) - return TRUE; - } - } - return FALSE; -} - -//========================================================= -// CheckRangeAttack1 -// flDot is the cos of the angle of the cone within which -// the attack can occur. -//========================================================= -// -// Stomp attack -// -//========================================================= -BOOL CGargantua::CheckRangeAttack1(float flDot, float flDist) -{ - if (gpGlobals->time > m_seeTime) - { - if (flDot >= 0.7 && flDist > GARG_ATTACKDIST) - { - return TRUE; - } - } - return FALSE; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CGargantua::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case GARG_AE_SLASH_LEFT: - { - // HACKHACK!!! - CBaseEntity *pHurt = GargantuaCheckTraceHullAttack(GARG_ATTACKDIST + 10.0, gSkillData.gargantuaDmgSlash, DMG_SLASH); - if (pHurt) - { - if (pHurt->pev->flags & (FL_MONSTER | FL_CLIENT)) - { - pHurt->pev->punchangle.x = -30; // pitch - pHurt->pev->punchangle.y = -30; // yaw - pHurt->pev->punchangle.z = 30; // roll - //UTIL_MakeVectors(pev->angles); // called by CheckTraceHullAttack - pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_right * 100; - } - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, pAttackHitSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackHitSounds) - 1)], 1.0, ATTN_NORM, 0, 50 + RANDOM_LONG(0, 15)); - } - else // Play a random attack miss sound - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, pAttackMissSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackMissSounds) - 1)], 1.0, ATTN_NORM, 0, 50 + RANDOM_LONG(0, 15)); - - Vector forward; - UTIL_MakeVectorsPrivate(pev->angles, forward, NULL, NULL); - } - break; - - case GARG_AE_RIGHT_FOOT: - case GARG_AE_LEFT_FOOT: - UTIL_ScreenShake(pev->origin, 4.0, 3.0, 1.0, 750); - EMIT_SOUND_DYN(edict(), CHAN_BODY, pFootSounds[RANDOM_LONG(0, ARRAYSIZE(pFootSounds) - 1)], 1.0, ATTN_GARG, 0, PITCH_NORM + RANDOM_LONG(-10, 10)); - break; - - case GARG_AE_STOMP: - StompAttack(); - m_seeTime = gpGlobals->time + 12; - break; - - case GARG_AE_BREATHE: - EMIT_SOUND_DYN(edict(), CHAN_VOICE, pBreatheSounds[RANDOM_LONG(0, ARRAYSIZE(pBreatheSounds) - 1)], 1.0, ATTN_GARG, 0, PITCH_NORM + RANDOM_LONG(-10, 10)); - break; - - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// CheckTraceHullAttack - expects a length to trace, amount -// of damage to do, and damage type. Returns a pointer to -// the damaged entity in case the monster wishes to do -// other stuff to the victim (punchangle, etc) -// Used for many contact-range melee attacks. Bites, claws, etc. - -// Overridden for Gargantua because his swing starts lower as -// a percentage of his height (otherwise he swings over the -// players head) -//========================================================= -CBaseEntity *CGargantua::GargantuaCheckTraceHullAttack(float flDist, int iDamage, int iDmgType) -{ - TraceResult tr; - - UTIL_MakeVectors(pev->angles); - Vector vecStart = pev->origin; - vecStart.z += 64; - Vector vecEnd = vecStart + (gpGlobals->v_forward * flDist) - (gpGlobals->v_up * flDist * 0.3); - - UTIL_TraceHull(vecStart, vecEnd, dont_ignore_monsters, head_hull, ENT(pev), &tr); - - if (tr.pHit) - { - CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); - - if (iDamage > 0) - { - pEntity->TakeDamage(pev, pev, iDamage, iDmgType); - } - - return pEntity; - } - - return NULL; -} - -Schedule_t *CGargantua::GetScheduleOfType(int Type) -{ - // HACKHACK - turn off the flames if they are on and garg goes scripted / dead - if (FlameIsOn()) - FlameDestroy(); - - switch (Type) - { - case SCHED_MELEE_ATTACK2: - return slGargFlame; - case SCHED_MELEE_ATTACK1: - return slGargSwipe; - break; - } - - return CBaseMonster::GetScheduleOfType(Type); -} - -void CGargantua::StartTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_FLAME_SWEEP: - FlameCreate(); - m_flWaitFinished = gpGlobals->time + pTask->flData; - m_flameTime = gpGlobals->time + 6; - m_flameX = 0; - m_flameY = 0; - break; - - case TASK_SOUND_ATTACK: - if (RANDOM_LONG(0, 100) < 30) - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, pAttackSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackSounds) - 1)], 1.0, ATTN_GARG, 0, PITCH_NORM); - TaskComplete(); - break; - - case TASK_DIE: - m_flWaitFinished = gpGlobals->time + 1.6; - DeathEffect(); - // FALL THROUGH - default: - CBaseMonster::StartTask(pTask); - break; - } -} - -//========================================================= -// RunTask -//========================================================= -void CGargantua::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_DIE: - if (gpGlobals->time > m_flWaitFinished) - { - pev->renderfx = kRenderFxExplode; - pev->rendercolor.x = 255; - pev->rendercolor.y = 0; - pev->rendercolor.z = 0; - StopAnimation(); - pev->nextthink = gpGlobals->time + 0.15; - SetThink(SUB_Remove); - int i; - int parts = MODEL_FRAMES(gGargGibModel); - for (i = 0; i < 10; i++) - { - CGib *pGib = GetClassPtr((CGib *)NULL); - - pGib->Spawn(GARG_GIB_MODEL); - - int bodyPart = 0; - if (parts > 1) - bodyPart = RANDOM_LONG(0, pev->body - 1); - - pGib->pev->body = bodyPart; - pGib->m_bloodColor = BLOOD_COLOR_YELLOW; - pGib->m_material = matNone; - pGib->pev->origin = pev->origin; - pGib->pev->velocity = UTIL_RandomBloodVector() * RANDOM_FLOAT(300, 500); - pGib->pev->nextthink = gpGlobals->time + 1.25; - pGib->SetThink(SUB_FadeOut); - } - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_BREAKMODEL); - - // position - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - - // size - WRITE_COORD(200); - WRITE_COORD(200); - WRITE_COORD(128); - - // velocity - WRITE_COORD(0); - WRITE_COORD(0); - WRITE_COORD(0); - - // randomization - WRITE_BYTE(200); - - // Model - WRITE_SHORT(gGargGibModel); //model id# - - // # of shards - WRITE_BYTE(50); - - // duration - WRITE_BYTE(20); // 3.0 seconds - - // flags - - WRITE_BYTE(BREAK_FLESH); - MESSAGE_END(); - - return; - } - else - CBaseMonster::RunTask(pTask); - break; - - case TASK_FLAME_SWEEP: - if (gpGlobals->time > m_flWaitFinished) - { - FlameDestroy(); - TaskComplete(); - FlameControls(0, 0); - SetBoneController(0, 0); - SetBoneController(1, 0); - } - else - { - BOOL cancel = FALSE; - - Vector angles = g_vecZero; - - FlameUpdate(); - CBaseEntity *pEnemy = m_hEnemy; - if (pEnemy) - { - Vector org = pev->origin; - org.z += 64; - Vector dir = pEnemy->BodyTarget(org) - org; - angles = UTIL_VecToAngles(dir); - angles.x = -angles.x; - angles.y -= pev->angles.y; - if (dir.Length() > 400) - cancel = TRUE; - } - if (fabs(angles.y) > 60) - cancel = TRUE; - - if (cancel) - { - m_flWaitFinished -= 0.5; - m_flameTime -= 0.5; - } - // FlameControls( angles.x + 2 * sin(gpGlobals->time*8), angles.y + 28 * sin(gpGlobals->time*8.5) ); - FlameControls(angles.x, angles.y); - } - break; - - default: - CBaseMonster::RunTask(pTask); - break; - } -} - -class CSmoker : public CBaseEntity -{ -public: - void Spawn(void); - void Think(void); -}; - -LINK_ENTITY_TO_CLASS(env_smoker, CSmoker); - -void CSmoker::Spawn(void) -{ - pev->movetype = MOVETYPE_NONE; - pev->nextthink = gpGlobals->time; - pev->solid = SOLID_NOT; - UTIL_SetSize(pev, g_vecZero, g_vecZero); - pev->effects |= EF_NODRAW; - pev->angles = g_vecZero; -} - -void CSmoker::Think(void) -{ - // lots of smoke - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(pev->origin.x + RANDOM_FLOAT(-pev->dmg, pev->dmg)); - WRITE_COORD(pev->origin.y + RANDOM_FLOAT(-pev->dmg, pev->dmg)); - WRITE_COORD(pev->origin.z); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(RANDOM_LONG(pev->scale, pev->scale * 1.1)); - WRITE_BYTE(RANDOM_LONG(8, 14)); // framerate - MESSAGE_END(); - - pev->health--; - if (pev->health > 0) - pev->nextthink = gpGlobals->time + RANDOM_FLOAT(0.1, 0.2); - else - UTIL_Remove(this); -} - -void CSpiral::Spawn(void) -{ - pev->movetype = MOVETYPE_NONE; - pev->nextthink = gpGlobals->time; - pev->solid = SOLID_NOT; - UTIL_SetSize(pev, g_vecZero, g_vecZero); - pev->effects |= EF_NODRAW; - pev->angles = g_vecZero; -} - -CSpiral *CSpiral::Create(const Vector &origin, float height, float radius, float duration) -{ - if (duration <= 0) - return NULL; - - CSpiral *pSpiral = GetClassPtr((CSpiral *)NULL); - pSpiral->Spawn(); - pSpiral->pev->dmgtime = pSpiral->pev->nextthink; - pSpiral->pev->origin = origin; - pSpiral->pev->scale = radius; - pSpiral->pev->dmg = height; - pSpiral->pev->speed = duration; - pSpiral->pev->health = 0; - pSpiral->pev->angles = g_vecZero; - - return pSpiral; -} - -#define SPIRAL_INTERVAL 0.1 //025 - -void CSpiral::Think(void) -{ - float time = gpGlobals->time - pev->dmgtime; - - while (time > SPIRAL_INTERVAL) - { - Vector position = pev->origin; - Vector direction = Vector(0, 0, 1); - - float fraction = 1.0 / pev->speed; - - float radius = (pev->scale * pev->health) * fraction; - - position.z += (pev->health * pev->dmg) * fraction; - pev->angles.y = (pev->health * 360 * 8) * fraction; - UTIL_MakeVectors(pev->angles); - position = position + gpGlobals->v_forward * radius; - direction = (direction + gpGlobals->v_forward).Normalize(); - - StreakSplash(position, Vector(0, 0, 1), RANDOM_LONG(8, 11), 20, RANDOM_LONG(50, 150), 400); - - // Jeez, how many counters should this take ? :) - pev->dmgtime += SPIRAL_INTERVAL; - pev->health += SPIRAL_INTERVAL; - time -= SPIRAL_INTERVAL; - } - - pev->nextthink = gpGlobals->time; - - if (pev->health >= pev->speed) - UTIL_Remove(this); -} - -// HACKHACK Cut and pasted from explode.cpp -void SpawnExplosion(Vector center, float randomRange, float time, int magnitude) -{ - KeyValueData kvd; - char buf[128]; - - center.x += RANDOM_FLOAT(-randomRange, randomRange); - center.y += RANDOM_FLOAT(-randomRange, randomRange); - - CBaseEntity *pExplosion = CBaseEntity::Create("env_explosion", center, g_vecZero, NULL); - _snprintf(buf, sizeof(buf), "%3d", magnitude ); - kvd.szKeyName = "iMagnitude"; - kvd.szValue = buf; - pExplosion->KeyValue(&kvd); - pExplosion->pev->spawnflags |= SF_ENVEXPLOSION_NODAMAGE; - - pExplosion->Spawn(); - pExplosion->SetThink(CBaseEntity::SUB_CallUseToggle); - pExplosion->pev->nextthink = gpGlobals->time + time; -} - -#endif \ No newline at end of file diff --git a/dlls/Half-life/gauss.cpp b/dlls/Half-life/gauss.cpp deleted file mode 100644 index 0b061a02..00000000 --- a/dlls/Half-life/gauss.cpp +++ /dev/null @@ -1,626 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "soundent.h" -#include "shake.h" -#include "gamerules.h" - -#define GAUSS_PRIMARY_CHARGE_VOLUME 256 // how loud gauss is while charging -#define GAUSS_PRIMARY_FIRE_VOLUME 450 // how loud gauss is when discharged - -enum gauss_e -{ - GAUSS_IDLE = 0, - GAUSS_IDLE2, - GAUSS_FIDGET, - GAUSS_SPINUP, - GAUSS_SPIN, - GAUSS_FIRE, - GAUSS_FIRE2, - GAUSS_HOLSTER, - GAUSS_DRAW -}; - -class CGauss : public CBasePlayerWeapon -{ -public: - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void Spawn(void); - void Precache(void); - int iItemSlot(void) { return 4; } - int GetItemInfo(ItemInfo *p); - int AddToPlayer(CBasePlayer *pPlayer); - - BOOL Deploy(void); - void Holster(int skiplocal = 0); - - void PrimaryAttack(void); - void SecondaryAttack(void); - void WeaponIdle(void); - - int m_fInAttack; - float m_flStartCharge; - float m_flPlayAftershock; - void StartFire(void); - void Fire(Vector vecOrigSrc, Vector vecDirShooting, float flDamage); - float GetFullChargeTime(void); - int m_iBalls; - int m_iGlow; - int m_iBeam; - int m_iSoundState; // don't save this - - float m_flNextAmmoBurn; // while charging, when to absorb another unit of player's ammo? - - // was this weapon just fired primary or secondary? - // we need to know so we can pick the right set of effects. - BOOL m_fPrimaryFire; - -private: - unsigned short m_usGaussFire; - unsigned short m_usGaussSpin; -}; -LINK_ENTITY_TO_CLASS(weapon_gauss, CGauss); - -TYPEDESCRIPTION CGauss::m_SaveData[] = - { - DEFINE_FIELD(CGauss, m_fInAttack, FIELD_INTEGER), - DEFINE_FIELD(CGauss, m_flStartCharge, FIELD_TIME), - DEFINE_FIELD(CGauss, m_flPlayAftershock, FIELD_TIME), - DEFINE_FIELD(CGauss, m_flNextAmmoBurn, FIELD_TIME), - DEFINE_FIELD(CGauss, m_fPrimaryFire, FIELD_BOOLEAN), -}; -IMPLEMENT_SAVERESTORE(CGauss, CBasePlayerWeapon); - -float CGauss::GetFullChargeTime(void) -{ - if (g_pGameRules->IsMultiplayer()) - { - return 1.5; - } - - return 4; -} - -void CGauss::Spawn() -{ - Precache(); - m_iId = WEAPON_GAUSS; - SET_MODEL(ENT(pev), "models/w_gauss.mdl"); - - m_iDefaultAmmo = GAUSS_DEFAULT_GIVE; - - FallInit(); // get ready to fall down. -} - -void CGauss::Precache(void) -{ - PRECACHE_MODEL("models/w_gauss.mdl"); - PRECACHE_MODEL("models/v_gauss.mdl"); - PRECACHE_MODEL("models/p_gauss.mdl"); - - PRECACHE_SOUND("items/9mmclip1.wav"); - - PRECACHE_SOUND("weapons/gauss2.wav"); - PRECACHE_SOUND("weapons/electro4.wav"); - PRECACHE_SOUND("weapons/electro5.wav"); - PRECACHE_SOUND("weapons/electro6.wav"); - PRECACHE_SOUND("ambience/pulsemachine.wav"); - - m_iGlow = PRECACHE_MODEL("sprites/hotglow.spr"); - m_iBalls = PRECACHE_MODEL("sprites/hotglow.spr"); - m_iBeam = PRECACHE_MODEL("sprites/smoke.spr"); - - m_usGaussFire = PRECACHE_EVENT(1, "events/gauss.sc"); - m_usGaussSpin = PRECACHE_EVENT(1, "events/gaussspin.sc"); -} - -int CGauss::AddToPlayer(CBasePlayer *pPlayer) -{ - if (CBasePlayerWeapon::AddToPlayer(pPlayer)) - { - MESSAGE_BEGIN(MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev); - WRITE_BYTE(m_iId); - MESSAGE_END(); - return TRUE; - } - return FALSE; -} - -int CGauss::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "uranium"; - p->iMaxAmmo1 = URANIUM_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = WEAPON_NOCLIP; - p->iSlot = 3; - p->iPosition = 1; - p->iId = m_iId = WEAPON_GAUSS; - p->iFlags = 0; - p->iWeight = GAUSS_WEIGHT; - - return 1; -} - -BOOL CGauss::Deploy() -{ - return DefaultDeploy("models/v_gauss.mdl", "models/p_gauss.mdl", GAUSS_DRAW, "gauss"); -} - -void CGauss::Holster(int skiplocal /* = 0 */) -{ - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - // m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 ); - SendWeaponAnim(GAUSS_HOLSTER); - m_fInAttack = 0; - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM); -} - -void CGauss::PrimaryAttack() -{ - // don't fire underwater - if (m_pPlayer->pev->waterlevel == 3) - { - PlayEmptySound(); - m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->time + 0.15; - return; - } - - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 2) - { - PlayEmptySound(); - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - return; - } - - m_pPlayer->m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME; - - m_fPrimaryFire = TRUE; - - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 2; - - StartFire(); - m_fInAttack = 0; - m_flTimeWeaponIdle = gpGlobals->time + 1.0; - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.2; -} - -void CGauss::SecondaryAttack() -{ - // don't fire underwater - if (m_pPlayer->pev->waterlevel == 3) - { - if (m_fInAttack != 0) - { - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/electro4.wav", 1.0, ATTN_NORM, 0, 80 + RANDOM_LONG(0, 0x3f)); - SendWeaponAnim(GAUSS_IDLE); - m_fInAttack = 0; - } - else - { - PlayEmptySound(); - } - - m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->time + 0.5; - return; - } - - if (m_fInAttack == 0) - { - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - { - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/357_cock1.wav", 0.8, ATTN_NORM); - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - return; - } - - m_fPrimaryFire = FALSE; - - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; // take one ammo just to start the spin - m_flNextAmmoBurn = gpGlobals->time; - - // spin up - m_pPlayer->m_iWeaponVolume = GAUSS_PRIMARY_CHARGE_VOLUME; - - SendWeaponAnim(GAUSS_SPINUP); - m_fInAttack = 1; - m_flTimeWeaponIdle = gpGlobals->time + 0.5; - m_flStartCharge = gpGlobals->time; - - PLAYBACK_EVENT_FULL(0, m_pPlayer->edict(), m_usGaussSpin, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 110, 0, 0, 0); - - m_iSoundState = SND_CHANGE_PITCH; - } - else if (m_fInAttack == 1) - { - if (m_flTimeWeaponIdle < gpGlobals->time) - { - SendWeaponAnim(GAUSS_SPIN); - m_fInAttack = 2; - } - } - else - { - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0) - { - // out of ammo! force the gun to fire - StartFire(); - m_fInAttack = 0; - m_flTimeWeaponIdle = gpGlobals->time + 1.0; - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1; - return; - } - - // during the charging process, eat one bit of ammo every once in a while - if (gpGlobals->time > m_flNextAmmoBurn && m_flNextAmmoBurn != -1) - { - if (g_pGameRules->IsMultiplayer()) - { - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; - m_flNextAmmoBurn = gpGlobals->time + 0.1; - } - else - { - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; - m_flNextAmmoBurn = gpGlobals->time + 0.3; - } - } - - if (gpGlobals->time - m_flStartCharge >= GetFullChargeTime()) - { - // don't eat any more ammo after gun is fully charged. - m_flNextAmmoBurn = -1; - } - - int pitch = (gpGlobals->time - m_flStartCharge) * (150 / GetFullChargeTime()) + 100; - if (pitch > 250) - pitch = 250; - - // ALERT( at_console, "%d %d %d\n", m_fInAttack, m_iSoundState, pitch ); - - if (m_iSoundState == 0) - ALERT(at_console, "sound state %d\n", m_iSoundState); - - PLAYBACK_EVENT_FULL(0, m_pPlayer->edict(), m_usGaussSpin, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, pitch, 0, (m_iSoundState == SND_CHANGE_PITCH) ? 1 : 0, 0); - - m_iSoundState = SND_CHANGE_PITCH; // hack for going through level transitions - - m_pPlayer->m_iWeaponVolume = GAUSS_PRIMARY_CHARGE_VOLUME; - - // m_flTimeWeaponIdle = gpGlobals->time + 0.1; - if (m_flStartCharge < gpGlobals->time - 10) - { - // Player charged up too long. Zap him. - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/electro4.wav", 1.0, ATTN_NORM, 0, 80 + RANDOM_LONG(0, 0x3f)); - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/electro6.wav", 1.0, ATTN_NORM, 0, 75 + RANDOM_LONG(0, 0x3f)); - - m_fInAttack = 0; - m_flTimeWeaponIdle = gpGlobals->time + 1.0; - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0; - m_pPlayer->TakeDamage(VARS(eoNullEntity), VARS(eoNullEntity), 50, DMG_SHOCK); - - UTIL_ScreenFade(m_pPlayer, Vector(255, 128, 0), 2, 0.5, 128, FFADE_IN); - SendWeaponAnim(GAUSS_IDLE); - - // Player may have been killed and this weapon dropped, don't execute any more code after this! - return; - } - } -} - -//========================================================= -// StartFire- since all of this code has to run and then -// call Fire(), it was easier at this point to rip it out -// of weaponidle() and make its own function then to try to -// merge this into Fire(), which has some identical variable names -//========================================================= -void CGauss::StartFire(void) -{ - float flDamage; - - UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle); - Vector vecAiming = gpGlobals->v_forward; - Vector vecSrc = m_pPlayer->GetGunPosition(); // + gpGlobals->v_up * -8 + gpGlobals->v_right * 8; - - if (gpGlobals->time - m_flStartCharge > GetFullChargeTime()) - { - flDamage = 200; - } - else - { - flDamage = 200 * ((gpGlobals->time - m_flStartCharge) / GetFullChargeTime()); - } - - if (m_fPrimaryFire) - { - // fixed damage on primary attack - flDamage = gSkillData.plrDmgGauss; - } - - if (m_fInAttack != 3) - { - //ALERT ( at_console, "Time:%f Damage:%f\n", gpGlobals->time - m_flStartCharge, flDamage ); - - float flZVel = m_pPlayer->pev->velocity.z; - - if (!m_fPrimaryFire) - { - m_pPlayer->pev->velocity = m_pPlayer->pev->velocity - gpGlobals->v_forward * flDamage * 5; - } - - if (!g_pGameRules->IsDeathmatch()) - { - // in deathmatch, gauss can pop you up into the air. Not in single play. - m_pPlayer->pev->velocity.z = flZVel; - } - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - } - // time until aftershock 'static discharge' sound - m_flPlayAftershock = gpGlobals->time + RANDOM_FLOAT(0.3, 0.8); - - Fire(vecSrc, vecAiming, flDamage); -} - -void CGauss::Fire(Vector vecOrigSrc, Vector vecDir, float flDamage) -{ - m_pPlayer->m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME; - - Vector vecSrc = vecOrigSrc; - Vector vecDest = vecSrc + vecDir * 8192; - edict_t *pentIgnore; - TraceResult tr, beam_tr; - float flMaxFrac = 1.0; - int nTotal = 0; - int fHasPunched = 0; - int fFirstBeam = 1; - int nMaxHits = 10; - - pentIgnore = ENT(m_pPlayer->pev); - - // Pass in correct values here - PLAYBACK_EVENT_FULL(FEV_RELIABLE, m_pPlayer->edict(), m_usGaussFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, flDamage, 0.0, 0, 0, m_fPrimaryFire ? 1 : 0, 0); - - /* - ALERT( at_console, "%f %f %f\n%f %f %f\n", - vecSrc.x, vecSrc.y, vecSrc.z, - vecDest.x, vecDest.y, vecDest.z ); - */ - - // ALERT( at_console, "%f %f\n", tr.flFraction, flMaxFrac ); - - while (flDamage > 10 && nMaxHits > 0) - { - nMaxHits--; - - // ALERT( at_console, "." ); - UTIL_TraceLine(vecSrc, vecDest, dont_ignore_monsters, pentIgnore, &tr); - - if (tr.fAllSolid) - break; - - CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); - - if (pEntity == NULL) - break; - - if (fFirstBeam) - { - m_pPlayer->pev->effects |= EF_MUZZLEFLASH; - fFirstBeam = 0; - } - else - { - } - - if (pEntity->pev->takedamage) - { - ClearMultiDamage(); - pEntity->TraceAttack(m_pPlayer->pev, flDamage, vecDir, &tr, DMG_BULLET); - ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev); - } - - // ALERT( at_console, "%s\n", STRING( pEntity->pev->classname )); - - if (pEntity->ReflectGauss()) - { - float n; - - pentIgnore = NULL; - - n = -DotProduct(tr.vecPlaneNormal, vecDir); - - if (n < 0.5) // 60 degrees - { - // ALERT( at_console, "reflect %f\n", n ); - // reflect - Vector r; - - r = 2.0 * tr.vecPlaneNormal * n + vecDir; - flMaxFrac = flMaxFrac - tr.flFraction; - vecDir = r; - vecSrc = tr.vecEndPos + vecDir * 8; - vecDest = vecSrc + vecDir * 8192; - - // explode a bit - m_pPlayer->RadiusDamage(tr.vecEndPos, pev, m_pPlayer->pev, flDamage * n, CLASS_NONE, DMG_BLAST); - - // lose energy - if (n == 0) - n = 0.1; - flDamage = flDamage * (1 - n); - } - else - { - // limit it to one hole punch - if (fHasPunched) - break; - fHasPunched = 1; - - // try punching through wall if secondary attack (primary is incapable of breaking through) - if (!m_fPrimaryFire) - { - UTIL_TraceLine(tr.vecEndPos + vecDir * 8, vecDest, dont_ignore_monsters, pentIgnore, &beam_tr); - if (!beam_tr.fAllSolid) - { - // trace backwards to find exit point - UTIL_TraceLine(beam_tr.vecEndPos, tr.vecEndPos, dont_ignore_monsters, pentIgnore, &beam_tr); - - float n = (beam_tr.vecEndPos - tr.vecEndPos).Length(); - - if (n < flDamage) - { - if (n == 0) - n = 1; - flDamage -= n; - - // exit blast damage - //m_pPlayer->RadiusDamage( beam_tr.vecEndPos + vecDir * 8, pev, m_pPlayer->pev, flDamage, CLASS_NONE, DMG_BLAST ); - float damage_radius; - - if (g_pGameRules->IsMultiplayer()) - { - damage_radius = flDamage * 1.75; // Old code == 2.5 - } - else - { - damage_radius = flDamage * 2.5; - } - - ::RadiusDamage(beam_tr.vecEndPos + vecDir * 8, pev, m_pPlayer->pev, flDamage, damage_radius, CLASS_NONE, DMG_BLAST); - CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0); - - vecSrc = beam_tr.vecEndPos + vecDir; - } - } - else - { - //ALERT( at_console, "blocked %f\n", n ); - flDamage = 0; - } - } - else - { - //ALERT( at_console, "blocked solid\n" ); - flDamage = 0; - } - } - } - else - { - vecSrc = tr.vecEndPos + vecDir; - pentIgnore = ENT(pEntity->pev); - } - } - // ALERT( at_console, "%d bytes\n", nTotal ); -} - -void CGauss::WeaponIdle(void) -{ - ResetEmptySound(); - - // play aftershock static discharge - if (m_flPlayAftershock && m_flPlayAftershock < gpGlobals->time) - { - switch (RANDOM_LONG(0, 3)) - { - case 0: - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/electro4.wav", RANDOM_FLOAT(0.7, 0.8), ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/electro5.wav", RANDOM_FLOAT(0.7, 0.8), ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/electro6.wav", RANDOM_FLOAT(0.7, 0.8), ATTN_NORM); - break; - case 3: - break; // no sound - } - m_flPlayAftershock = 0.0; - } - - if (m_flTimeWeaponIdle > gpGlobals->time) - return; - - if (m_fInAttack != 0) - { - StartFire(); - m_fInAttack = 0; - m_flTimeWeaponIdle = gpGlobals->time + 2.0; - } - else - { - int iAnim; - float flRand = RANDOM_FLOAT(0, 1); - if (flRand <= 0.5) - { - iAnim = GAUSS_IDLE; - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); - } - else if (flRand <= 0.75) - { - iAnim = GAUSS_IDLE2; - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); - } - else - { - iAnim = GAUSS_FIDGET; - m_flTimeWeaponIdle = gpGlobals->time + 3; - } - - return; - SendWeaponAnim(iAnim); - } -} - -class CGaussAmmo : public CBasePlayerAmmo -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_gaussammo.mdl"); - CBasePlayerAmmo::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_gaussammo.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - } - BOOL AddAmmo(CBaseEntity *pOther) - { - if (pOther->GiveAmmo(AMMO_URANIUMBOX_GIVE, "uranium", URANIUM_MAX_CARRY) != -1) - { - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); - return TRUE; - } - return FALSE; - } -}; -LINK_ENTITY_TO_CLASS(ammo_gaussclip, CGaussAmmo); - -#endif \ No newline at end of file diff --git a/dlls/Half-life/genericmonster.cpp b/dlls/Half-life/genericmonster.cpp deleted file mode 100644 index f2713e1c..00000000 --- a/dlls/Half-life/genericmonster.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// Generic Monster - purely for scripted sequence work. -//========================================================= -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" - -// For holograms, make them not solid so the player can walk through them -#define SF_GENERICMONSTER_NOTSOLID 4 - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= - -class CGenericMonster : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - int ISoundMask(void); -}; -LINK_ENTITY_TO_CLASS(monster_generic, CGenericMonster); - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CGenericMonster ::Classify(void) -{ - return CLASS_PLAYER_ALLY; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CGenericMonster ::SetYawSpeed(void) -{ - int ys; - - switch (m_Activity) - { - case ACT_IDLE: - default: - ys = 90; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CGenericMonster ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case 0: - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// ISoundMask - generic monster can't hear. -//========================================================= -int CGenericMonster ::ISoundMask(void) -{ - return NULL; -} - -//========================================================= -// Spawn -//========================================================= -void CGenericMonster ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), STRING(pev->model)); - - /* - if ( FStrEq( STRING(pev->model), "models/player.mdl" ) ) - UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); - else - UTIL_SetSize(pev, VEC_HULL_MIN, VEC_HULL_MAX); -*/ - - if (FStrEq(STRING(pev->model), "models/player.mdl") || FStrEq(STRING(pev->model), "models/holo.mdl")) - UTIL_SetSize(pev, VEC_HULL_MIN, VEC_HULL_MAX); - else - 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->health = 8; - m_flFieldOfView = 0.5; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - - MonsterInit(); - - if (pev->spawnflags & SF_GENERICMONSTER_NOTSOLID) - { - pev->solid = SOLID_NOT; - pev->takedamage = DAMAGE_NO; - } -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CGenericMonster ::Precache() -{ - PRECACHE_MODEL((char *)STRING(pev->model)); -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= diff --git a/dlls/Half-life/gman.cpp b/dlls/Half-life/gman.cpp deleted file mode 100644 index 0f0209cf..00000000 --- a/dlls/Half-life/gman.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// GMan - misunderstood servant of the people -//========================================================= -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" -#include "weapons.h" - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= - -class CGMan : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - int ISoundMask(void); - - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void StartTask(Task_t *pTask); - void RunTask(Task_t *pTask); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - - void PlayScriptedSentence(const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener); - - EHANDLE m_hPlayer; - EHANDLE m_hTalkTarget; - float m_flTalkTime; -}; -LINK_ENTITY_TO_CLASS(monster_gman, CGMan); - -TYPEDESCRIPTION CGMan::m_SaveData[] = - { - DEFINE_FIELD(CGMan, m_hTalkTarget, FIELD_EHANDLE), - DEFINE_FIELD(CGMan, m_flTalkTime, FIELD_TIME), -}; -IMPLEMENT_SAVERESTORE(CGMan, CBaseMonster); - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CGMan ::Classify(void) -{ - return CLASS_NONE; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CGMan ::SetYawSpeed(void) -{ - int ys; - - switch (m_Activity) - { - case ACT_IDLE: - default: - ys = 90; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CGMan ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case 0: - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// ISoundMask - generic monster can't hear. -//========================================================= -int CGMan ::ISoundMask(void) -{ - return NULL; -} - -//========================================================= -// Spawn -//========================================================= -void CGMan ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/gman.mdl"); - UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = DONT_BLEED; - pev->health = 100; - m_flFieldOfView = 0.5; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CGMan ::Precache() -{ - PRECACHE_MODEL("models/gman.mdl"); -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - -void CGMan ::StartTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_WAIT: - if (m_hPlayer == NULL) - { - m_hPlayer = UTIL_FindEntityByClassname(NULL, "player"); - } - break; - } - CBaseMonster::StartTask(pTask); -} - -void CGMan ::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_WAIT: - // look at who I'm talking to - if (m_flTalkTime > gpGlobals->time && m_hTalkTarget != NULL) - { - float yaw = VecToYaw(m_hTalkTarget->pev->origin - pev->origin) - pev->angles.y; - - if (yaw > 180) - yaw -= 360; - if (yaw < -180) - yaw += 360; - - // turn towards vector - SetBoneController(0, yaw); - } - // look at player, but only if playing a "safe" idle animation - else if (m_hPlayer != NULL && pev->sequence == 0) - { - float yaw = VecToYaw(m_hPlayer->pev->origin - pev->origin) - pev->angles.y; - - if (yaw > 180) - yaw -= 360; - if (yaw < -180) - yaw += 360; - - // turn towards vector - SetBoneController(0, yaw); - } - else - { - SetBoneController(0, 0); - } - CBaseMonster::RunTask(pTask); - break; - default: - SetBoneController(0, 0); - CBaseMonster::RunTask(pTask); - break; - } -} - -//========================================================= -// Override all damage -//========================================================= -int CGMan ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - pev->health = pev->max_health / 2; // always trigger the 50% damage aitrigger - - if (flDamage > 0) - { - SetConditions(bits_COND_LIGHT_DAMAGE); - } - - if (flDamage >= 20) - { - SetConditions(bits_COND_HEAVY_DAMAGE); - } - return TRUE; -} - -void CGMan::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - UTIL_Ricochet(ptr->vecEndPos, 1.0); - AddMultiDamage(pevAttacker, this, flDamage, bitsDamageType); -} - -void CGMan::PlayScriptedSentence(const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener) -{ - CBaseMonster::PlayScriptedSentence(pszSentence, duration, volume, attenuation, bConcurrent, pListener); - - m_flTalkTime = gpGlobals->time + duration; - m_hTalkTarget = pListener; -} diff --git a/dlls/Half-life/h_ai.cpp b/dlls/Half-life/h_ai.cpp deleted file mode 100644 index f09c4a06..00000000 --- a/dlls/Half-life/h_ai.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -/* - - h_ai.cpp - halflife specific ai code - -*/ - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" - -#define NUM_LATERAL_CHECKS 13 // how many checks are made on each side of a monster looking for lateral cover -#define NUM_LATERAL_LOS_CHECKS 6 // how many checks are made on each side of a monster looking for lateral cover - -//float flRandom = RANDOM_FLOAT(0,1); - -DLL_GLOBAL BOOL g_fDrawLines = FALSE; - -//========================================================= -// -// AI UTILITY FUNCTIONS -// -// !!!UNDONE - move CBaseMonster functions to monsters.cpp -//========================================================= - -//========================================================= -// FBoxVisible - a more accurate ( and slower ) version -// of FVisible. -// -// !!!UNDONE - make this CBaseMonster? -//========================================================= -BOOL FBoxVisible(entvars_t *pevLooker, entvars_t *pevTarget, Vector &vecTargetOrigin, float flSize) -{ - // don't look through water - if ((pevLooker->waterlevel != 3 && pevTarget->waterlevel == 3) || (pevLooker->waterlevel == 3 && pevTarget->waterlevel == 0)) - return FALSE; - - TraceResult tr; - Vector vecLookerOrigin = pevLooker->origin + pevLooker->view_ofs; //look through the monster's 'eyes' - for (int i = 0; i < 5; i++) - { - Vector vecTarget = pevTarget->origin; - vecTarget.x += RANDOM_FLOAT(pevTarget->mins.x + flSize, pevTarget->maxs.x - flSize); - vecTarget.y += RANDOM_FLOAT(pevTarget->mins.y + flSize, pevTarget->maxs.y - flSize); - vecTarget.z += RANDOM_FLOAT(pevTarget->mins.z + flSize, pevTarget->maxs.z - flSize); - - UTIL_TraceLine(vecLookerOrigin, vecTarget, ignore_monsters, ignore_glass, ENT(pevLooker) /*pentIgnore*/, &tr); - - if (tr.flFraction == 1.0) - { - vecTargetOrigin = vecTarget; - return TRUE; // line of sight is valid. - } - } - return FALSE; // Line of sight is not established -} - -// -// VecCheckToss - returns the velocity at which an object should be lobbed from vecspot1 to land near vecspot2. -// returns g_vecZero if toss is not feasible. -// -Vector VecCheckToss(entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flGravityAdj) -{ - TraceResult tr; - Vector vecMidPoint; // halfway point between Spot1 and Spot2 - Vector vecApex; // highest point - Vector vecScale; - Vector vecGrenadeVel; - Vector vecTemp; - float flGravity = CVAR_GET_FLOAT("sv_gravity") * flGravityAdj; - - if (vecSpot2.z - vecSpot1.z > 500) - { - // to high, fail - return g_vecZero; - } - - UTIL_MakeVectors(pev->angles); - - // toss a little bit to the left or right, not right down on the enemy's bean (head). - vecSpot2 = vecSpot2 + gpGlobals->v_right * (RANDOM_FLOAT(-8, 8) + RANDOM_FLOAT(-16, 16)); - vecSpot2 = vecSpot2 + gpGlobals->v_forward * (RANDOM_FLOAT(-8, 8) + RANDOM_FLOAT(-16, 16)); - - // calculate the midpoint and apex of the 'triangle' - // UNDONE: normalize any Z position differences between spot1 and spot2 so that triangle is always RIGHT - - // How much time does it take to get there? - - // get a rough idea of how high it can be thrown - vecMidPoint = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5; - UTIL_TraceLine(vecMidPoint, vecMidPoint + Vector(0, 0, 500), ignore_monsters, ENT(pev), &tr); - vecMidPoint = tr.vecEndPos; - // (subtract 15 so the grenade doesn't hit the ceiling) - vecMidPoint.z -= 15; - - if (vecMidPoint.z < vecSpot1.z || vecMidPoint.z < vecSpot2.z) - { - // to not enough space, fail - return g_vecZero; - } - - // How high should the grenade travel to reach the apex - float distance1 = (vecMidPoint.z - vecSpot1.z); - float distance2 = (vecMidPoint.z - vecSpot2.z); - - // How long will it take for the grenade to travel this distance - float time1 = sqrt(distance1 / (0.5 * flGravity)); - float time2 = sqrt(distance2 / (0.5 * flGravity)); - - if (time1 < 0.1) - { - // too close - return g_vecZero; - } - - // how hard to throw sideways to get there in time. - vecGrenadeVel = (vecSpot2 - vecSpot1) / (time1 + time2); - // how hard upwards to reach the apex at the right time. - vecGrenadeVel.z = flGravity * time1; - - // find the apex - vecApex = vecSpot1 + vecGrenadeVel * time1; - vecApex.z = vecMidPoint.z; - - UTIL_TraceLine(vecSpot1, vecApex, dont_ignore_monsters, ENT(pev), &tr); - if (tr.flFraction != 1.0) - { - // fail! - return g_vecZero; - } - - // UNDONE: either ignore monsters or change it to not care if we hit our enemy - UTIL_TraceLine(vecSpot2, vecApex, ignore_monsters, ENT(pev), &tr); - if (tr.flFraction != 1.0) - { - // fail! - return g_vecZero; - } - - return vecGrenadeVel; -} - -// -// VecCheckThrow - returns the velocity vector at which an object should be thrown from vecspot1 to hit vecspot2. -// returns g_vecZero if throw is not feasible. -// -Vector VecCheckThrow(entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj) -{ - float flGravity = CVAR_GET_FLOAT("sv_gravity") * flGravityAdj; - - Vector vecGrenadeVel = (vecSpot2 - vecSpot1); - - // throw at a constant time - float time = vecGrenadeVel.Length() / flSpeed; - vecGrenadeVel = vecGrenadeVel * (1.0 / time); - - // adjust upward toss to compensate for gravity loss - vecGrenadeVel.z += flGravity * time * 0.5; - - Vector vecApex = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5; - vecApex.z += 0.5 * flGravity * (time * 0.5) * (time * 0.5); - - TraceResult tr; - UTIL_TraceLine(vecSpot1, vecApex, dont_ignore_monsters, ENT(pev), &tr); - if (tr.flFraction != 1.0) - { - // fail! - return g_vecZero; - } - - UTIL_TraceLine(vecSpot2, vecApex, ignore_monsters, ENT(pev), &tr); - if (tr.flFraction != 1.0) - { - // fail! - return g_vecZero; - } - - return vecGrenadeVel; -} diff --git a/dlls/Half-life/h_battery.cpp b/dlls/Half-life/h_battery.cpp deleted file mode 100644 index 4e69dfb3..00000000 --- a/dlls/Half-life/h_battery.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -/* - -===== h_battery.cpp ======================================================== - - battery-related code - -*/ - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "saverestore.h" -#include "skill.h" -#include "gamerules.h" - -class CRecharge : public CBaseToggle -{ -public: - void Spawn(); - void Precache(void); - void EXPORT Off(void); - void EXPORT Recharge(void); - void KeyValue(KeyValueData *pkvd); - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - virtual int ObjectCaps(void) { return (CBaseToggle ::ObjectCaps() | FCAP_CONTINUOUS_USE) & ~FCAP_ACROSS_TRANSITION; } - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - - static TYPEDESCRIPTION m_SaveData[]; - - float m_flNextCharge; - int m_iReactivate; // DeathMatch Delay until reactvated - int m_iJuice; - int m_iOn; // 0 = off, 1 = startup, 2 = going - float m_flSoundTime; -}; - -TYPEDESCRIPTION CRecharge::m_SaveData[] = - { - DEFINE_FIELD(CRecharge, m_flNextCharge, FIELD_TIME), - DEFINE_FIELD(CRecharge, m_iReactivate, FIELD_INTEGER), - DEFINE_FIELD(CRecharge, m_iJuice, FIELD_INTEGER), - DEFINE_FIELD(CRecharge, m_iOn, FIELD_INTEGER), - DEFINE_FIELD(CRecharge, m_flSoundTime, FIELD_TIME), -}; - -IMPLEMENT_SAVERESTORE(CRecharge, CBaseEntity); - -LINK_ENTITY_TO_CLASS(func_recharge, CRecharge); - -void CRecharge::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "style") || - FStrEq(pkvd->szKeyName, "height") || - FStrEq(pkvd->szKeyName, "value1") || - FStrEq(pkvd->szKeyName, "value2") || - FStrEq(pkvd->szKeyName, "value3")) - { - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "dmdelay")) - { - m_iReactivate = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else - CBaseToggle::KeyValue(pkvd); -} - -void CRecharge::Spawn() -{ - Precache(); - - pev->solid = SOLID_BSP; - pev->movetype = MOVETYPE_PUSH; - - UTIL_SetOrigin(pev, pev->origin); // set size and link into world - UTIL_SetSize(pev, pev->mins, pev->maxs); - SET_MODEL(ENT(pev), STRING(pev->model)); - m_iJuice = gSkillData.suitchargerCapacity; - pev->frame = 0; -} - -void CRecharge::Precache() -{ - PRECACHE_SOUND("items/suitcharge1.wav"); - PRECACHE_SOUND("items/suitchargeno1.wav"); - PRECACHE_SOUND("items/suitchargeok1.wav"); -} - -void CRecharge::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - // if it's not a player, ignore - if (!FClassnameIs(pActivator->pev, "player")) - return; - - // if there is no juice left, turn it off - if (m_iJuice <= 0) - { - pev->frame = 1; - Off(); - } - - // if the player doesn't have the suit, or there is no juice left, make the deny noise - if ((m_iJuice <= 0) || (!(pActivator->pev->weapons & (1 << WEAPON_SUIT)))) - { - if (m_flSoundTime <= gpGlobals->time) - { - m_flSoundTime = gpGlobals->time + 0.62; - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/suitchargeno1.wav", 0.85, ATTN_NORM); - } - return; - } - - pev->nextthink = pev->ltime + 0.25; - SetThink(Off); - - // Time to recharge yet? - - if (m_flNextCharge >= gpGlobals->time) - return; - - // Make sure that we have a caller - if (!pActivator) - return; - - m_hActivator = pActivator; - - //only recharge the player - - if (!m_hActivator->IsPlayer()) - return; - - // Play the on sound or the looping charging sound - if (!m_iOn) - { - m_iOn++; - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/suitchargeok1.wav", 0.85, ATTN_NORM); - m_flSoundTime = 0.56 + gpGlobals->time; - } - if ((m_iOn == 1) && (m_flSoundTime <= gpGlobals->time)) - { - m_iOn++; - EMIT_SOUND(ENT(pev), CHAN_STATIC, "items/suitcharge1.wav", 0.85, ATTN_NORM); - } - - // charge the player - if (m_hActivator->pev->armorvalue < 100) - { - m_iJuice--; - m_hActivator->pev->armorvalue += 1; - - if (m_hActivator->pev->armorvalue > 100) - m_hActivator->pev->armorvalue = 100; - } - - // govern the rate of charge - m_flNextCharge = gpGlobals->time + 0.1; -} - -void CRecharge::Recharge(void) -{ - m_iJuice = gSkillData.suitchargerCapacity; - pev->frame = 0; - SetThink(SUB_DoNothing); -} - -void CRecharge::Off(void) -{ - // Stop looping sound. - if (m_iOn > 1) - STOP_SOUND(ENT(pev), CHAN_STATIC, "items/suitcharge1.wav"); - - m_iOn = 0; - - if ((!m_iJuice) && ((m_iReactivate = g_pGameRules->FlHEVChargerRechargeTime()) > 0)) - { - pev->nextthink = pev->ltime + m_iReactivate; - SetThink(Recharge); - } - else - SetThink(SUB_DoNothing); -} \ No newline at end of file diff --git a/dlls/Half-life/h_cine.cpp b/dlls/Half-life/h_cine.cpp deleted file mode 100644 index 6f8fe577..00000000 --- a/dlls/Half-life/h_cine.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -/* - -===== h_cine.cpp ======================================================== - - The Halflife hard coded "scripted sequence". - - I'm pretty sure all this code is obsolete - -*/ - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "decals.h" - -class CLegacyCineMonster : public CBaseMonster -{ -public: - void CineSpawn(char *szModel); - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void EXPORT CineThink(void); - void Pain(void); - void Die(void); -}; - -class CCineScientist : public CLegacyCineMonster -{ -public: - void Spawn(void) { CineSpawn("models/cine-scientist.mdl"); } -}; -class CCine2Scientist : public CLegacyCineMonster -{ -public: - void Spawn(void) { CineSpawn("models/cine2-scientist.mdl"); } -}; -class CCinePanther : public CLegacyCineMonster -{ -public: - void Spawn(void) { CineSpawn("models/cine-panther.mdl"); } -}; - -class CCineBarney : public CLegacyCineMonster -{ -public: - void Spawn(void) { CineSpawn("models/cine-barney.mdl"); } -}; - -class CCine2HeavyWeapons : public CLegacyCineMonster -{ -public: - void Spawn(void) { CineSpawn("models/cine2_hvyweapons.mdl"); } -}; - -class CCine2Slave : public CLegacyCineMonster -{ -public: - void Spawn(void) { CineSpawn("models/cine2_slave.mdl"); } -}; - -class CCine3Scientist : public CLegacyCineMonster -{ -public: - void Spawn(void) { CineSpawn("models/cine3-scientist.mdl"); } -}; - -class CCine3Barney : public CLegacyCineMonster -{ -public: - void Spawn(void) { CineSpawn("models/cine3-barney.mdl"); } -}; - -// -// ********** Scientist SPAWN ********** -// - -LINK_ENTITY_TO_CLASS(monster_cine_scientist, CCineScientist); -LINK_ENTITY_TO_CLASS(monster_cine_panther, CCinePanther); -LINK_ENTITY_TO_CLASS(monster_cine_barney, CCineBarney); -LINK_ENTITY_TO_CLASS(monster_cine2_scientist, CCine2Scientist); -LINK_ENTITY_TO_CLASS(monster_cine2_hvyweapons, CCine2HeavyWeapons); -LINK_ENTITY_TO_CLASS(monster_cine2_slave, CCine2Slave); -LINK_ENTITY_TO_CLASS(monster_cine3_scientist, CCine3Scientist); -LINK_ENTITY_TO_CLASS(monster_cine3_barney, CCine3Barney); - -// -// ********** Scientist SPAWN ********** -// - -void CLegacyCineMonster ::CineSpawn(char *szModel) -{ - PRECACHE_MODEL(szModel); - SET_MODEL(ENT(pev), szModel); - UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 64)); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - pev->effects = 0; - pev->health = 1; - pev->yaw_speed = 10; - - // ugly alpha hack, can't set ints from the bsp. - pev->sequence = (int)pev->impulse; - ResetSequenceInfo(); - pev->framerate = 0.0; - - m_bloodColor = BLOOD_COLOR_RED; - - // if no targetname, start now - if (FStringNull(pev->targetname)) - { - SetThink(CineThink); - pev->nextthink += 1.0; - } -} - -// -// CineStart -// -void CLegacyCineMonster ::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - pev->animtime = 0; // reset the sequence - SetThink(CineThink); - pev->nextthink = gpGlobals->time; -} - -// -// ********** Scientist DIE ********** -// -void CLegacyCineMonster ::Die(void) -{ - SetThink(SUB_Remove); -} - -// -// ********** Scientist PAIN ********** -// -void CLegacyCineMonster ::Pain(void) -{ - EMIT_SOUND(ENT(pev), CHAN_VOICE, "player/pain3.wav", 1, ATTN_NORM); -} - -void CLegacyCineMonster ::CineThink(void) -{ - // DBG_CheckMonsterData(pev); - - // Emit particles from origin (double check animator's placement of model) - // THIS is a test feature - //UTIL_ParticleEffect(pev->origin, g_vecZero, 255, 20); - - if (!pev->animtime) - ResetSequenceInfo(); - - pev->nextthink = gpGlobals->time + 1.0; - - if (pev->spawnflags != 0 && m_fSequenceFinished) - { - Die(); - return; - } - - StudioFrameAdvance(); -} - -// -// cine_blood -// -// e3/prealpha only. -class CCineBlood : public CBaseEntity -{ -public: - void Spawn(void); - void EXPORT BloodStart(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void EXPORT BloodGush(void); -}; - -LINK_ENTITY_TO_CLASS(cine_blood, CCineBlood); - -void CCineBlood ::BloodGush(void) -{ - Vector vecSplatDir; - TraceResult tr; - pev->nextthink = gpGlobals->time + 0.1; - - UTIL_MakeVectors(pev->angles); - if (pev->health-- < 0) - REMOVE_ENTITY(ENT(pev)); - // CHANGE_METHOD ( ENT(pev), em_think, SUB_Remove ); - - if (RANDOM_FLOAT(0, 1) < 0.7) // larger chance of globs - { - UTIL_BloodDrips(pev->origin, UTIL_RandomBloodVector(), BLOOD_COLOR_RED, 10); - } - else // slim chance of geyser - { - UTIL_BloodStream(pev->origin, UTIL_RandomBloodVector(), BLOOD_COLOR_RED, RANDOM_LONG(50, 150)); - } - - if (RANDOM_FLOAT(0, 1) < 0.75) - { // decals the floor with blood. - vecSplatDir = Vector(0, 0, -1); - vecSplatDir = vecSplatDir + (RANDOM_FLOAT(-1, 1) * 0.6 * gpGlobals->v_right) + (RANDOM_FLOAT(-1, 1) * 0.6 * gpGlobals->v_forward); // randomize a bit - UTIL_TraceLine(pev->origin + Vector(0, 0, 64), pev->origin + vecSplatDir * 256, ignore_monsters, ENT(pev), &tr); - if (tr.flFraction != 1.0) - { - // Decal with a bloodsplat - UTIL_BloodDecalTrace(&tr, BLOOD_COLOR_RED); - } - } -} - -void CCineBlood ::BloodStart(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - SetThink(BloodGush); - pev->nextthink = gpGlobals->time; // now! -} - -void CCineBlood ::Spawn(void) -{ - pev->solid = SOLID_NOT; - SetUse(BloodStart); - pev->health = 20; //hacked health to count iterations -} diff --git a/dlls/Half-life/h_cycler.cpp b/dlls/Half-life/h_cycler.cpp deleted file mode 100644 index cae90694..00000000 --- a/dlls/Half-life/h_cycler.cpp +++ /dev/null @@ -1,441 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -/* - -===== h_cycler.cpp ======================================================== - - The Halflife Cycler Monsters - -*/ - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "animation.h" -#include "weapons.h" -#include "player.h" - -#define TEMP_FOR_SCREEN_SHOTS -#ifdef TEMP_FOR_SCREEN_SHOTS //=================================================== - -class CCycler : public CBaseMonster -{ -public: - void GenericCyclerSpawn(char *szModel, Vector vecMin, Vector vecMax); - virtual int ObjectCaps(void) { return (CBaseEntity ::ObjectCaps() | FCAP_IMPULSE_USE); } - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - void Spawn(void); - void Think(void); - //void Pain( float flDamage ); - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - - // Don't treat as a live target - virtual BOOL IsAlive(void) { return FALSE; } - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - int m_animate; -}; - -TYPEDESCRIPTION CCycler::m_SaveData[] = - { - DEFINE_FIELD(CCycler, m_animate, FIELD_INTEGER), -}; - -IMPLEMENT_SAVERESTORE(CCycler, CBaseMonster); - -// -// we should get rid of all the other cyclers and replace them with this. -// -class CGenericCycler : public CCycler -{ -public: - void Spawn(void) { GenericCyclerSpawn((char *)STRING(pev->model), Vector(-16, -16, 0), Vector(16, 16, 72)); } -}; -LINK_ENTITY_TO_CLASS(cycler, CGenericCycler); - -// Probe droid imported for tech demo compatibility -// -// PROBE DROID -// -class CCyclerProbe : public CCycler -{ -public: - void Spawn(void); -}; -LINK_ENTITY_TO_CLASS(cycler_prdroid, CCyclerProbe); -void CCyclerProbe ::Spawn(void) -{ - pev->origin = pev->origin + Vector(0, 0, 16); - GenericCyclerSpawn("models/prdroid.mdl", Vector(-16, -16, -16), Vector(16, 16, 16)); -} - -// Cycler member functions - -void CCycler ::GenericCyclerSpawn(char *szModel, Vector vecMin, Vector vecMax) -{ - if (!szModel || !*szModel) - { - ALERT(at_error, "cycler at %.0f %.0f %0.f missing modelname", pev->origin.x, pev->origin.y, pev->origin.z); - REMOVE_ENTITY(ENT(pev)); - return; - } - - pev->classname = MAKE_STRING("cycler"); - PRECACHE_MODEL(szModel); - SET_MODEL(ENT(pev), szModel); - - CCycler::Spawn(); - - UTIL_SetSize(pev, vecMin, vecMax); -} - -void CCycler ::Spawn() -{ - InitBoneControllers(); - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_NONE; - pev->takedamage = DAMAGE_YES; - pev->effects = 0; - pev->health = 80000; // no cycler should die - pev->yaw_speed = 5; - pev->ideal_yaw = pev->angles.y; - ChangeYaw(360); - - m_flFrameRate = 75; - m_flGroundSpeed = 0; - - pev->nextthink += 1.0; - - ResetSequenceInfo(); - - if (pev->sequence != 0 || pev->frame != 0) - { - m_animate = 0; - pev->framerate = 0; - } - else - { - m_animate = 1; - } -} - -// -// cycler think -// -void CCycler ::Think(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - if (m_animate) - { - StudioFrameAdvance(); - } - if (m_fSequenceFinished && !m_fSequenceLoops) - { - // ResetSequenceInfo(); - // hack to avoid reloading model every frame - pev->animtime = gpGlobals->time; - pev->framerate = 1.0; - m_fSequenceFinished = FALSE; - m_flLastEventCheck = gpGlobals->time; - pev->frame = 0; - if (!m_animate) - pev->framerate = 0.0; // FIX: don't reset framerate - } -} - -// -// CyclerUse - starts a rotation trend -// -void CCycler ::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - m_animate = !m_animate; - if (m_animate) - pev->framerate = 1.0; - else - pev->framerate = 0.0; -} - -// -// CyclerPain , changes sequences when shot -// -//void CCycler :: Pain( float flDamage ) -int CCycler ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (m_animate) - { - pev->sequence++; - - ResetSequenceInfo(); - - if (m_flFrameRate == 0.0) - { - pev->sequence = 0; - ResetSequenceInfo(); - } - pev->frame = 0; - } - else - { - pev->framerate = 1.0; - StudioFrameAdvance(0.1); - pev->framerate = 0; - ALERT(at_console, "sequence: %d, frame %.0f\n", pev->sequence, pev->frame); - } - - return 0; -} - -#endif - -class CCyclerSprite : public CBaseEntity -{ -public: - void Spawn(void); - void Think(void); - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - virtual int ObjectCaps(void) { return (CBaseEntity ::ObjectCaps() | FCAP_DONT_SAVE | FCAP_IMPULSE_USE); } - virtual int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - void Animate(float frames); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - inline int ShouldAnimate(void) { return m_animate && m_maxFrame > 1.0; } - int m_animate; - float m_lastTime; - float m_maxFrame; -}; - -LINK_ENTITY_TO_CLASS(cycler_sprite, CCyclerSprite); - -TYPEDESCRIPTION CCyclerSprite::m_SaveData[] = - { - DEFINE_FIELD(CCyclerSprite, m_animate, FIELD_INTEGER), - DEFINE_FIELD(CCyclerSprite, m_lastTime, FIELD_TIME), - DEFINE_FIELD(CCyclerSprite, m_maxFrame, FIELD_FLOAT), -}; - -IMPLEMENT_SAVERESTORE(CCyclerSprite, CBaseEntity); - -void CCyclerSprite::Spawn(void) -{ - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_NONE; - pev->takedamage = DAMAGE_YES; - pev->effects = 0; - - pev->frame = 0; - pev->nextthink = gpGlobals->time + 0.1; - m_animate = 1; - m_lastTime = gpGlobals->time; - - PRECACHE_MODEL((char *)STRING(pev->model)); - SET_MODEL(ENT(pev), STRING(pev->model)); - - m_maxFrame = (float)MODEL_FRAMES(pev->modelindex) - 1; -} - -void CCyclerSprite::Think(void) -{ - if (ShouldAnimate()) - Animate(pev->framerate * (gpGlobals->time - m_lastTime)); - - pev->nextthink = gpGlobals->time + 0.1; - m_lastTime = gpGlobals->time; -} - -void CCyclerSprite::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - m_animate = !m_animate; - ALERT(at_console, "Sprite: %s\n", STRING(pev->model)); -} - -int CCyclerSprite::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (m_maxFrame > 1.0) - { - Animate(1.0); - } - return 1; -} - -void CCyclerSprite::Animate(float frames) -{ - pev->frame += frames; - if (m_maxFrame > 0) - pev->frame = fmod(pev->frame, m_maxFrame); -} - -class CWeaponCycler : public CBasePlayerWeapon -{ -public: - void Spawn(void); - int iItemSlot(void) { return 1; } - int GetItemInfo(ItemInfo *p) { return 0; } - - void PrimaryAttack(void); - void SecondaryAttack(void); - BOOL Deploy(void); - void Holster(int skiplocal = 0); - int m_iszModel; - int m_iModel; -}; -LINK_ENTITY_TO_CLASS(cycler_weapon, CWeaponCycler); - -void CWeaponCycler::Spawn() -{ - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_NONE; - - PRECACHE_MODEL((char *)STRING(pev->model)); - SET_MODEL(ENT(pev), STRING(pev->model)); - m_iszModel = pev->model; - m_iModel = pev->modelindex; - - UTIL_SetOrigin(pev, pev->origin); - UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 16)); - SetTouch(DefaultTouch); -} - -BOOL CWeaponCycler::Deploy() -{ - m_pPlayer->pev->viewmodel = m_iszModel; - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0; - SendWeaponAnim(0); - m_iClip = 0; - return TRUE; -} - -void CWeaponCycler::Holster(int skiplocal /* = 0 */) -{ - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; -} - -void CWeaponCycler::PrimaryAttack() -{ - - SendWeaponAnim(pev->sequence); - - m_flNextPrimaryAttack = gpGlobals->time + 0.3; -} - -void CWeaponCycler::SecondaryAttack(void) -{ - float flFrameRate, flGroundSpeed; - - pev->sequence = (pev->sequence + 1) % 8; - - pev->modelindex = m_iModel; - void *pmodel = GET_MODEL_PTR(ENT(pev)); - GetSequenceInfo(pmodel, pev, &flFrameRate, &flGroundSpeed); - pev->modelindex = 0; - - if (flFrameRate == 0.0) - { - pev->sequence = 0; - } - - SendWeaponAnim(pev->sequence); - - m_flNextSecondaryAttack = gpGlobals->time + 0.3; -} - -// Flaming Wreakage -class CWreckage : public CBaseMonster -{ - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void Spawn(void); - void Precache(void); - void Think(void); - - int m_flStartTime; -}; -TYPEDESCRIPTION CWreckage::m_SaveData[] = - { - DEFINE_FIELD(CWreckage, m_flStartTime, FIELD_TIME), -}; -IMPLEMENT_SAVERESTORE(CWreckage, CBaseMonster); - -LINK_ENTITY_TO_CLASS(cycler_wreckage, CWreckage); - -void CWreckage::Spawn(void) -{ - pev->solid = SOLID_NOT; - pev->movetype = MOVETYPE_NONE; - pev->takedamage = 0; - pev->effects = 0; - - pev->frame = 0; - pev->nextthink = gpGlobals->time + 0.1; - - if (pev->model) - { - PRECACHE_MODEL((char *)STRING(pev->model)); - SET_MODEL(ENT(pev), STRING(pev->model)); - } - // pev->scale = 5.0; - - m_flStartTime = gpGlobals->time; -} - -void CWreckage::Precache() -{ - if (pev->model) - PRECACHE_MODEL((char *)STRING(pev->model)); -} - -void CWreckage::Think(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.2; - - if (pev->dmgtime) - { - if (pev->dmgtime < gpGlobals->time) - { - UTIL_Remove(this); - return; - } - else if (RANDOM_FLOAT(0, pev->dmgtime - m_flStartTime) > pev->dmgtime - gpGlobals->time) - { - return; - } - } - - Vector VecSrc; - - VecSrc.x = RANDOM_FLOAT(pev->absmin.x, pev->absmax.x); - VecSrc.y = RANDOM_FLOAT(pev->absmin.y, pev->absmax.y); - VecSrc.z = RANDOM_FLOAT(pev->absmin.z, pev->absmax.z); - - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, VecSrc); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(VecSrc.x); - WRITE_COORD(VecSrc.y); - WRITE_COORD(VecSrc.z); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(RANDOM_LONG(0, 49) + 50); // scale * 10 - WRITE_BYTE(RANDOM_LONG(0, 3) + 8); // framerate - MESSAGE_END(); -} diff --git a/dlls/Half-life/handgrenade.cpp b/dlls/Half-life/handgrenade.cpp deleted file mode 100644 index 7a94b018..00000000 --- a/dlls/Half-life/handgrenade.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" - -#define HANDGRENADE_PRIMARY_VOLUME 450 - -enum handgrenade_e -{ - HANDGRENADE_IDLE = 0, - HANDGRENADE_FIDGET, - HANDGRENADE_PINPULL, - HANDGRENADE_THROW1, // toss - HANDGRENADE_THROW2, // medium - HANDGRENADE_THROW3, // hard - HANDGRENADE_HOLSTER, - HANDGRENADE_DRAW -}; - -class CHandGrenade : public CBasePlayerWeapon -{ -public: - void Spawn(void); - void Precache(void); - int iItemSlot(void) { return 5; } - int GetItemInfo(ItemInfo *p); - - void PrimaryAttack(void); - BOOL Deploy(void); - BOOL CanHolster(void); - void Holster(int skiplocal = 0); - void WeaponIdle(void); - float m_flStartThrow; - float m_flReleaseThrow; -}; -LINK_ENTITY_TO_CLASS(weapon_handgrenade, CHandGrenade); - -void CHandGrenade::Spawn() -{ - Precache(); - m_iId = WEAPON_HANDGRENADE; - SET_MODEL(ENT(pev), "models/w_grenade.mdl"); - - pev->dmg = gSkillData.plrDmgHandGrenade; - - m_iDefaultAmmo = HANDGRENADE_DEFAULT_GIVE; - - FallInit(); // get ready to fall down. -} - -void CHandGrenade::Precache(void) -{ - PRECACHE_MODEL("models/w_grenade.mdl"); - PRECACHE_MODEL("models/v_grenade.mdl"); - PRECACHE_MODEL("models/p_grenade.mdl"); -} - -int CHandGrenade::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "Hand Grenade"; - p->iMaxAmmo1 = HANDGRENADE_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = WEAPON_NOCLIP; - p->iSlot = 4; - p->iPosition = 0; - p->iId = m_iId = WEAPON_HANDGRENADE; - p->iWeight = HANDGRENADE_WEIGHT; - p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE; - - return 1; -} - -BOOL CHandGrenade::Deploy() -{ - m_flReleaseThrow = -1; - return DefaultDeploy("models/v_grenade.mdl", "models/p_grenade.mdl", HANDGRENADE_DRAW, "crowbar"); -} - -BOOL CHandGrenade::CanHolster(void) -{ - // can only holster hand grenades when not primed! - return (m_flStartThrow == 0); -} - -void CHandGrenade::Holster(int skiplocal /* = 0 */) -{ - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - SendWeaponAnim(HANDGRENADE_HOLSTER); - } - else - { - // no more grenades! - m_pPlayer->pev->weapons &= ~(1 << WEAPON_HANDGRENADE); - SetThink(DestroyItem); - pev->nextthink = gpGlobals->time + 0.1; - } - - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM); -} - -void CHandGrenade::PrimaryAttack() -{ - if (!m_flStartThrow && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0) - { - m_flStartThrow = gpGlobals->time; - m_flReleaseThrow = 0; - - SendWeaponAnim(HANDGRENADE_PINPULL); - m_flTimeWeaponIdle = gpGlobals->time + 0.5; - } -} - -void CHandGrenade::WeaponIdle(void) -{ - if (m_flReleaseThrow == 0) - m_flReleaseThrow = gpGlobals->time; - - if (m_flTimeWeaponIdle > gpGlobals->time) - return; - - if (m_flStartThrow) - { - Vector angThrow = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle; - - if (angThrow.x < 0) - angThrow.x = -10 + angThrow.x * ((90 - 10) / 90.0); - else - angThrow.x = -10 + angThrow.x * ((90 + 10) / 90.0); - - float flVel = (90 - angThrow.x) * 4; - if (flVel > 500) - flVel = 500; - - UTIL_MakeVectors(angThrow); - - Vector vecSrc = m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16; - - Vector vecThrow = gpGlobals->v_forward * flVel + m_pPlayer->pev->velocity; - - // alway explode 3 seconds after the pin was pulled - float time = m_flStartThrow - gpGlobals->time + 3.0; - if (time < 0) - time = 0; - - CGrenade::ShootTimed(m_pPlayer->pev, vecSrc, vecThrow, time); - - if (flVel < 500) - { - SendWeaponAnim(HANDGRENADE_THROW1); - } - else if (flVel < 1000) - { - SendWeaponAnim(HANDGRENADE_THROW2); - } - else - { - SendWeaponAnim(HANDGRENADE_THROW3); - } - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - m_flStartThrow = 0; - m_flNextPrimaryAttack = gpGlobals->time + 0.5; - m_flTimeWeaponIdle = gpGlobals->time + 0.5; - - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; - - if (!m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - // just threw last grenade - // set attack times in the future, and weapon idle in the future so we can see the whole throw - // animation, weapon idle will automatically retire the weapon for us. - m_flTimeWeaponIdle = m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->time + 0.5; // ensure that the animation can finish playing - } - return; - } - else if (m_flReleaseThrow > 0) - { - // we've finished the throw, restart. - m_flStartThrow = 0; - - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - SendWeaponAnim(HANDGRENADE_DRAW); - } - else - { - RetireWeapon(); - return; - } - - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); - m_flReleaseThrow = -1; - return; - } - - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - int iAnim; - float flRand = RANDOM_FLOAT(0, 1); - if (flRand <= 0.75) - { - iAnim = HANDGRENADE_IDLE; - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); // how long till we do this again. - } - else - { - iAnim = HANDGRENADE_FIDGET; - m_flTimeWeaponIdle = gpGlobals->time + 75.0 / 30.0; - } - - SendWeaponAnim(iAnim); - } -} diff --git a/dlls/Half-life/hassassin.cpp b/dlls/Half-life/hassassin.cpp deleted file mode 100644 index 0512fb64..00000000 --- a/dlls/Half-life/hassassin.cpp +++ /dev/null @@ -1,976 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -//========================================================= -// hassassin - Human assassin, fast and stealthy -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" -#include "squadmonster.h" -#include "weapons.h" -#include "soundent.h" - -extern DLL_GLOBAL int g_iSkillLevel; - -//========================================================= -// monster-specific schedule types -//========================================================= -enum -{ - SCHED_ASSASSIN_EXPOSED = LAST_COMMON_SCHEDULE + 1, // cover was blown. - SCHED_ASSASSIN_JUMP, // fly through the air - SCHED_ASSASSIN_JUMP_ATTACK, // fly through the air and shoot - SCHED_ASSASSIN_JUMP_LAND, // hit and run away -}; - -//========================================================= -// monster-specific tasks -//========================================================= - -enum -{ - TASK_ASSASSIN_FALL_TO_GROUND = LAST_COMMON_TASK + 1, // falling and waiting to hit ground -}; - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define ASSASSIN_AE_SHOOT1 1 -#define ASSASSIN_AE_TOSS1 2 -#define ASSASSIN_AE_JUMP 3 - -#define bits_MEMORY_BADJUMP (bits_MEMORY_CUSTOM1) - -class CHAssassin : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int Classify(void); - int ISoundMask(void); - void Shoot(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - Schedule_t *GetSchedule(void); - Schedule_t *GetScheduleOfType(int Type); - BOOL CheckMeleeAttack1(float flDot, float flDist); // jump - // BOOL CheckMeleeAttack2 ( float flDot, float flDist ); - BOOL CheckRangeAttack1(float flDot, float flDist); // shoot - BOOL CheckRangeAttack2(float flDot, float flDist); // throw grenade - void StartTask(Task_t *pTask); - void RunAI(void); - void RunTask(Task_t *pTask); - void DeathSound(void); - void IdleSound(void); - CUSTOM_SCHEDULES; - - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - float m_flLastShot; - float m_flDiviation; - - float m_flNextJump; - Vector m_vecJumpVelocity; - - float m_flNextGrenadeCheck; - Vector m_vecTossVelocity; - BOOL m_fThrowGrenade; - - int m_iTargetRanderamt; - - int m_iFrustration; - - int m_iShell; -}; -LINK_ENTITY_TO_CLASS(monster_human_assassin, CHAssassin); - -TYPEDESCRIPTION CHAssassin::m_SaveData[] = - { - DEFINE_FIELD(CHAssassin, m_flLastShot, FIELD_TIME), - DEFINE_FIELD(CHAssassin, m_flDiviation, FIELD_FLOAT), - - DEFINE_FIELD(CHAssassin, m_flNextJump, FIELD_TIME), - DEFINE_FIELD(CHAssassin, m_vecJumpVelocity, FIELD_VECTOR), - - DEFINE_FIELD(CHAssassin, m_flNextGrenadeCheck, FIELD_TIME), - DEFINE_FIELD(CHAssassin, m_vecTossVelocity, FIELD_VECTOR), - DEFINE_FIELD(CHAssassin, m_fThrowGrenade, FIELD_BOOLEAN), - - DEFINE_FIELD(CHAssassin, m_iTargetRanderamt, FIELD_INTEGER), - DEFINE_FIELD(CHAssassin, m_iFrustration, FIELD_INTEGER), -}; - -IMPLEMENT_SAVERESTORE(CHAssassin, CBaseMonster); - -//========================================================= -// DieSound -//========================================================= -void CHAssassin ::DeathSound(void) -{ -} - -//========================================================= -// IdleSound -//========================================================= -void CHAssassin ::IdleSound(void) -{ -} - -//========================================================= -// ISoundMask - returns a bit mask indicating which types -// of sounds this monster regards. -//========================================================= -int CHAssassin ::ISoundMask(void) -{ - return bits_SOUND_WORLD | - bits_SOUND_COMBAT | - bits_SOUND_DANGER | - bits_SOUND_PLAYER; -} - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CHAssassin ::Classify(void) -{ - return CLASS_HUMAN_MILITARY; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CHAssassin ::SetYawSpeed(void) -{ - int ys; - - switch (m_Activity) - { - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - ys = 360; - break; - default: - ys = 360; - break; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// Shoot -//========================================================= -void CHAssassin ::Shoot(void) -{ - if (m_hEnemy == NULL) - { - return; - } - - Vector vecShootOrigin = GetGunPosition(); - Vector vecShootDir = ShootAtEnemy(vecShootOrigin); - - if (m_flLastShot + 2 < gpGlobals->time) - { - m_flDiviation = 0.10; - } - else - { - m_flDiviation -= 0.01; - if (m_flDiviation < 0.02) - m_flDiviation = 0.02; - } - m_flLastShot = gpGlobals->time; - - 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(pev->origin + gpGlobals->v_up * 32 + gpGlobals->v_forward * 12, vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHELL); - FireBullets(1, vecShootOrigin, vecShootDir, Vector(m_flDiviation, m_flDiviation, m_flDiviation), 2048, BULLET_MONSTER_9MM); // shoot +-8 degrees - - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/pl_gun1.wav", RANDOM_FLOAT(0.6, 0.8), ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/pl_gun2.wav", RANDOM_FLOAT(0.6, 0.8), ATTN_NORM); - break; - } - - pev->effects |= EF_MUZZLEFLASH; - - Vector angDir = UTIL_VecToAngles(vecShootDir); - SetBlending(0, angDir.x); - - m_cAmmoLoaded--; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -// -// Returns number of events handled, 0 if none. -//========================================================= -void CHAssassin ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case ASSASSIN_AE_SHOOT1: - Shoot(); - break; - case ASSASSIN_AE_TOSS1: - { - UTIL_MakeVectors(pev->angles); - CGrenade::ShootTimed(pev, pev->origin + gpGlobals->v_forward * 34 + Vector(0, 0, 32), m_vecTossVelocity, 2.0); - - m_flNextGrenadeCheck = gpGlobals->time + 6; // wait six seconds before even looking again to see if a grenade can be thrown. - m_fThrowGrenade = FALSE; - // !!!LATER - when in a group, only try to throw grenade if ordered. - } - break; - case ASSASSIN_AE_JUMP: - { - // ALERT( at_console, "jumping"); - UTIL_MakeAimVectors(pev->angles); - pev->movetype = MOVETYPE_TOSS; - pev->flags &= ~FL_ONGROUND; - pev->velocity = m_vecJumpVelocity; - m_flNextJump = gpGlobals->time + 3.0; - } - return; - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CHAssassin ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/hassassin.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.hassassinHealth; - m_flFieldOfView = VIEW_FIELD_WIDE; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - m_afCapability = bits_CAP_MELEE_ATTACK1 | bits_CAP_DOORS_GROUP; - pev->friction = 1; - - m_HackedGunPos = Vector(0, 24, 48); - - m_iTargetRanderamt = 20; - pev->renderamt = 20; - pev->rendermode = kRenderTransTexture; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CHAssassin ::Precache() -{ - PRECACHE_MODEL("models/hassassin.mdl"); - - PRECACHE_SOUND("weapons/pl_gun1.wav"); - PRECACHE_SOUND("weapons/pl_gun2.wav"); - - PRECACHE_SOUND("debris/beamstart1.wav"); - - m_iShell = PRECACHE_MODEL("models/shell.mdl"); // brass shell -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - -//========================================================= -// Fail Schedule -//========================================================= -Task_t tlAssassinFail[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_WAIT_FACE_ENEMY, (float)2}, - // { TASK_WAIT_PVS, (float)0 }, - {TASK_SET_SCHEDULE, (float)SCHED_CHASE_ENEMY}, -}; - -Schedule_t slAssassinFail[] = - { - {tlAssassinFail, - ARRAYSIZE(tlAssassinFail), - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_PROVOKED | - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_RANGE_ATTACK2 | - bits_COND_CAN_MELEE_ATTACK1 | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER | - bits_SOUND_PLAYER, - "AssassinFail"}, -}; - -//========================================================= -// Enemy exposed Agrunt's cover -//========================================================= -Task_t tlAssassinExposed[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_ASSASSIN_JUMP}, - {TASK_SET_SCHEDULE, (float)SCHED_TAKE_COVER_FROM_ENEMY}, -}; - -Schedule_t slAssassinExposed[] = - { - { - tlAssassinExposed, - ARRAYSIZE(tlAssassinExposed), - bits_COND_CAN_MELEE_ATTACK1, - 0, - "AssassinExposed", - }, -}; - -//========================================================= -// Take cover from enemy! Tries lateral cover before node -// cover! -//========================================================= -Task_t tlAssassinTakeCoverFromEnemy[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_WAIT, (float)0.2}, - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_RANGE_ATTACK1}, - {TASK_FIND_COVER_FROM_ENEMY, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_REMEMBER, (float)bits_MEMORY_INCOVER}, - {TASK_FACE_ENEMY, (float)0}, -}; - -Schedule_t slAssassinTakeCoverFromEnemy[] = - { - {tlAssassinTakeCoverFromEnemy, - ARRAYSIZE(tlAssassinTakeCoverFromEnemy), - bits_COND_NEW_ENEMY | - bits_COND_CAN_MELEE_ATTACK1 | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER, - "AssassinTakeCoverFromEnemy"}, -}; - -//========================================================= -// Take cover from enemy! Tries lateral cover before node -// cover! -//========================================================= -Task_t tlAssassinTakeCoverFromEnemy2[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_WAIT, (float)0.2}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_RANGE_ATTACK2}, - {TASK_FIND_FAR_NODE_COVER_FROM_ENEMY, (float)384}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_REMEMBER, (float)bits_MEMORY_INCOVER}, - {TASK_FACE_ENEMY, (float)0}, -}; - -Schedule_t slAssassinTakeCoverFromEnemy2[] = - { - {tlAssassinTakeCoverFromEnemy2, - ARRAYSIZE(tlAssassinTakeCoverFromEnemy2), - bits_COND_NEW_ENEMY | - bits_COND_CAN_MELEE_ATTACK2 | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER, - "AssassinTakeCoverFromEnemy2"}, -}; - -//========================================================= -// hide from the loudest sound source -//========================================================= -Task_t tlAssassinTakeCoverFromBestSound[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_MELEE_ATTACK1}, - {TASK_STOP_MOVING, (float)0}, - {TASK_FIND_COVER_FROM_BEST_SOUND, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_REMEMBER, (float)bits_MEMORY_INCOVER}, - {TASK_TURN_LEFT, (float)179}, -}; - -Schedule_t slAssassinTakeCoverFromBestSound[] = - { - {tlAssassinTakeCoverFromBestSound, - ARRAYSIZE(tlAssassinTakeCoverFromBestSound), - bits_COND_NEW_ENEMY, - 0, - "AssassinTakeCoverFromBestSound"}, -}; - -//========================================================= -// AlertIdle Schedules -//========================================================= -Task_t tlAssassinHide[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_WAIT, (float)2}, - {TASK_SET_SCHEDULE, (float)SCHED_CHASE_ENEMY}, -}; - -Schedule_t slAssassinHide[] = - { - {tlAssassinHide, - ARRAYSIZE(tlAssassinHide), - bits_COND_NEW_ENEMY | - bits_COND_SEE_ENEMY | - bits_COND_SEE_FEAR | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_PROVOKED | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER, - "AssassinHide"}, -}; - -//========================================================= -// HUNT Schedules -//========================================================= -Task_t tlAssassinHunt[] = - { - {TASK_GET_PATH_TO_ENEMY, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, -}; - -Schedule_t slAssassinHunt[] = - { - {tlAssassinHunt, - ARRAYSIZE(tlAssassinHunt), - bits_COND_NEW_ENEMY | - // bits_COND_SEE_ENEMY | - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER, - "AssassinHunt"}, -}; - -//========================================================= -// Jumping Schedules -//========================================================= -Task_t tlAssassinJump[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_HOP}, - {TASK_SET_SCHEDULE, (float)SCHED_ASSASSIN_JUMP_ATTACK}, -}; - -Schedule_t slAssassinJump[] = - { - {tlAssassinJump, - ARRAYSIZE(tlAssassinJump), - 0, - 0, - "AssassinJump"}, -}; - -//========================================================= -// repel -//========================================================= -Task_t tlAssassinJumpAttack[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_ASSASSIN_JUMP_LAND}, - // { TASK_SET_ACTIVITY, (float)ACT_FLY }, - {TASK_ASSASSIN_FALL_TO_GROUND, (float)0}, -}; - -Schedule_t slAssassinJumpAttack[] = - { - {tlAssassinJumpAttack, - ARRAYSIZE(tlAssassinJumpAttack), - 0, - 0, - "AssassinJumpAttack"}, -}; - -//========================================================= -// repel -//========================================================= -Task_t tlAssassinJumpLand[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_ASSASSIN_EXPOSED}, - // { TASK_SET_FAIL_SCHEDULE, (float)SCHED_MELEE_ATTACK1 }, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_REMEMBER, (float)bits_MEMORY_BADJUMP}, - {TASK_FIND_NODE_COVER_FROM_ENEMY, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_FORGET, (float)bits_MEMORY_BADJUMP}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_REMEMBER, (float)bits_MEMORY_INCOVER}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_RANGE_ATTACK1}, -}; - -Schedule_t slAssassinJumpLand[] = - { - {tlAssassinJumpLand, - ARRAYSIZE(tlAssassinJumpLand), - 0, - 0, - "AssassinJumpLand"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CHAssassin){ - slAssassinFail, - slAssassinExposed, - slAssassinTakeCoverFromEnemy, - slAssassinTakeCoverFromEnemy2, - slAssassinTakeCoverFromBestSound, - slAssassinHide, - slAssassinHunt, - slAssassinJump, - slAssassinJumpAttack, - slAssassinJumpLand, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CHAssassin, CBaseMonster); - -//========================================================= -// CheckMeleeAttack1 - jump like crazy if the enemy gets too close. -//========================================================= -BOOL CHAssassin ::CheckMeleeAttack1(float flDot, float flDist) -{ - if (m_flNextJump < gpGlobals->time && (flDist <= 128 || HasMemory(bits_MEMORY_BADJUMP)) && m_hEnemy != NULL) - { - TraceResult tr; - - Vector vecDest = pev->origin + Vector(RANDOM_FLOAT(-64, 64), RANDOM_FLOAT(-64, 64), 160); - - UTIL_TraceHull(pev->origin + Vector(0, 0, 36), vecDest + Vector(0, 0, 36), dont_ignore_monsters, human_hull, ENT(pev), &tr); - - if (tr.fStartSolid || tr.flFraction < 1.0) - { - return FALSE; - } - - float flGravity = CVAR_GET_FLOAT("sv_gravity"); - - float time = sqrt(160 / (0.5 * flGravity)); - float speed = flGravity * time / 160; - m_vecJumpVelocity = (vecDest - pev->origin) * speed; - - return TRUE; - } - return FALSE; -} - -//========================================================= -// CheckRangeAttack1 - drop a cap in their ass -// -//========================================================= -BOOL CHAssassin ::CheckRangeAttack1(float flDot, float flDist) -{ - if (!HasConditions(bits_COND_ENEMY_OCCLUDED) && flDist > 64 && flDist <= 2048 /* && flDot >= 0.5 */ /* && NoFriendlyFire() */) - { - TraceResult tr; - - Vector vecSrc = GetGunPosition(); - - // verify that a bullet fired from the gun will hit the enemy before the world. - UTIL_TraceLine(vecSrc, m_hEnemy->BodyTarget(vecSrc), dont_ignore_monsters, ENT(pev), &tr); - - if (tr.flFraction == 1 || tr.pHit == m_hEnemy->edict()) - { - return TRUE; - } - } - return FALSE; -} - -//========================================================= -// CheckRangeAttack2 - toss grenade is enemy gets in the way and is too close. -//========================================================= -BOOL CHAssassin ::CheckRangeAttack2(float flDot, float flDist) -{ - m_fThrowGrenade = FALSE; - if (!FBitSet(m_hEnemy->pev->flags, FL_ONGROUND)) - { - // don't throw grenades at anything that isn't on the ground! - return FALSE; - } - - // don't get grenade happy unless the player starts to piss you off - if (m_iFrustration <= 2) - return FALSE; - - if (m_flNextGrenadeCheck < gpGlobals->time && !HasConditions(bits_COND_ENEMY_OCCLUDED) && flDist <= 512 /* && flDot >= 0.5 */ /* && NoFriendlyFire() */) - { - Vector vecToss = VecCheckThrow(pev, GetGunPosition(), m_hEnemy->Center(), flDist, 0.5); // use dist as speed to get there in 1 second - - if (vecToss != g_vecZero) - { - m_vecTossVelocity = vecToss; - - // throw a hand grenade - m_fThrowGrenade = TRUE; - - return TRUE; - } - } - - return FALSE; -} - -//========================================================= -// RunAI -//========================================================= -void CHAssassin ::RunAI(void) -{ - CBaseMonster ::RunAI(); - - // always visible if moving - // always visible is not on hard - if (g_iSkillLevel != SKILL_HARD || m_hEnemy == NULL || pev->deadflag != DEAD_NO || m_Activity == ACT_RUN || m_Activity == ACT_WALK || !(pev->flags & FL_ONGROUND)) - m_iTargetRanderamt = 255; - else - m_iTargetRanderamt = 20; - - if (pev->renderamt > m_iTargetRanderamt) - { - if (pev->renderamt == 255) - { - EMIT_SOUND(ENT(pev), CHAN_BODY, "debris/beamstart1.wav", 0.2, ATTN_NORM); - } - - pev->renderamt = max(pev->renderamt - 50, m_iTargetRanderamt); - pev->rendermode = kRenderTransTexture; - } - else if (pev->renderamt < m_iTargetRanderamt) - { - pev->renderamt = min(pev->renderamt + 50, m_iTargetRanderamt); - if (pev->renderamt == 255) - pev->rendermode = kRenderNormal; - } - - if (m_Activity == ACT_RUN || m_Activity == ACT_WALK) - { - static int iStep = 0; - iStep = !iStep; - if (iStep) - { - switch (RANDOM_LONG(0, 3)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_BODY, "player/pl_step1.wav", 0.5, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_BODY, "player/pl_step3.wav", 0.5, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_BODY, "player/pl_step2.wav", 0.5, ATTN_NORM); - break; - case 3: - EMIT_SOUND(ENT(pev), CHAN_BODY, "player/pl_step4.wav", 0.5, ATTN_NORM); - break; - } - } - } -} - -//========================================================= -// StartTask -//========================================================= -void CHAssassin ::StartTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_RANGE_ATTACK2: - if (!m_fThrowGrenade) - { - TaskComplete(); - } - else - { - CBaseMonster ::StartTask(pTask); - } - break; - case TASK_ASSASSIN_FALL_TO_GROUND: - break; - default: - CBaseMonster ::StartTask(pTask); - break; - } -} - -//========================================================= -// RunTask -//========================================================= -void CHAssassin ::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_ASSASSIN_FALL_TO_GROUND: - MakeIdealYaw(m_vecEnemyLKP); - ChangeYaw(pev->yaw_speed); - - if (m_fSequenceFinished) - { - if (pev->velocity.z > 0) - { - pev->sequence = LookupSequence("fly_up"); - } - else if (HasConditions(bits_COND_SEE_ENEMY)) - { - pev->sequence = LookupSequence("fly_attack"); - pev->frame = 0; - } - else - { - pev->sequence = LookupSequence("fly_down"); - pev->frame = 0; - } - - ResetSequenceInfo(); - SetYawSpeed(); - } - if (pev->flags & FL_ONGROUND) - { - // ALERT( at_console, "on ground\n"); - TaskComplete(); - } - break; - default: - CBaseMonster ::RunTask(pTask); - break; - } -} - -//========================================================= -// GetSchedule - Decides which type of schedule best suits -// the monster's current state and conditions. Then calls -// monster's member function to get a pointer to a schedule -// of the proper type. -//========================================================= -Schedule_t *CHAssassin ::GetSchedule(void) -{ - switch (m_MonsterState) - { - case MONSTERSTATE_IDLE: - case MONSTERSTATE_ALERT: - { - if (HasConditions(bits_COND_HEAR_SOUND)) - { - CSound *pSound; - pSound = PBestSound(); - - ASSERT(pSound != NULL); - if (pSound && (pSound->m_iType & bits_SOUND_DANGER)) - { - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_BEST_SOUND); - } - if (pSound && (pSound->m_iType & bits_SOUND_COMBAT)) - { - return GetScheduleOfType(SCHED_INVESTIGATE_SOUND); - } - } - } - break; - - case MONSTERSTATE_COMBAT: - { - // dead enemy - if (HasConditions(bits_COND_ENEMY_DEAD)) - { - // call base class, all code to handle dead enemies is centralized there. - return CBaseMonster ::GetSchedule(); - } - - // flying? - if (pev->movetype == MOVETYPE_TOSS) - { - if (pev->flags & FL_ONGROUND) - { - // ALERT( at_console, "landed\n"); - // just landed - pev->movetype = MOVETYPE_STEP; - return GetScheduleOfType(SCHED_ASSASSIN_JUMP_LAND); - } - else - { - // ALERT( at_console, "jump\n"); - // jump or jump/shoot - if (m_MonsterState == MONSTERSTATE_COMBAT) - return GetScheduleOfType(SCHED_ASSASSIN_JUMP); - else - return GetScheduleOfType(SCHED_ASSASSIN_JUMP_ATTACK); - } - } - - if (HasConditions(bits_COND_HEAR_SOUND)) - { - CSound *pSound; - pSound = PBestSound(); - - ASSERT(pSound != NULL); - if (pSound && (pSound->m_iType & bits_SOUND_DANGER)) - { - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_BEST_SOUND); - } - } - - if (HasConditions(bits_COND_LIGHT_DAMAGE)) - { - m_iFrustration++; - } - if (HasConditions(bits_COND_HEAVY_DAMAGE)) - { - m_iFrustration++; - } - - // jump player! - if (HasConditions(bits_COND_CAN_MELEE_ATTACK1)) - { - // ALERT( at_console, "melee attack 1\n"); - return GetScheduleOfType(SCHED_MELEE_ATTACK1); - } - - // throw grenade - if (HasConditions(bits_COND_CAN_RANGE_ATTACK2)) - { - // ALERT( at_console, "range attack 2\n"); - return GetScheduleOfType(SCHED_RANGE_ATTACK2); - } - - // spotted - if (HasConditions(bits_COND_SEE_ENEMY) && HasConditions(bits_COND_ENEMY_FACING_ME)) - { - // ALERT( at_console, "exposed\n"); - m_iFrustration++; - return GetScheduleOfType(SCHED_ASSASSIN_EXPOSED); - } - - // can attack - if (HasConditions(bits_COND_CAN_RANGE_ATTACK1)) - { - // ALERT( at_console, "range attack 1\n"); - m_iFrustration = 0; - return GetScheduleOfType(SCHED_RANGE_ATTACK1); - } - - if (HasConditions(bits_COND_SEE_ENEMY)) - { - // ALERT( at_console, "face\n"); - return GetScheduleOfType(SCHED_COMBAT_FACE); - } - - // new enemy - if (HasConditions(bits_COND_NEW_ENEMY)) - { - // ALERT( at_console, "take cover\n"); - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_ENEMY); - } - - // ALERT( at_console, "stand\n"); - return GetScheduleOfType(SCHED_ALERT_STAND); - } - break; - } - - return CBaseMonster ::GetSchedule(); -} - -//========================================================= -//========================================================= -Schedule_t *CHAssassin ::GetScheduleOfType(int Type) -{ - // ALERT( at_console, "%d\n", m_iFrustration ); - switch (Type) - { - case SCHED_TAKE_COVER_FROM_ENEMY: - if (pev->health > 30) - return slAssassinTakeCoverFromEnemy; - else - return slAssassinTakeCoverFromEnemy2; - case SCHED_TAKE_COVER_FROM_BEST_SOUND: - return slAssassinTakeCoverFromBestSound; - case SCHED_ASSASSIN_EXPOSED: - return slAssassinExposed; - case SCHED_FAIL: - if (m_MonsterState == MONSTERSTATE_COMBAT) - return slAssassinFail; - break; - case SCHED_ALERT_STAND: - if (m_MonsterState == MONSTERSTATE_COMBAT) - return slAssassinHide; - break; - case SCHED_CHASE_ENEMY: - return slAssassinHunt; - case SCHED_MELEE_ATTACK1: - if (pev->flags & FL_ONGROUND) - { - if (m_flNextJump > gpGlobals->time) - { - // can't jump yet, go ahead and fail - return slAssassinFail; - } - else - { - return slAssassinJump; - } - } - else - { - return slAssassinJumpAttack; - } - case SCHED_ASSASSIN_JUMP: - case SCHED_ASSASSIN_JUMP_ATTACK: - return slAssassinJumpAttack; - case SCHED_ASSASSIN_JUMP_LAND: - return slAssassinJumpLand; - } - - return CBaseMonster ::GetScheduleOfType(Type); -} - -#endif \ No newline at end of file diff --git a/dlls/Half-life/headcrab.cpp b/dlls/Half-life/headcrab.cpp deleted file mode 100644 index 0a136d82..00000000 --- a/dlls/Half-life/headcrab.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// headcrab.cpp - tiny, jumpy alien parasite -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define HC_AE_JUMPATTACK (2) - -Task_t tlHCRangeAttack1[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_WAIT_RANDOM, (float)0.5}, -}; - -Schedule_t slHCRangeAttack1[] = - { - {tlHCRangeAttack1, - ARRAYSIZE(tlHCRangeAttack1), - bits_COND_ENEMY_OCCLUDED | - bits_COND_NO_AMMO_LOADED, - 0, - "HCRangeAttack1"}, -}; - -Task_t tlHCRangeAttack1Fast[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, -}; - -Schedule_t slHCRangeAttack1Fast[] = - { - {tlHCRangeAttack1Fast, - ARRAYSIZE(tlHCRangeAttack1Fast), - bits_COND_ENEMY_OCCLUDED | - bits_COND_NO_AMMO_LOADED, - 0, - "HCRAFast"}, -}; - -class CHeadCrab : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void RunTask(Task_t *pTask); - void StartTask(Task_t *pTask); - void SetYawSpeed(void); - void EXPORT LeapTouch(CBaseEntity *pOther); - Vector Center(void); - Vector BodyTarget(const Vector &posSrc); - void PainSound(void); - void DeathSound(void); - void IdleSound(void); - void AlertSound(void); - void PrescheduleThink(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - BOOL CheckRangeAttack1(float flDot, float flDist); - BOOL CheckRangeAttack2(float flDot, float flDist); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - - virtual float GetDamageAmount(void) { return gSkillData.headcrabDmgBite; } - virtual int GetVoicePitch(void) { return 100; } - virtual float GetSoundVolue(void) { return 1.0; } - Schedule_t *GetScheduleOfType(int Type); - - CUSTOM_SCHEDULES; - - static const char *pIdleSounds[]; - static const char *pAlertSounds[]; - static const char *pPainSounds[]; - static const char *pAttackSounds[]; - static const char *pDeathSounds[]; - static const char *pBiteSounds[]; -}; -LINK_ENTITY_TO_CLASS(monster_headcrab, CHeadCrab); - -DEFINE_CUSTOM_SCHEDULES(CHeadCrab){ - slHCRangeAttack1, - slHCRangeAttack1Fast, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CHeadCrab, CBaseMonster); - -const char *CHeadCrab::pIdleSounds[] = - { - "headcrab/hc_idle1.wav", - "headcrab/hc_idle2.wav", - "headcrab/hc_idle3.wav", -}; -const char *CHeadCrab::pAlertSounds[] = - { - "headcrab/hc_alert1.wav", -}; -const char *CHeadCrab::pPainSounds[] = - { - "headcrab/hc_pain1.wav", - "headcrab/hc_pain2.wav", - "headcrab/hc_pain3.wav", -}; -const char *CHeadCrab::pAttackSounds[] = - { - "headcrab/hc_attack1.wav", - "headcrab/hc_attack2.wav", - "headcrab/hc_attack3.wav", -}; - -const char *CHeadCrab::pDeathSounds[] = - { - "headcrab/hc_die1.wav", - "headcrab/hc_die2.wav", -}; - -const char *CHeadCrab::pBiteSounds[] = - { - "headcrab/hc_headbite.wav", -}; - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CHeadCrab ::Classify(void) -{ - return CLASS_ALIEN_PREY; -} - -//========================================================= -// Center - returns the real center of the headcrab. The -// bounding box is much larger than the actual creature so -// this is needed for targeting -//========================================================= -Vector CHeadCrab ::Center(void) -{ - return Vector(pev->origin.x, pev->origin.y, pev->origin.z + 6); -} - -Vector CHeadCrab ::BodyTarget(const Vector &posSrc) -{ - return Center(); -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CHeadCrab ::SetYawSpeed(void) -{ - int ys; - - switch (m_Activity) - { - case ACT_IDLE: - ys = 30; - break; - case ACT_RUN: - case ACT_WALK: - ys = 20; - break; - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - ys = 60; - break; - case ACT_RANGE_ATTACK1: - ys = 30; - break; - default: - ys = 30; - break; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CHeadCrab ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case HC_AE_JUMPATTACK: - { - ClearBits(pev->flags, FL_ONGROUND); - - UTIL_SetOrigin(pev, pev->origin + Vector(0, 0, 1)); // take him off ground so engine doesn't instantly reset onground - UTIL_MakeVectors(pev->angles); - - Vector vecJumpDir; - if (m_hEnemy != NULL) - { - float gravity = CVAR_GET_FLOAT("sv_gravity"); - if (gravity <= 1) - gravity = 1; - - // How fast does the headcrab need to travel to reach that height given gravity? - float height = (m_hEnemy->pev->origin.z + m_hEnemy->pev->view_ofs.z - pev->origin.z); - if (height < 16) - height = 16; - float speed = sqrt(2 * gravity * height); - float time = speed / gravity; - - // Scale the sideways velocity to get there at the right time - vecJumpDir = (m_hEnemy->pev->origin + m_hEnemy->pev->view_ofs - pev->origin); - vecJumpDir = vecJumpDir * (1.0 / time); - - // Speed to offset gravity at the desired height - vecJumpDir.z = speed; - - // Don't jump too far/fast - float distance = vecJumpDir.Length(); - - if (distance > 650) - { - vecJumpDir = vecJumpDir * (650.0 / distance); - } - } - else - { - // jump hop, don't care where - vecJumpDir = Vector(gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_up.z) * 350; - } - - int iSound = RANDOM_LONG(0, 2); - if (iSound != 0) - EMIT_SOUND_DYN(edict(), CHAN_VOICE, pAttackSounds[iSound], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch()); - - pev->velocity = vecJumpDir; - m_flNextAttack = gpGlobals->time + 2; - } - break; - - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CHeadCrab ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/headcrab.mdl"); - UTIL_SetSize(pev, Vector(-12, -12, 0), Vector(12, 12, 24)); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->effects = 0; - pev->health = gSkillData.headcrabHealth; - pev->view_ofs = Vector(0, 0, 20); // position of the eyes relative to monster's origin. - pev->yaw_speed = 5; //!!! should we put this in the monster's changeanim function since turn rates may vary with state/anim? - m_flFieldOfView = 0.5; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CHeadCrab ::Precache() -{ - PRECACHE_SOUND_ARRAY(pIdleSounds); - PRECACHE_SOUND_ARRAY(pAlertSounds); - PRECACHE_SOUND_ARRAY(pPainSounds); - PRECACHE_SOUND_ARRAY(pAttackSounds); - PRECACHE_SOUND_ARRAY(pDeathSounds); - PRECACHE_SOUND_ARRAY(pBiteSounds); - - PRECACHE_MODEL("models/headcrab.mdl"); -} - -//========================================================= -// RunTask -//========================================================= -void CHeadCrab ::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_RANGE_ATTACK1: - case TASK_RANGE_ATTACK2: - { - if (m_fSequenceFinished) - { - TaskComplete(); - SetTouch(NULL); - m_IdealActivity = ACT_IDLE; - } - break; - } - default: - { - CBaseMonster ::RunTask(pTask); - } - } -} - -//========================================================= -// LeapTouch - this is the headcrab's touch function when it -// is in the air -//========================================================= -void CHeadCrab ::LeapTouch(CBaseEntity *pOther) -{ - if (!pOther->pev->takedamage) - { - return; - } - - if (pOther->Classify() == Classify()) - { - return; - } - - // Don't hit if back on ground - if (!FBitSet(pev->flags, FL_ONGROUND)) - { - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pBiteSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch()); - - pOther->TakeDamage(pev, pev, GetDamageAmount(), DMG_SLASH); - } - - SetTouch(NULL); -} - -//========================================================= -// PrescheduleThink -//========================================================= -void CHeadCrab ::PrescheduleThink(void) -{ - // make the crab coo a little bit in combat state - if (m_MonsterState == MONSTERSTATE_COMBAT && RANDOM_FLOAT(0, 5) < 0.1) - { - IdleSound(); - } -} - -void CHeadCrab ::StartTask(Task_t *pTask) -{ - m_iTaskStatus = TASKSTATUS_RUNNING; - - switch (pTask->iTask) - { - case TASK_RANGE_ATTACK1: - { - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, pAttackSounds[0], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch()); - m_IdealActivity = ACT_RANGE_ATTACK1; - SetTouch(LeapTouch); - break; - } - default: - { - CBaseMonster ::StartTask(pTask); - } - } -} - -//========================================================= -// CheckRangeAttack1 -//========================================================= -BOOL CHeadCrab ::CheckRangeAttack1(float flDot, float flDist) -{ - if (FBitSet(pev->flags, FL_ONGROUND) && flDist <= 256 && flDot >= 0.65) - { - return TRUE; - } - return FALSE; -} - -//========================================================= -// CheckRangeAttack2 -//========================================================= -BOOL CHeadCrab ::CheckRangeAttack2(float flDot, float flDist) -{ - return FALSE; - // BUGBUG: Why is this code here? There is no ACT_RANGE_ATTACK2 animation. I've disabled it for now. -#if 0 - if ( FBitSet( pev->flags, FL_ONGROUND ) && flDist > 64 && flDist <= 256 && flDot >= 0.5 ) - { - return TRUE; - } - return FALSE; -#endif -} - -int CHeadCrab ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - // Don't take any acid damage -- BigMomma's mortar is acid - if (bitsDamageType & DMG_ACID) - flDamage = 0; - - return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -//========================================================= -// IdleSound -//========================================================= -#define CRAB_ATTN_IDLE (float)1.5 -void CHeadCrab ::IdleSound(void) -{ - EMIT_SOUND_DYN(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pIdleSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch()); -} - -//========================================================= -// AlertSound -//========================================================= -void CHeadCrab ::AlertSound(void) -{ - EMIT_SOUND_DYN(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAlertSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch()); -} - -//========================================================= -// AlertSound -//========================================================= -void CHeadCrab ::PainSound(void) -{ - EMIT_SOUND_DYN(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pPainSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch()); -} - -//========================================================= -// DeathSound -//========================================================= -void CHeadCrab ::DeathSound(void) -{ - EMIT_SOUND_DYN(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDeathSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch()); -} - -Schedule_t *CHeadCrab ::GetScheduleOfType(int Type) -{ - switch (Type) - { - case SCHED_RANGE_ATTACK1: - { - return &slHCRangeAttack1[0]; - } - break; - } - - return CBaseMonster::GetScheduleOfType(Type); -} - -class CBabyCrab : public CHeadCrab -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - float GetDamageAmount(void) { return gSkillData.headcrabDmgBite * 0.3; } - BOOL CheckRangeAttack1(float flDot, float flDist); - Schedule_t *GetScheduleOfType(int Type); - virtual int GetVoicePitch(void) { return PITCH_NORM + RANDOM_LONG(40, 50); } - virtual float GetSoundVolue(void) { return 0.8; } -}; -LINK_ENTITY_TO_CLASS(monster_babycrab, CBabyCrab); - -void CBabyCrab ::Spawn(void) -{ - CHeadCrab::Spawn(); - SET_MODEL(ENT(pev), "models/baby_headcrab.mdl"); - pev->rendermode = kRenderTransTexture; - pev->renderamt = 192; - UTIL_SetSize(pev, Vector(-12, -12, 0), Vector(12, 12, 24)); - - pev->health = gSkillData.headcrabHealth * 0.25; // less health than full grown -} - -void CBabyCrab ::Precache(void) -{ - PRECACHE_MODEL("models/baby_headcrab.mdl"); - CHeadCrab::Precache(); -} - -void CBabyCrab ::SetYawSpeed(void) -{ - pev->yaw_speed = 120; -} - -BOOL CBabyCrab ::CheckRangeAttack1(float flDot, float flDist) -{ - if (pev->flags & FL_ONGROUND) - { - if (pev->groundentity && (pev->groundentity->v.flags & (FL_CLIENT | FL_MONSTER))) - return TRUE; - - // A little less accurate, but jump from closer - if (flDist <= 180 && flDot >= 0.55) - return TRUE; - } - - return FALSE; -} - -Schedule_t *CBabyCrab ::GetScheduleOfType(int Type) -{ - switch (Type) - { - case SCHED_FAIL: // If you fail, try to jump! - if (m_hEnemy != NULL) - return slHCRangeAttack1Fast; - break; - - case SCHED_RANGE_ATTACK1: - { - return slHCRangeAttack1Fast; - } - break; - } - - return CHeadCrab::GetScheduleOfType(Type); -} diff --git a/dlls/Half-life/healthkit.cpp b/dlls/Half-life/healthkit.cpp deleted file mode 100644 index 3dcbd528..00000000 --- a/dlls/Half-life/healthkit.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "items.h" -#include "gamerules.h" - -extern int gmsgItemPickup; - -class CHealthKit : public CItem -{ - void Spawn(void); - void Precache(void); - BOOL MyTouch(CBasePlayer *pPlayer); - - /* - virtual int Save( CSave &save ); - virtual int Restore( CRestore &restore ); - - static TYPEDESCRIPTION m_SaveData[]; -*/ -}; - -LINK_ENTITY_TO_CLASS(item_healthkit, CHealthKit); - -/* -TYPEDESCRIPTION CHealthKit::m_SaveData[] = -{ - -}; - - -IMPLEMENT_SAVERESTORE( CHealthKit, CItem); -*/ - -void CHealthKit ::Spawn(void) -{ - Precache(); - SET_MODEL(ENT(pev), "models/w_medkit.mdl"); - - CItem::Spawn(); -} - -void CHealthKit::Precache(void) -{ - PRECACHE_MODEL("models/w_medkit.mdl"); - PRECACHE_SOUND("items/smallmedkit1.wav"); -} - -BOOL CHealthKit::MyTouch(CBasePlayer *pPlayer) -{ - if (pPlayer->TakeHealth(gSkillData.healthkitCapacity, DMG_GENERIC)) - { - MESSAGE_BEGIN(MSG_ONE, gmsgItemPickup, NULL, pPlayer->pev); - WRITE_STRING(STRING(pev->classname)); - MESSAGE_END(); - - EMIT_SOUND(ENT(pPlayer->pev), CHAN_ITEM, "items/smallmedkit1.wav", 1, ATTN_NORM); - - if (g_pGameRules->ItemShouldRespawn(this)) - { - Respawn(); - } - else - { - UTIL_Remove(this); - } - - return TRUE; - } - - return FALSE; -} - -//------------------------------------------------------------- -// Wall mounted health kit -//------------------------------------------------------------- -class CWallHealth : public CBaseToggle -{ -public: - void Spawn(); - void Precache(void); - void EXPORT Off(void); - void EXPORT Recharge(void); - void KeyValue(KeyValueData *pkvd); - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - virtual int ObjectCaps(void) { return (CBaseToggle ::ObjectCaps() | FCAP_CONTINUOUS_USE) & ~FCAP_ACROSS_TRANSITION; } - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - - static TYPEDESCRIPTION m_SaveData[]; - - float m_flNextCharge; - int m_iReactivate; // DeathMatch Delay until reactvated - int m_iJuice; - int m_iOn; // 0 = off, 1 = startup, 2 = going - float m_flSoundTime; -}; - -TYPEDESCRIPTION CWallHealth::m_SaveData[] = - { - DEFINE_FIELD(CWallHealth, m_flNextCharge, FIELD_TIME), - DEFINE_FIELD(CWallHealth, m_iReactivate, FIELD_INTEGER), - DEFINE_FIELD(CWallHealth, m_iJuice, FIELD_INTEGER), - DEFINE_FIELD(CWallHealth, m_iOn, FIELD_INTEGER), - DEFINE_FIELD(CWallHealth, m_flSoundTime, FIELD_TIME), -}; - -IMPLEMENT_SAVERESTORE(CWallHealth, CBaseEntity); - -LINK_ENTITY_TO_CLASS(func_healthcharger, CWallHealth); - -void CWallHealth::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "style") || - FStrEq(pkvd->szKeyName, "height") || - FStrEq(pkvd->szKeyName, "value1") || - FStrEq(pkvd->szKeyName, "value2") || - FStrEq(pkvd->szKeyName, "value3")) - { - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "dmdelay")) - { - m_iReactivate = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else - CBaseToggle::KeyValue(pkvd); -} - -void CWallHealth::Spawn() -{ - Precache(); - - pev->solid = SOLID_BSP; - pev->movetype = MOVETYPE_PUSH; - - UTIL_SetOrigin(pev, pev->origin); // set size and link into world - UTIL_SetSize(pev, pev->mins, pev->maxs); - SET_MODEL(ENT(pev), STRING(pev->model)); - m_iJuice = gSkillData.healthchargerCapacity; - pev->frame = 0; -} - -void CWallHealth::Precache() -{ - PRECACHE_SOUND("items/medshot4.wav"); - PRECACHE_SOUND("items/medshotno1.wav"); - PRECACHE_SOUND("items/medcharge4.wav"); -} - -void CWallHealth::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - // Make sure that we have a caller - if (!pActivator) - return; - // if it's not a player, ignore - if (!pActivator->IsPlayer()) - return; - - // if there is no juice left, turn it off - if (m_iJuice <= 0) - { - pev->frame = 1; - Off(); - } - - // if the player doesn't have the suit, or there is no juice left, make the deny noise - if ((m_iJuice <= 0) || (!(pActivator->pev->weapons & (1 << WEAPON_SUIT)))) - { - if (m_flSoundTime <= gpGlobals->time) - { - m_flSoundTime = gpGlobals->time + 0.62; - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/medshotno1.wav", 1.0, ATTN_NORM); - } - return; - } - - pev->nextthink = pev->ltime + 0.25; - SetThink(Off); - - // Time to recharge yet? - - if (m_flNextCharge >= gpGlobals->time) - return; - - // Play the on sound or the looping charging sound - if (!m_iOn) - { - m_iOn++; - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/medshot4.wav", 1.0, ATTN_NORM); - m_flSoundTime = 0.56 + gpGlobals->time; - } - if ((m_iOn == 1) && (m_flSoundTime <= gpGlobals->time)) - { - m_iOn++; - EMIT_SOUND(ENT(pev), CHAN_STATIC, "items/medcharge4.wav", 1.0, ATTN_NORM); - } - - // charge the player - if (pActivator->TakeHealth(1, DMG_GENERIC)) - { - m_iJuice--; - } - - // govern the rate of charge - m_flNextCharge = gpGlobals->time + 0.1; -} - -void CWallHealth::Recharge(void) -{ - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/medshot4.wav", 1.0, ATTN_NORM); - m_iJuice = gSkillData.healthchargerCapacity; - pev->frame = 0; - SetThink(SUB_DoNothing); -} - -void CWallHealth::Off(void) -{ - // Stop looping sound. - if (m_iOn > 1) - STOP_SOUND(ENT(pev), CHAN_STATIC, "items/medcharge4.wav"); - - m_iOn = 0; - - if ((!m_iJuice) && ((m_iReactivate = g_pGameRules->FlHealthChargerRechargeTime()) > 0)) - { - pev->nextthink = pev->ltime + m_iReactivate; - SetThink(Recharge); - } - else - SetThink(SUB_DoNothing); -} \ No newline at end of file diff --git a/dlls/Half-life/hgrunt.cpp b/dlls/Half-life/hgrunt.cpp deleted file mode 100644 index 29268a88..00000000 --- a/dlls/Half-life/hgrunt.cpp +++ /dev/null @@ -1,2455 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// hgrunt -//========================================================= - -//========================================================= -// Hit groups! -//========================================================= -/* - - 1 - Head - 2 - Stomach - 3 - Gun - -*/ - -#include "extdll.h" -#include "util.h" -#include "plane.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" - -int g_fGruntQuestion; // true if an idle grunt asked a question. Cleared when someone answers. - -extern DLL_GLOBAL int g_iSkillLevel; - -//========================================================= -// monster-specific DEFINE's -//========================================================= -#define GRUNT_CLIP_SIZE 36 // how many bullets in a clip? - NOTE: 3 round burst sound, so keep as 3 * x! -#define GRUNT_VOL 0.35 // volume of grunt sounds -#define GRUNT_ATTN ATTN_NORM // attenutation of grunt sentences -#define HGRUNT_LIMP_HEALTH 20 -#define HGRUNT_DMG_HEADSHOT (DMG_BULLET | DMG_CLUB) // damage types that can kill a grunt with a single headshot. -#define HGRUNT_NUM_HEADS 2 // how many grunt heads are there? -#define HGRUNT_MINIMUM_HEADSHOT_DAMAGE 15 // must do at least this much damage in one shot to head to score a headshot kill -#define HGRUNT_SENTENCE_VOLUME (float)0.35 // volume of grunt sentences - -#define HGRUNT_9MMAR (1 << 0) -#define HGRUNT_HANDGRENADE (1 << 1) -#define HGRUNT_GRENADELAUNCHER (1 << 2) -#define HGRUNT_SHOTGUN (1 << 3) - -#define HEAD_GROUP 1 -#define HEAD_GRUNT 0 -#define HEAD_COMMANDER 1 -#define HEAD_SHOTGUN 2 -#define HEAD_M203 3 -#define GUN_GROUP 2 -#define GUN_MP5 0 -#define GUN_SHOTGUN 1 -#define GUN_NONE 2 - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define HGRUNT_AE_RELOAD (2) -#define HGRUNT_AE_KICK (3) -#define HGRUNT_AE_BURST1 (4) -#define HGRUNT_AE_BURST2 (5) -#define HGRUNT_AE_BURST3 (6) -#define HGRUNT_AE_GREN_TOSS (7) -#define HGRUNT_AE_GREN_LAUNCH (8) -#define HGRUNT_AE_GREN_DROP (9) -#define HGRUNT_AE_CAUGHT_ENEMY (10) // grunt established sight with an enemy (player only) that had previously eluded the squad. -#define HGRUNT_AE_DROP_GUN (11) // grunt (probably dead) is dropping his mp5. - -//========================================================= -// monster-specific schedule types -//========================================================= -enum -{ - SCHED_GRUNT_SUPPRESS = LAST_COMMON_SCHEDULE + 1, - SCHED_GRUNT_ESTABLISH_LINE_OF_FIRE, // move to a location to set up an attack against the enemy. (usually when a friendly is in the way). - SCHED_GRUNT_COVER_AND_RELOAD, - SCHED_GRUNT_SWEEP, - SCHED_GRUNT_FOUND_ENEMY, - SCHED_GRUNT_REPEL, - SCHED_GRUNT_REPEL_ATTACK, - SCHED_GRUNT_REPEL_LAND, - SCHED_GRUNT_WAIT_FACE_ENEMY, - SCHED_GRUNT_TAKECOVER_FAILED, // special schedule type that forces analysis of conditions and picks the best possible schedule to recover from this type of failure. - SCHED_GRUNT_ELOF_FAIL, -}; - -//========================================================= -// monster-specific tasks -//========================================================= -enum -{ - TASK_GRUNT_FACE_TOSS_DIR = LAST_COMMON_TASK + 1, - TASK_GRUNT_SPEAK_SENTENCE, - TASK_GRUNT_CHECK_FIRE, -}; - -//========================================================= -// monster-specific conditions -//========================================================= -#define bits_COND_GRUNT_NOFIRE (bits_COND_SPECIAL1) - -class CHGrunt : public CSquadMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int Classify(void); - int ISoundMask(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - BOOL FCanCheckAttacks(void); - BOOL CheckMeleeAttack1(float flDot, float flDist); - BOOL CheckRangeAttack1(float flDot, float flDist); - BOOL CheckRangeAttack2(float flDot, float flDist); - void CheckAmmo(void); - void SetActivity(Activity NewActivity); - void StartTask(Task_t *pTask); - void RunTask(Task_t *pTask); - void DeathSound(void); - void PainSound(void); - void IdleSound(void); - Vector GetGunPosition(void); - void Shoot(void); - void Shotgun(void); - void PrescheduleThink(void); - void GibMonster(void); - void SpeakSentence(void); - - int Save(CSave &save); - int Restore(CRestore &restore); - - CBaseEntity *Kick(void); - Schedule_t *GetSchedule(void); - Schedule_t *GetScheduleOfType(int Type); - void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - - int IRelationship(CBaseEntity *pTarget); - - BOOL FOkToSpeak(void); - void JustSpoke(void); - - CUSTOM_SCHEDULES; - static TYPEDESCRIPTION m_SaveData[]; - - // checking the feasibility of a grenade toss is kind of costly, so we do it every couple of seconds, - // not every server frame. - float m_flNextGrenadeCheck; - float m_flNextPainTime; - float m_flLastEnemySightTime; - - Vector m_vecTossVelocity; - - BOOL m_fThrowGrenade; - BOOL m_fStanding; - BOOL m_fFirstEncounter; // only put on the handsign show in the squad's first encounter. - int m_cClipSize; - - int m_voicePitch; - - int m_iBrassShell; - int m_iShotgunShell; - - int m_iSentence; - - static const char *pGruntSentences[]; -}; - -LINK_ENTITY_TO_CLASS(monster_human_grunt, CHGrunt); - -TYPEDESCRIPTION CHGrunt::m_SaveData[] = - { - DEFINE_FIELD(CHGrunt, m_flNextGrenadeCheck, FIELD_TIME), - DEFINE_FIELD(CHGrunt, m_flNextPainTime, FIELD_TIME), - // DEFINE_FIELD( CHGrunt, m_flLastEnemySightTime, FIELD_TIME ), // don't save, go to zero - DEFINE_FIELD(CHGrunt, m_vecTossVelocity, FIELD_VECTOR), - DEFINE_FIELD(CHGrunt, m_fThrowGrenade, FIELD_BOOLEAN), - DEFINE_FIELD(CHGrunt, m_fStanding, FIELD_BOOLEAN), - DEFINE_FIELD(CHGrunt, m_fFirstEncounter, FIELD_BOOLEAN), - DEFINE_FIELD(CHGrunt, m_cClipSize, FIELD_INTEGER), - DEFINE_FIELD(CHGrunt, m_voicePitch, FIELD_INTEGER), - // DEFINE_FIELD( CShotgun, m_iBrassShell, FIELD_INTEGER ), - // DEFINE_FIELD( CShotgun, m_iShotgunShell, FIELD_INTEGER ), - DEFINE_FIELD(CHGrunt, m_iSentence, FIELD_INTEGER), -}; - -IMPLEMENT_SAVERESTORE(CHGrunt, CSquadMonster); - -const char *CHGrunt::pGruntSentences[] = - { - "HG_GREN", // grenade scared grunt - "HG_ALERT", // sees player - "HG_MONSTER", // sees monster - "HG_COVER", // running to cover - "HG_THROW", // about to throw grenade - "HG_CHARGE", // running out to get the enemy - "HG_TAUNT", // say rude things -}; - -enum -{ - HGRUNT_SENT_NONE = -1, - HGRUNT_SENT_GREN = 0, - HGRUNT_SENT_ALERT, - HGRUNT_SENT_MONSTER, - HGRUNT_SENT_COVER, - HGRUNT_SENT_THROW, - HGRUNT_SENT_CHARGE, - HGRUNT_SENT_TAUNT, -} HGRUNT_SENTENCE_TYPES; - -//========================================================= -// Speak Sentence - say your cued up sentence. -// -// Some grunt sentences (take cover and charge) rely on actually -// being able to execute the intended action. It's really lame -// when a grunt says 'COVER ME' and then doesn't move. The problem -// is that the sentences were played when the decision to TRY -// to move to cover was made. Now the sentence is played after -// we know for sure that there is a valid path. The schedule -// may still fail but in most cases, well after the grunt has -// started moving. -//========================================================= -void CHGrunt ::SpeakSentence(void) -{ - if (m_iSentence == HGRUNT_SENT_NONE) - { - // no sentence cued up. - return; - } - - if (FOkToSpeak()) - { - SENTENCEG_PlayRndSz(ENT(pev), pGruntSentences[m_iSentence], HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch); - JustSpoke(); - } -} - -//========================================================= -// IRelationship - overridden because Alien Grunts are -// Human Grunt's nemesis. -//========================================================= -int CHGrunt::IRelationship(CBaseEntity *pTarget) -{ - if (FClassnameIs(pTarget->pev, "monster_alien_grunt") || (FClassnameIs(pTarget->pev, "monster_gargantua"))) - { - return R_NM; - } - - return CSquadMonster::IRelationship(pTarget); -} - -//========================================================= -// GibMonster - make gun fly through the air. -//========================================================= -void CHGrunt ::GibMonster(void) -{ - Vector vecGunPos; - Vector vecGunAngles; - - if (GetBodygroup(2) != 2) - { // throw a gun if the grunt has one - GetAttachment(0, vecGunPos, vecGunAngles); - - CBaseEntity *pGun; - if (FBitSet(pev->weapons, HGRUNT_SHOTGUN)) - { - pGun = DropItem("weapon_shotgun", vecGunPos, vecGunAngles); - } - else - { - pGun = DropItem("weapon_9mmAR", vecGunPos, vecGunAngles); - } - if (pGun) - { - pGun->pev->velocity = Vector(RANDOM_FLOAT(-100, 100), RANDOM_FLOAT(-100, 100), RANDOM_FLOAT(200, 300)); - pGun->pev->avelocity = Vector(0, RANDOM_FLOAT(200, 400), 0); - } - - if (FBitSet(pev->weapons, HGRUNT_GRENADELAUNCHER)) - { - pGun = DropItem("ammo_ARgrenades", vecGunPos, vecGunAngles); - if (pGun) - { - pGun->pev->velocity = Vector(RANDOM_FLOAT(-100, 100), RANDOM_FLOAT(-100, 100), RANDOM_FLOAT(200, 300)); - pGun->pev->avelocity = Vector(0, RANDOM_FLOAT(200, 400), 0); - } - } - } - - CBaseMonster ::GibMonster(); -} - -//========================================================= -// ISoundMask - Overidden for human grunts because they -// hear the DANGER sound that is made by hand grenades and -// other dangerous items. -//========================================================= -int CHGrunt ::ISoundMask(void) -{ - return bits_SOUND_WORLD | - bits_SOUND_COMBAT | - bits_SOUND_PLAYER | - bits_SOUND_DANGER; -} - -//========================================================= -// someone else is talking - don't speak -//========================================================= -BOOL CHGrunt ::FOkToSpeak(void) -{ - // if someone else is talking, don't speak - if (gpGlobals->time <= CTalkMonster::g_talkWaitTime) - return FALSE; - - if (pev->spawnflags & SF_MONSTER_GAG) - { - if (m_MonsterState != MONSTERSTATE_COMBAT) - { - // no talking outside of combat if gagged. - return FALSE; - } - } - - // if player is not in pvs, don't speak - // if (FNullEnt(FIND_CLIENT_IN_PVS(edict()))) - // return FALSE; - - return TRUE; -} - -//========================================================= -//========================================================= -void CHGrunt ::JustSpoke(void) -{ - CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(1.5, 2.0); - m_iSentence = HGRUNT_SENT_NONE; -} - -//========================================================= -// PrescheduleThink - this function runs after conditions -// are collected and before scheduling code is run. -//========================================================= -void CHGrunt ::PrescheduleThink(void) -{ - if (InSquad() && m_hEnemy != NULL) - { - if (HasConditions(bits_COND_SEE_ENEMY)) - { - // update the squad's last enemy sighting time. - MySquadLeader()->m_flLastEnemySightTime = gpGlobals->time; - } - else - { - if (gpGlobals->time - MySquadLeader()->m_flLastEnemySightTime > 5) - { - // been a while since we've seen the enemy - MySquadLeader()->m_fEnemyEluded = TRUE; - } - } - } -} - -//========================================================= -// FCanCheckAttacks - this is overridden for human grunts -// because they can throw/shoot grenades when they can't see their -// target and the base class doesn't check attacks if the monster -// cannot see its enemy. -// -// !!!BUGBUG - this gets called before a 3-round burst is fired -// which means that a friendly can still be hit with up to 2 rounds. -// ALSO, grenades will not be tossed if there is a friendly in front, -// this is a bad bug. Friendly machine gun fire avoidance -// will unecessarily prevent the throwing of a grenade as well. -//========================================================= -BOOL CHGrunt ::FCanCheckAttacks(void) -{ - if (!HasConditions(bits_COND_ENEMY_TOOFAR)) - { - return TRUE; - } - else - { - return FALSE; - } -} - -//========================================================= -// CheckMeleeAttack1 -//========================================================= -BOOL CHGrunt ::CheckMeleeAttack1(float flDot, float flDist) -{ - CBaseMonster *pEnemy; - - if (m_hEnemy != NULL) - { - pEnemy = m_hEnemy->MyMonsterPointer(); - - if (!pEnemy) - { - return FALSE; - } - } - - if (flDist <= 64 && flDot >= 0.7 && - pEnemy->Classify() != CLASS_ALIEN_BIOWEAPON && - pEnemy->Classify() != CLASS_PLAYER_BIOWEAPON) - { - return TRUE; - } - return FALSE; -} - -//========================================================= -// CheckRangeAttack1 - overridden for HGrunt, cause -// FCanCheckAttacks() doesn't disqualify all attacks based -// on whether or not the enemy is occluded because unlike -// the base class, the HGrunt can attack when the enemy is -// occluded (throw grenade over wall, etc). We must -// disqualify the machine gun attack if the enemy is occluded. -//========================================================= -BOOL CHGrunt ::CheckRangeAttack1(float flDot, float flDist) -{ - if (!HasConditions(bits_COND_ENEMY_OCCLUDED) && flDist <= 2048 && flDot >= 0.5 && NoFriendlyFire()) - { - TraceResult tr; - - if (!m_hEnemy->IsPlayer() && flDist <= 64) - { - // kick nonclients, but don't shoot at them. - return FALSE; - } - - Vector vecSrc = GetGunPosition(); - - // verify that a bullet fired from the gun will hit the enemy before the world. - UTIL_TraceLine(vecSrc, m_hEnemy->BodyTarget(vecSrc), ignore_monsters, ignore_glass, ENT(pev), &tr); - - if (tr.flFraction == 1.0) - { - return TRUE; - } - } - - return FALSE; -} - -//========================================================= -// CheckRangeAttack2 - this checks the Grunt's grenade -// attack. -//========================================================= -BOOL CHGrunt ::CheckRangeAttack2(float flDot, float flDist) -{ - if (!FBitSet(pev->weapons, (HGRUNT_HANDGRENADE | HGRUNT_GRENADELAUNCHER))) - { - return FALSE; - } - - // if the grunt isn't moving, it's ok to check. - if (m_flGroundSpeed != 0) - { - m_fThrowGrenade = FALSE; - return m_fThrowGrenade; - } - - // assume things haven't changed too much since last time - if (gpGlobals->time < m_flNextGrenadeCheck) - { - return m_fThrowGrenade; - } - - if (!FBitSet(m_hEnemy->pev->flags, FL_ONGROUND) && m_hEnemy->pev->waterlevel == 0 && m_vecEnemyLKP.z > pev->absmax.z) - { - //!!!BUGBUG - we should make this check movetype and make sure it isn't FLY? Players who jump a lot are unlikely to - // be grenaded. - // don't throw grenades at anything that isn't on the ground! - m_fThrowGrenade = FALSE; - return m_fThrowGrenade; - } - - Vector vecTarget; - - if (FBitSet(pev->weapons, HGRUNT_HANDGRENADE)) - { - // find feet - if (RANDOM_LONG(0, 1)) - { - // magically know where they are - vecTarget = Vector(m_hEnemy->pev->origin.x, m_hEnemy->pev->origin.y, m_hEnemy->pev->absmin.z); - } - else - { - // toss it to where you last saw them - vecTarget = m_vecEnemyLKP; - } - // vecTarget = m_vecEnemyLKP + (m_hEnemy->BodyTarget( pev->origin ) - m_hEnemy->pev->origin); - // estimate position - // vecTarget = vecTarget + m_hEnemy->pev->velocity * 2; - } - else - { - // find target - // vecTarget = m_hEnemy->BodyTarget( pev->origin ); - vecTarget = m_vecEnemyLKP + (m_hEnemy->BodyTarget(pev->origin) - m_hEnemy->pev->origin); - // estimate position - if (HasConditions(bits_COND_SEE_ENEMY)) - vecTarget = vecTarget + ((vecTarget - pev->origin).Length() / gSkillData.hgruntGrenadeSpeed) * m_hEnemy->pev->velocity; - } - - // are any of my squad members near the intended grenade impact area? - if (InSquad()) - { - if (SquadMemberInRange(vecTarget, 256)) - { - // crap, I might blow my own guy up. Don't throw a grenade and don't check again for a while. - m_flNextGrenadeCheck = gpGlobals->time + 1; // one full second. - m_fThrowGrenade = FALSE; - } - } - - if ((vecTarget - pev->origin).Length2D() <= 256) - { - // crap, I don't want to blow myself up - m_flNextGrenadeCheck = gpGlobals->time + 1; // one full second. - m_fThrowGrenade = FALSE; - return m_fThrowGrenade; - } - - if (FBitSet(pev->weapons, HGRUNT_HANDGRENADE)) - { - Vector vecToss = VecCheckToss(pev, GetGunPosition(), vecTarget, 0.5); - - if (vecToss != g_vecZero) - { - m_vecTossVelocity = vecToss; - - // throw a hand grenade - m_fThrowGrenade = TRUE; - // don't check again for a while. - m_flNextGrenadeCheck = gpGlobals->time; // 1/3 second. - } - else - { - // don't throw - m_fThrowGrenade = FALSE; - // don't check again for a while. - m_flNextGrenadeCheck = gpGlobals->time + 1; // one full second. - } - } - else - { - Vector vecToss = VecCheckThrow(pev, GetGunPosition(), vecTarget, gSkillData.hgruntGrenadeSpeed, 0.5); - - if (vecToss != g_vecZero) - { - m_vecTossVelocity = vecToss; - - // throw a hand grenade - m_fThrowGrenade = TRUE; - // don't check again for a while. - m_flNextGrenadeCheck = gpGlobals->time + 0.3; // 1/3 second. - } - else - { - // don't throw - m_fThrowGrenade = FALSE; - // don't check again for a while. - m_flNextGrenadeCheck = gpGlobals->time + 1; // one full second. - } - } - - return m_fThrowGrenade; -} - -//========================================================= -// TraceAttack - make sure we're not taking it in the helmet -//========================================================= -void CHGrunt ::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - // check for helmet shot - if (ptr->iHitgroup == 11) - { - // make sure we're wearing one - if (GetBodygroup(1) == HEAD_GRUNT && (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB))) - { - // absorb damage - flDamage -= 20; - if (flDamage <= 0) - { - UTIL_Ricochet(ptr->vecEndPos, 1.0); - flDamage = 0.01; - } - } - // it's head shot anyways - ptr->iHitgroup = HITGROUP_HEAD; - } - CSquadMonster::TraceAttack(pevAttacker, flDamage, vecDir, ptr, bitsDamageType); -} - -//========================================================= -// TakeDamage - overridden for the grunt because the grunt -// needs to forget that he is in cover if he's hurt. (Obviously -// not in a safe place anymore). -//========================================================= -int CHGrunt ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - Forget(bits_MEMORY_INCOVER); - - return CSquadMonster ::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CHGrunt ::SetYawSpeed(void) -{ - int ys; - - switch (m_Activity) - { - case ACT_IDLE: - ys = 150; - break; - case ACT_RUN: - ys = 150; - break; - case ACT_WALK: - ys = 180; - break; - case ACT_RANGE_ATTACK1: - ys = 120; - break; - case ACT_RANGE_ATTACK2: - ys = 120; - break; - case ACT_MELEE_ATTACK1: - ys = 120; - break; - case ACT_MELEE_ATTACK2: - ys = 120; - break; - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - ys = 180; - break; - case ACT_GLIDE: - case ACT_FLY: - ys = 30; - break; - default: - ys = 90; - break; - } - - pev->yaw_speed = ys; -} - -void CHGrunt ::IdleSound(void) -{ - if (FOkToSpeak() && (g_fGruntQuestion || RANDOM_LONG(0, 1))) - { - if (!g_fGruntQuestion) - { - // ask question or make statement - switch (RANDOM_LONG(0, 2)) - { - case 0: // check in - SENTENCEG_PlayRndSz(ENT(pev), "HG_CHECK", HGRUNT_SENTENCE_VOLUME, ATTN_NORM, 0, m_voicePitch); - g_fGruntQuestion = 1; - break; - case 1: // question - SENTENCEG_PlayRndSz(ENT(pev), "HG_QUEST", HGRUNT_SENTENCE_VOLUME, ATTN_NORM, 0, m_voicePitch); - g_fGruntQuestion = 2; - break; - case 2: // statement - SENTENCEG_PlayRndSz(ENT(pev), "HG_IDLE", HGRUNT_SENTENCE_VOLUME, ATTN_NORM, 0, m_voicePitch); - break; - } - } - else - { - switch (g_fGruntQuestion) - { - case 1: // check in - SENTENCEG_PlayRndSz(ENT(pev), "HG_CLEAR", HGRUNT_SENTENCE_VOLUME, ATTN_NORM, 0, m_voicePitch); - break; - case 2: // question - SENTENCEG_PlayRndSz(ENT(pev), "HG_ANSWER", HGRUNT_SENTENCE_VOLUME, ATTN_NORM, 0, m_voicePitch); - break; - } - g_fGruntQuestion = 0; - } - JustSpoke(); - } -} - -//========================================================= -// CheckAmmo - overridden for the grunt because he actually -// uses ammo! (base class doesn't) -//========================================================= -void CHGrunt ::CheckAmmo(void) -{ - if (m_cAmmoLoaded <= 0) - { - SetConditions(bits_COND_NO_AMMO_LOADED); - } -} - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CHGrunt ::Classify(void) -{ - return CLASS_HUMAN_MILITARY; -} - -//========================================================= -//========================================================= -CBaseEntity *CHGrunt ::Kick(void) -{ - TraceResult tr; - - UTIL_MakeVectors(pev->angles); - Vector vecStart = pev->origin; - vecStart.z += pev->size.z * 0.5; - Vector vecEnd = vecStart + (gpGlobals->v_forward * 70); - - UTIL_TraceHull(vecStart, vecEnd, dont_ignore_monsters, head_hull, ENT(pev), &tr); - - if (tr.pHit) - { - CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); - return pEntity; - } - - return NULL; -} - -//========================================================= -// GetGunPosition return the end of the barrel -//========================================================= - -Vector CHGrunt ::GetGunPosition() -{ - if (m_fStanding) - { - return pev->origin + Vector(0, 0, 60); - } - else - { - return pev->origin + Vector(0, 0, 48); - } -} - -//========================================================= -// Shoot -//========================================================= -void CHGrunt ::Shoot(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_10DEGREES, 2048, BULLET_MONSTER_MP5); // shoot +-5 degrees - - pev->effects |= EF_MUZZLEFLASH; - - m_cAmmoLoaded--; // take away a bullet! - - Vector angDir = UTIL_VecToAngles(vecShootDir); - SetBlending(0, angDir.x); -} - -//========================================================= -// Shoot -//========================================================= -void CHGrunt ::Shotgun(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_iShotgunShell, TE_BOUNCE_SHOTSHELL); - FireBullets(gSkillData.hgruntShotgunPellets, vecShootOrigin, vecShootDir, VECTOR_CONE_15DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 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 CHGrunt ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - Vector vecShootDir; - Vector vecShootOrigin; - - switch (pEvent->event) - { - case HGRUNT_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, HGRUNT_SHOTGUN)) - { - DropItem("weapon_shotgun", vecGunPos, vecGunAngles); - } - else - { - DropItem("weapon_9mmAR", vecGunPos, vecGunAngles); - } - if (FBitSet(pev->weapons, HGRUNT_GRENADELAUNCHER)) - { - DropItem("ammo_ARgrenades", BodyTarget(pev->origin), vecGunAngles); - } - } - break; - - case HGRUNT_AE_RELOAD: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "hgrunt/gr_reload1.wav", 1, ATTN_NORM); - m_cAmmoLoaded = m_cClipSize; - ClearConditions(bits_COND_NO_AMMO_LOADED); - break; - - case HGRUNT_AE_GREN_TOSS: - { - UTIL_MakeVectors(pev->angles); - // CGrenade::ShootTimed( pev, pev->origin + gpGlobals->v_forward * 34 + Vector (0, 0, 32), m_vecTossVelocity, 3.5 ); - CGrenade::ShootTimed(pev, GetGunPosition(), m_vecTossVelocity, 3.5); - - m_fThrowGrenade = FALSE; - m_flNextGrenadeCheck = gpGlobals->time + 6; // wait six seconds before even looking again to see if a grenade can be thrown. - // !!!LATER - when in a group, only try to throw grenade if ordered. - } - break; - - case HGRUNT_AE_GREN_LAUNCH: - { - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/glauncher.wav", 0.8, ATTN_NORM); - CGrenade::ShootContact(pev, GetGunPosition(), m_vecTossVelocity); - m_fThrowGrenade = FALSE; - if (g_iSkillLevel == SKILL_HARD) - m_flNextGrenadeCheck = gpGlobals->time + RANDOM_FLOAT(2, 5); // wait a random amount of time before shooting again - else - m_flNextGrenadeCheck = gpGlobals->time + 6; // wait six seconds before even looking again to see if a grenade can be thrown. - } - break; - - case HGRUNT_AE_GREN_DROP: - { - UTIL_MakeVectors(pev->angles); - CGrenade::ShootTimed(pev, pev->origin + gpGlobals->v_forward * 17 - gpGlobals->v_right * 27 + gpGlobals->v_up * 6, g_vecZero, 3); - } - break; - - case HGRUNT_AE_BURST1: - { - if (FBitSet(pev->weapons, HGRUNT_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 - { - Shotgun(); - - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/sbarrel1.wav", 1, ATTN_NORM); - } - - CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, 384, 0.3); - } - break; - - case HGRUNT_AE_BURST2: - case HGRUNT_AE_BURST3: - Shoot(); - break; - - case HGRUNT_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.hgruntDmgKick, DMG_CLUB); - } - } - break; - - case HGRUNT_AE_CAUGHT_ENEMY: - { - if (FOkToSpeak()) - { - SENTENCEG_PlayRndSz(ENT(pev), "HG_ALERT", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch); - JustSpoke(); - } - } - - default: - CSquadMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CHGrunt ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/hgrunt.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.hgruntHealth; - 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 = HGRUNT_SENT_NONE; - - 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 = HGRUNT_9MMAR | HGRUNT_HANDGRENADE; - // pev->weapons = HGRUNT_SHOTGUN; - // pev->weapons = HGRUNT_9MMAR | HGRUNT_GRENADELAUNCHER; - } - - if (FBitSet(pev->weapons, HGRUNT_SHOTGUN)) - { - SetBodygroup(GUN_GROUP, GUN_SHOTGUN); - m_cClipSize = 8; - } - else - { - m_cClipSize = GRUNT_CLIP_SIZE; - } - m_cAmmoLoaded = m_cClipSize; - - if (RANDOM_LONG(0, 99) < 80) - pev->skin = 0; // light skin - else - pev->skin = 1; // dark skin - - if (FBitSet(pev->weapons, HGRUNT_SHOTGUN)) - { - SetBodygroup(HEAD_GROUP, HEAD_SHOTGUN); - } - else if (FBitSet(pev->weapons, HGRUNT_GRENADELAUNCHER)) - { - SetBodygroup(HEAD_GROUP, HEAD_M203); - pev->skin = 1; // alway dark skin - } - - CTalkMonster::g_talkWaitTime = 0; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CHGrunt ::Precache() -{ - PRECACHE_MODEL("models/hgrunt.mdl"); - - PRECACHE_SOUND("hgrunt/gr_mgun1.wav"); - PRECACHE_SOUND("hgrunt/gr_mgun2.wav"); - - PRECACHE_SOUND("hgrunt/gr_die1.wav"); - PRECACHE_SOUND("hgrunt/gr_die2.wav"); - PRECACHE_SOUND("hgrunt/gr_die3.wav"); - - PRECACHE_SOUND("hgrunt/gr_pain1.wav"); - PRECACHE_SOUND("hgrunt/gr_pain2.wav"); - PRECACHE_SOUND("hgrunt/gr_pain3.wav"); - PRECACHE_SOUND("hgrunt/gr_pain4.wav"); - PRECACHE_SOUND("hgrunt/gr_pain5.wav"); - - PRECACHE_SOUND("hgrunt/gr_reload1.wav"); - - PRECACHE_SOUND("weapons/glauncher.wav"); - - PRECACHE_SOUND("weapons/sbarrel1.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 - m_iShotgunShell = PRECACHE_MODEL("models/shotgunshell.mdl"); -} - -//========================================================= -// start task -//========================================================= -void CHGrunt ::StartTask(Task_t *pTask) -{ - m_iTaskStatus = TASKSTATUS_RUNNING; - - switch (pTask->iTask) - { - case TASK_GRUNT_CHECK_FIRE: - if (!NoFriendlyFire()) - { - SetConditions(bits_COND_GRUNT_NOFIRE); - } - TaskComplete(); - break; - - case TASK_GRUNT_SPEAK_SENTENCE: - SpeakSentence(); - TaskComplete(); - break; - - case TASK_WALK_PATH: - case TASK_RUN_PATH: - // grunt no longer assumes he is covered if he moves - Forget(bits_MEMORY_INCOVER); - CSquadMonster ::StartTask(pTask); - break; - - case TASK_RELOAD: - m_IdealActivity = ACT_RELOAD; - break; - - case TASK_GRUNT_FACE_TOSS_DIR: - break; - - case TASK_FACE_IDEAL: - case TASK_FACE_ENEMY: - CSquadMonster ::StartTask(pTask); - if (pev->movetype == MOVETYPE_FLY) - { - m_IdealActivity = ACT_GLIDE; - } - break; - - default: - CSquadMonster ::StartTask(pTask); - break; - } -} - -//========================================================= -// RunTask -//========================================================= -void CHGrunt ::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_GRUNT_FACE_TOSS_DIR: - { - // project a point along the toss vector and turn to face that point. - MakeIdealYaw(pev->origin + m_vecTossVelocity * 64); - ChangeYaw(pev->yaw_speed); - - if (FacingIdeal()) - { - m_iTaskStatus = TASKSTATUS_COMPLETE; - } - break; - } - default: - { - CSquadMonster ::RunTask(pTask); - break; - } - } -} - -//========================================================= -// PainSound -//========================================================= -void CHGrunt ::PainSound(void) -{ - if (gpGlobals->time > m_flNextPainTime) - { -#if 0 - if ( RANDOM_LONG(0,99) < 5 ) - { - // pain sentences are rare - if (FOkToSpeak()) - { - SENTENCEG_PlayRndSz(ENT(pev), "HG_PAIN", HGRUNT_SENTENCE_VOLUME, ATTN_NORM, 0, PITCH_NORM); - JustSpoke(); - return; - } - } -#endif - switch (RANDOM_LONG(0, 6)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hgrunt/gr_pain3.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hgrunt/gr_pain4.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hgrunt/gr_pain5.wav", 1, ATTN_NORM); - break; - case 3: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hgrunt/gr_pain1.wav", 1, ATTN_NORM); - break; - case 4: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hgrunt/gr_pain2.wav", 1, ATTN_NORM); - break; - } - - m_flNextPainTime = gpGlobals->time + 1; - } -} - -//========================================================= -// DeathSound -//========================================================= -void CHGrunt ::DeathSound(void) -{ - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hgrunt/gr_die1.wav", 1, ATTN_IDLE); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hgrunt/gr_die2.wav", 1, ATTN_IDLE); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hgrunt/gr_die3.wav", 1, ATTN_IDLE); - break; - } -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - -//========================================================= -// GruntFail -//========================================================= -Task_t tlGruntFail[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_WAIT, (float)2}, - {TASK_WAIT_PVS, (float)0}, -}; - -Schedule_t slGruntFail[] = - { - {tlGruntFail, - ARRAYSIZE(tlGruntFail), - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_RANGE_ATTACK2 | - bits_COND_CAN_MELEE_ATTACK1 | - bits_COND_CAN_MELEE_ATTACK2, - 0, - "Grunt Fail"}, -}; - -//========================================================= -// Grunt Combat Fail -//========================================================= -Task_t tlGruntCombatFail[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_WAIT_FACE_ENEMY, (float)2}, - {TASK_WAIT_PVS, (float)0}, -}; - -Schedule_t slGruntCombatFail[] = - { - {tlGruntCombatFail, - ARRAYSIZE(tlGruntCombatFail), - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_RANGE_ATTACK2, - 0, - "Grunt Combat Fail"}, -}; - -//========================================================= -// Victory dance! -//========================================================= -Task_t tlGruntVictoryDance[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_WAIT, (float)1.5}, - {TASK_GET_PATH_TO_ENEMY_CORPSE, (float)0}, - {TASK_WALK_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE}, -}; - -Schedule_t slGruntVictoryDance[] = - { - {tlGruntVictoryDance, - ARRAYSIZE(tlGruntVictoryDance), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "GruntVictoryDance"}, -}; - -//========================================================= -// Establish line of fire - move to a position that allows -// the grunt to attack. -//========================================================= -Task_t tlGruntEstablishLineOfFire[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_GRUNT_ELOF_FAIL}, - {TASK_GET_PATH_TO_ENEMY, (float)0}, - {TASK_GRUNT_SPEAK_SENTENCE, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, -}; - -Schedule_t slGruntEstablishLineOfFire[] = - { - {tlGruntEstablishLineOfFire, - ARRAYSIZE(tlGruntEstablishLineOfFire), - bits_COND_NEW_ENEMY | - bits_COND_ENEMY_DEAD | - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_MELEE_ATTACK1 | - bits_COND_CAN_RANGE_ATTACK2 | - bits_COND_CAN_MELEE_ATTACK2 | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER, - "GruntEstablishLineOfFire"}, -}; - -//========================================================= -// GruntFoundEnemy - grunt established sight with an enemy -// that was hiding from the squad. -//========================================================= -Task_t tlGruntFoundEnemy[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_PLAY_SEQUENCE_FACE_ENEMY, (float)ACT_SIGNAL1}, -}; - -Schedule_t slGruntFoundEnemy[] = - { - {tlGruntFoundEnemy, - ARRAYSIZE(tlGruntFoundEnemy), - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER, - "GruntFoundEnemy"}, -}; - -//========================================================= -// GruntCombatFace Schedule -//========================================================= -Task_t tlGruntCombatFace1[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_WAIT, (float)1.5}, - {TASK_SET_SCHEDULE, (float)SCHED_GRUNT_SWEEP}, -}; - -Schedule_t slGruntCombatFace[] = - { - {tlGruntCombatFace1, - ARRAYSIZE(tlGruntCombatFace1), - bits_COND_NEW_ENEMY | - bits_COND_ENEMY_DEAD | - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_RANGE_ATTACK2, - 0, - "Combat Face"}, -}; - -//========================================================= -// Suppressing fire - don't stop shooting until the clip is -// empty or grunt gets hurt. -//========================================================= -Task_t tlGruntSignalSuppress[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_PLAY_SEQUENCE_FACE_ENEMY, (float)ACT_SIGNAL2}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, -}; - -Schedule_t slGruntSignalSuppress[] = - { - {tlGruntSignalSuppress, - ARRAYSIZE(tlGruntSignalSuppress), - bits_COND_ENEMY_DEAD | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND | - bits_COND_GRUNT_NOFIRE | - bits_COND_NO_AMMO_LOADED, - - bits_SOUND_DANGER, - "SignalSuppress"}, -}; - -Task_t tlGruntSuppress[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, -}; - -Schedule_t slGruntSuppress[] = - { - {tlGruntSuppress, - ARRAYSIZE(tlGruntSuppress), - bits_COND_ENEMY_DEAD | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND | - bits_COND_GRUNT_NOFIRE | - bits_COND_NO_AMMO_LOADED, - - bits_SOUND_DANGER, - "Suppress"}, -}; - -//========================================================= -// grunt wait in cover - we don't allow danger or the ability -// to attack to break a grunt's run to cover schedule, but -// when a grunt is in cover, we do want them to attack if they can. -//========================================================= -Task_t tlGruntWaitInCover[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_WAIT_FACE_ENEMY, (float)1}, -}; - -Schedule_t slGruntWaitInCover[] = - { - {tlGruntWaitInCover, - ARRAYSIZE(tlGruntWaitInCover), - bits_COND_NEW_ENEMY | - bits_COND_HEAR_SOUND | - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_RANGE_ATTACK2 | - bits_COND_CAN_MELEE_ATTACK1 | - bits_COND_CAN_MELEE_ATTACK2, - - bits_SOUND_DANGER, - "GruntWaitInCover"}, -}; - -//========================================================= -// run to cover. -// !!!BUGBUG - set a decent fail schedule here. -//========================================================= -Task_t tlGruntTakeCover1[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_GRUNT_TAKECOVER_FAILED}, - {TASK_WAIT, (float)0.2}, - {TASK_FIND_COVER_FROM_ENEMY, (float)0}, - {TASK_GRUNT_SPEAK_SENTENCE, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_REMEMBER, (float)bits_MEMORY_INCOVER}, - {TASK_SET_SCHEDULE, (float)SCHED_GRUNT_WAIT_FACE_ENEMY}, -}; - -Schedule_t slGruntTakeCover[] = - { - {tlGruntTakeCover1, - ARRAYSIZE(tlGruntTakeCover1), - 0, - 0, - "TakeCover"}, -}; - -//========================================================= -// drop grenade then run to cover. -//========================================================= -Task_t tlGruntGrenadeCover1[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FIND_COVER_FROM_ENEMY, (float)99}, - {TASK_FIND_FAR_NODE_COVER_FROM_ENEMY, (float)384}, - {TASK_PLAY_SEQUENCE, (float)ACT_SPECIAL_ATTACK1}, - {TASK_CLEAR_MOVE_WAIT, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_SET_SCHEDULE, (float)SCHED_GRUNT_WAIT_FACE_ENEMY}, -}; - -Schedule_t slGruntGrenadeCover[] = - { - {tlGruntGrenadeCover1, - ARRAYSIZE(tlGruntGrenadeCover1), - 0, - 0, - "GrenadeCover"}, -}; - -//========================================================= -// drop grenade then run to cover. -//========================================================= -Task_t tlGruntTossGrenadeCover1[] = - { - {TASK_FACE_ENEMY, (float)0}, - {TASK_RANGE_ATTACK2, (float)0}, - {TASK_SET_SCHEDULE, (float)SCHED_TAKE_COVER_FROM_ENEMY}, -}; - -Schedule_t slGruntTossGrenadeCover[] = - { - {tlGruntTossGrenadeCover1, - ARRAYSIZE(tlGruntTossGrenadeCover1), - 0, - 0, - "TossGrenadeCover"}, -}; - -//========================================================= -// hide from the loudest sound source (to run from grenade) -//========================================================= -Task_t tlGruntTakeCoverFromBestSound[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_COWER}, // duck and cover if cannot move from explosion - {TASK_STOP_MOVING, (float)0}, - {TASK_FIND_COVER_FROM_BEST_SOUND, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_REMEMBER, (float)bits_MEMORY_INCOVER}, - {TASK_TURN_LEFT, (float)179}, -}; - -Schedule_t slGruntTakeCoverFromBestSound[] = - { - {tlGruntTakeCoverFromBestSound, - ARRAYSIZE(tlGruntTakeCoverFromBestSound), - 0, - 0, - "GruntTakeCoverFromBestSound"}, -}; - -//========================================================= -// Grunt reload schedule -//========================================================= -Task_t tlGruntHideReload[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_RELOAD}, - {TASK_FIND_COVER_FROM_ENEMY, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_REMEMBER, (float)bits_MEMORY_INCOVER}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_RELOAD}, -}; - -Schedule_t slGruntHideReload[] = - { - {tlGruntHideReload, - ARRAYSIZE(tlGruntHideReload), - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER, - "GruntHideReload"}}; - -//========================================================= -// Do a turning sweep of the area -//========================================================= -Task_t tlGruntSweep[] = - { - {TASK_TURN_LEFT, (float)179}, - {TASK_WAIT, (float)1}, - {TASK_TURN_LEFT, (float)179}, - {TASK_WAIT, (float)1}, -}; - -Schedule_t slGruntSweep[] = - { - {tlGruntSweep, - ARRAYSIZE(tlGruntSweep), - - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_CAN_RANGE_ATTACK1 | - bits_COND_CAN_RANGE_ATTACK2 | - bits_COND_HEAR_SOUND, - - bits_SOUND_WORLD | // sound flags - bits_SOUND_DANGER | - bits_SOUND_PLAYER, - - "Grunt Sweep"}, -}; - -//========================================================= -// primary range attack. Overriden because base class stops attacking when the enemy is occluded. -// grunt's grenade toss requires the enemy be occluded. -//========================================================= -Task_t tlGruntRangeAttack1A[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_PLAY_SEQUENCE_FACE_ENEMY, (float)ACT_CROUCH}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, -}; - -Schedule_t slGruntRangeAttack1A[] = - { - {tlGruntRangeAttack1A, - ARRAYSIZE(tlGruntRangeAttack1A), - bits_COND_NEW_ENEMY | - bits_COND_ENEMY_DEAD | - bits_COND_HEAVY_DAMAGE | - bits_COND_ENEMY_OCCLUDED | - bits_COND_HEAR_SOUND | - bits_COND_GRUNT_NOFIRE | - bits_COND_NO_AMMO_LOADED, - - bits_SOUND_DANGER, - "Range Attack1A"}, -}; - -//========================================================= -// primary range attack. Overriden because base class stops attacking when the enemy is occluded. -// grunt's grenade toss requires the enemy be occluded. -//========================================================= -Task_t tlGruntRangeAttack1B[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_PLAY_SEQUENCE_FACE_ENEMY, (float)ACT_IDLE_ANGRY}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_GRUNT_CHECK_FIRE, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, -}; - -Schedule_t slGruntRangeAttack1B[] = - { - {tlGruntRangeAttack1B, - ARRAYSIZE(tlGruntRangeAttack1B), - bits_COND_NEW_ENEMY | - bits_COND_ENEMY_DEAD | - bits_COND_HEAVY_DAMAGE | - bits_COND_ENEMY_OCCLUDED | - bits_COND_NO_AMMO_LOADED | - bits_COND_GRUNT_NOFIRE | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER, - "Range Attack1B"}, -}; - -//========================================================= -// secondary range attack. Overriden because base class stops attacking when the enemy is occluded. -// grunt's grenade toss requires the enemy be occluded. -//========================================================= -Task_t tlGruntRangeAttack2[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_GRUNT_FACE_TOSS_DIR, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_RANGE_ATTACK2}, - {TASK_SET_SCHEDULE, (float)SCHED_GRUNT_WAIT_FACE_ENEMY}, // don't run immediately after throwing grenade. -}; - -Schedule_t slGruntRangeAttack2[] = - { - {tlGruntRangeAttack2, - ARRAYSIZE(tlGruntRangeAttack2), - 0, - 0, - "RangeAttack2"}, -}; - -//========================================================= -// repel -//========================================================= -Task_t tlGruntRepel[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_GLIDE}, -}; - -Schedule_t slGruntRepel[] = - { - {tlGruntRepel, - ARRAYSIZE(tlGruntRepel), - bits_COND_SEE_ENEMY | - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER | - bits_SOUND_COMBAT | - bits_SOUND_PLAYER, - "Repel"}, -}; - -//========================================================= -// repel -//========================================================= -Task_t tlGruntRepelAttack[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_FLY}, -}; - -Schedule_t slGruntRepelAttack[] = - { - {tlGruntRepelAttack, - ARRAYSIZE(tlGruntRepelAttack), - bits_COND_ENEMY_OCCLUDED, - 0, - "Repel Attack"}, -}; - -//========================================================= -// repel land -//========================================================= -Task_t tlGruntRepelLand[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_LAND}, - {TASK_GET_PATH_TO_LASTPOSITION, (float)0}, - {TASK_RUN_PATH, (float)0}, - {TASK_WAIT_FOR_MOVEMENT, (float)0}, - {TASK_CLEAR_LASTPOSITION, (float)0}, -}; - -Schedule_t slGruntRepelLand[] = - { - {tlGruntRepelLand, - ARRAYSIZE(tlGruntRepelLand), - bits_COND_SEE_ENEMY | - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND, - - bits_SOUND_DANGER | - bits_SOUND_COMBAT | - bits_SOUND_PLAYER, - "Repel Land"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CHGrunt){ - slGruntFail, - slGruntCombatFail, - slGruntVictoryDance, - slGruntEstablishLineOfFire, - slGruntFoundEnemy, - slGruntCombatFace, - slGruntSignalSuppress, - slGruntSuppress, - slGruntWaitInCover, - slGruntTakeCover, - slGruntGrenadeCover, - slGruntTossGrenadeCover, - slGruntTakeCoverFromBestSound, - slGruntHideReload, - slGruntSweep, - slGruntRangeAttack1A, - slGruntRangeAttack1B, - slGruntRangeAttack2, - slGruntRepel, - slGruntRepelAttack, - slGruntRepelLand, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CHGrunt, CSquadMonster); - -//========================================================= -// SetActivity -//========================================================= -void CHGrunt ::SetActivity(Activity NewActivity) -{ - int iSequence = ACTIVITY_NOT_AVAILABLE; - void *pmodel = GET_MODEL_PTR(ENT(pev)); - - switch (NewActivity) - { - case ACT_RANGE_ATTACK1: - // grunt is either shooting standing or shooting crouched - if (FBitSet(pev->weapons, HGRUNT_9MMAR)) - { - if (m_fStanding) - { - // get aimable sequence - iSequence = LookupSequence("standing_mp5"); - } - else - { - // get crouching shoot - iSequence = LookupSequence("crouching_mp5"); - } - } - else - { - if (m_fStanding) - { - // get aimable sequence - iSequence = LookupSequence("standing_shotgun"); - } - else - { - // get crouching shoot - iSequence = LookupSequence("crouching_shotgun"); - } - } - break; - case ACT_RANGE_ATTACK2: - // grunt is going to a secondary long range attack. This may be a thrown - // grenade or fired grenade, we must determine which and pick proper sequence - if (pev->weapons & HGRUNT_HANDGRENADE) - { - // get toss anim - iSequence = LookupSequence("throwgrenade"); - } - else - { - // get launch anim - iSequence = LookupSequence("launchgrenade"); - } - break; - case ACT_RUN: - if (pev->health <= HGRUNT_LIMP_HEALTH) - { - // limp! - iSequence = LookupActivity(ACT_RUN_HURT); - } - else - { - iSequence = LookupActivity(NewActivity); - } - break; - case ACT_WALK: - if (pev->health <= HGRUNT_LIMP_HEALTH) - { - // limp! - iSequence = LookupActivity(ACT_WALK_HURT); - } - else - { - iSequence = LookupActivity(NewActivity); - } - break; - case ACT_IDLE: - if (m_MonsterState == MONSTERSTATE_COMBAT) - { - NewActivity = ACT_IDLE_ANGRY; - } - iSequence = LookupActivity(NewActivity); - break; - default: - iSequence = LookupActivity(NewActivity); - break; - } - - m_Activity = NewActivity; // Go ahead and set this so it doesn't keep trying when the anim is not present - - // Set to the desired anim, or default anim if the desired is not present - if (iSequence > ACTIVITY_NOT_AVAILABLE) - { - if (pev->sequence != iSequence || !m_fSequenceLoops) - { - pev->frame = 0; - } - - pev->sequence = iSequence; // Set to the reset anim (if it's there) - ResetSequenceInfo(); - SetYawSpeed(); - } - else - { - // Not available try to get default anim - ALERT(at_console, "%s has no sequence for act:%d\n", STRING(pev->classname), NewActivity); - pev->sequence = 0; // Set to the reset anim (if it's there) - } -} - -//========================================================= -// Get Schedule! -//========================================================= -Schedule_t *CHGrunt ::GetSchedule(void) -{ - - // clear old sentence - m_iSentence = HGRUNT_SENT_NONE; - - // flying? If PRONE, barnacle has me. IF not, it's assumed I am rapelling. - if (pev->movetype == MOVETYPE_FLY && m_MonsterState != MONSTERSTATE_PRONE) - { - if (pev->flags & FL_ONGROUND) - { - // just landed - pev->movetype = MOVETYPE_STEP; - return GetScheduleOfType(SCHED_GRUNT_REPEL_LAND); - } - else - { - // repel down a rope, - if (m_MonsterState == MONSTERSTATE_COMBAT) - return GetScheduleOfType(SCHED_GRUNT_REPEL_ATTACK); - else - return GetScheduleOfType(SCHED_GRUNT_REPEL); - } - } - - // grunts place HIGH priority on running away from danger sounds. - if (HasConditions(bits_COND_HEAR_SOUND)) - { - CSound *pSound; - pSound = PBestSound(); - - ASSERT(pSound != NULL); - if (pSound) - { - if (pSound->m_iType & bits_SOUND_DANGER) - { - // dangerous sound nearby! - - //!!!KELLY - currently, this is the grunt's signal that a grenade has landed nearby, - // and the grunt should find cover from the blast - // good place for "SHIT!" or some other colorful verbal indicator of dismay. - // It's not safe to play a verbal order here "Scatter", etc cause - // this may only affect a single individual in a squad. - - if (FOkToSpeak()) - { - SENTENCEG_PlayRndSz(ENT(pev), "HG_GREN", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch); - JustSpoke(); - } - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_BEST_SOUND); - } - /* - if (!HasConditions( bits_COND_SEE_ENEMY ) && ( pSound->m_iType & (bits_SOUND_PLAYER | bits_SOUND_COMBAT) )) - { - MakeIdealYaw( pSound->m_vecOrigin ); - } - */ - } - } - switch (m_MonsterState) - { - case MONSTERSTATE_COMBAT: - { - // dead enemy - if (HasConditions(bits_COND_ENEMY_DEAD)) - { - // call base class, all code to handle dead enemies is centralized there. - return CBaseMonster ::GetSchedule(); - } - - // new enemy - if (HasConditions(bits_COND_NEW_ENEMY)) - { - if (InSquad()) - { - MySquadLeader()->m_fEnemyEluded = FALSE; - - if (!IsLeader()) - { - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_ENEMY); - } - else - { - //!!!KELLY - the leader of a squad of grunts has just seen the player or a - // monster and has made it the squad's enemy. You - // can check pev->flags for FL_CLIENT to determine whether this is the player - // or a monster. He's going to immediately start - // firing, though. If you'd like, we can make an alternate "first sight" - // schedule where the leader plays a handsign anim - // that gives us enough time to hear a short sentence or spoken command - // before he starts pluggin away. - if (FOkToSpeak()) // && RANDOM_LONG(0,1)) - { - if ((m_hEnemy != NULL) && m_hEnemy->IsPlayer()) - // player - SENTENCEG_PlayRndSz(ENT(pev), "HG_ALERT", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch); - else if ((m_hEnemy != NULL) && - (m_hEnemy->Classify() != CLASS_PLAYER_ALLY) && - (m_hEnemy->Classify() != CLASS_HUMAN_PASSIVE) && - (m_hEnemy->Classify() != CLASS_MACHINE)) - // monster - SENTENCEG_PlayRndSz(ENT(pev), "HG_MONST", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch); - - JustSpoke(); - } - - if (HasConditions(bits_COND_CAN_RANGE_ATTACK1)) - { - return GetScheduleOfType(SCHED_GRUNT_SUPPRESS); - } - else - { - return GetScheduleOfType(SCHED_GRUNT_ESTABLISH_LINE_OF_FIRE); - } - } - } - } - // no ammo - else if (HasConditions(bits_COND_NO_AMMO_LOADED)) - { - //!!!KELLY - this individual just realized he's out of bullet ammo. - // He's going to try to find cover to run to and reload, but rarely, if - // none is available, he'll drop and reload in the open here. - return GetScheduleOfType(SCHED_GRUNT_COVER_AND_RELOAD); - } - - // damaged just a little - else if (HasConditions(bits_COND_LIGHT_DAMAGE)) - { - // if hurt: - // 90% chance of taking cover - // 10% chance of flinch. - int iPercent = RANDOM_LONG(0, 99); - - if (iPercent <= 90 && m_hEnemy != NULL) - { - // only try to take cover if we actually have an enemy! - - //!!!KELLY - this grunt was hit and is going to run to cover. - if (FOkToSpeak()) // && RANDOM_LONG(0,1)) - { - //SENTENCEG_PlayRndSz( ENT(pev), "HG_COVER", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch); - m_iSentence = HGRUNT_SENT_COVER; - //JustSpoke(); - } - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_ENEMY); - } - else - { - return GetScheduleOfType(SCHED_SMALL_FLINCH); - } - } - // can kick - else if (HasConditions(bits_COND_CAN_MELEE_ATTACK1)) - { - return GetScheduleOfType(SCHED_MELEE_ATTACK1); - } - // can grenade launch - - else if (FBitSet(pev->weapons, HGRUNT_GRENADELAUNCHER) && HasConditions(bits_COND_CAN_RANGE_ATTACK2) && OccupySlot(bits_SLOTS_HGRUNT_GRENADE)) - { - // shoot a grenade if you can - return GetScheduleOfType(SCHED_RANGE_ATTACK2); - } - // can shoot - else if (HasConditions(bits_COND_CAN_RANGE_ATTACK1)) - { - if (InSquad()) - { - // if the enemy has eluded the squad and a squad member has just located the enemy - // and the enemy does not see the squad member, issue a call to the squad to waste a - // little time and give the player a chance to turn. - if (MySquadLeader()->m_fEnemyEluded && !HasConditions(bits_COND_ENEMY_FACING_ME)) - { - MySquadLeader()->m_fEnemyEluded = FALSE; - return GetScheduleOfType(SCHED_GRUNT_FOUND_ENEMY); - } - } - - if (OccupySlot(bits_SLOTS_HGRUNT_ENGAGE)) - { - // try to take an available ENGAGE slot - return GetScheduleOfType(SCHED_RANGE_ATTACK1); - } - else if (HasConditions(bits_COND_CAN_RANGE_ATTACK2) && OccupySlot(bits_SLOTS_HGRUNT_GRENADE)) - { - // throw a grenade if can and no engage slots are available - return GetScheduleOfType(SCHED_RANGE_ATTACK2); - } - else - { - // hide! - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_ENEMY); - } - } - // can't see enemy - else if (HasConditions(bits_COND_ENEMY_OCCLUDED)) - { - if (HasConditions(bits_COND_CAN_RANGE_ATTACK2) && OccupySlot(bits_SLOTS_HGRUNT_GRENADE)) - { - //!!!KELLY - this grunt is about to throw or fire a grenade at the player. Great place for "fire in the hole" "frag out" etc - if (FOkToSpeak()) - { - SENTENCEG_PlayRndSz(ENT(pev), "HG_THROW", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch); - JustSpoke(); - } - return GetScheduleOfType(SCHED_RANGE_ATTACK2); - } - else if (OccupySlot(bits_SLOTS_HGRUNT_ENGAGE)) - { - //!!!KELLY - grunt cannot see the enemy and has just decided to - // charge the enemy's position. - if (FOkToSpeak()) // && RANDOM_LONG(0,1)) - { - //SENTENCEG_PlayRndSz( ENT(pev), "HG_CHARGE", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch); - m_iSentence = HGRUNT_SENT_CHARGE; - //JustSpoke(); - } - - return GetScheduleOfType(SCHED_GRUNT_ESTABLISH_LINE_OF_FIRE); - } - else - { - //!!!KELLY - grunt is going to stay put for a couple seconds to see if - // the enemy wanders back out into the open, or approaches the - // grunt's covered position. Good place for a taunt, I guess? - if (FOkToSpeak() && RANDOM_LONG(0, 1)) - { - SENTENCEG_PlayRndSz(ENT(pev), "HG_TAUNT", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch); - JustSpoke(); - } - return GetScheduleOfType(SCHED_STANDOFF); - } - } - - if (HasConditions(bits_COND_SEE_ENEMY) && !HasConditions(bits_COND_CAN_RANGE_ATTACK1)) - { - return GetScheduleOfType(SCHED_GRUNT_ESTABLISH_LINE_OF_FIRE); - } - } - } - - // no special cases here, call the base class - return CSquadMonster ::GetSchedule(); -} - -//========================================================= -//========================================================= -Schedule_t *CHGrunt ::GetScheduleOfType(int Type) -{ - switch (Type) - { - case SCHED_TAKE_COVER_FROM_ENEMY: - { - if (InSquad()) - { - if (g_iSkillLevel == SKILL_HARD && HasConditions(bits_COND_CAN_RANGE_ATTACK2) && OccupySlot(bits_SLOTS_HGRUNT_GRENADE)) - { - if (FOkToSpeak()) - { - SENTENCEG_PlayRndSz(ENT(pev), "HG_THROW", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch); - JustSpoke(); - } - return slGruntTossGrenadeCover; - } - else - { - return &slGruntTakeCover[0]; - } - } - else - { - if (RANDOM_LONG(0, 1)) - { - return &slGruntTakeCover[0]; - } - else - { - return &slGruntGrenadeCover[0]; - } - } - } - case SCHED_TAKE_COVER_FROM_BEST_SOUND: - { - return &slGruntTakeCoverFromBestSound[0]; - } - case SCHED_GRUNT_TAKECOVER_FAILED: - { - if (HasConditions(bits_COND_CAN_RANGE_ATTACK1) && OccupySlot(bits_SLOTS_HGRUNT_ENGAGE)) - { - return GetScheduleOfType(SCHED_RANGE_ATTACK1); - } - - return GetScheduleOfType(SCHED_FAIL); - } - break; - case SCHED_GRUNT_ELOF_FAIL: - { - // human grunt is unable to move to a position that allows him to attack the enemy. - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_ENEMY); - } - break; - case SCHED_GRUNT_ESTABLISH_LINE_OF_FIRE: - { - return &slGruntEstablishLineOfFire[0]; - } - break; - case SCHED_RANGE_ATTACK1: - { - // randomly stand or crouch - if (RANDOM_LONG(0, 9) == 0) - m_fStanding = RANDOM_LONG(0, 1); - - if (m_fStanding) - return &slGruntRangeAttack1B[0]; - else - return &slGruntRangeAttack1A[0]; - } - case SCHED_RANGE_ATTACK2: - { - return &slGruntRangeAttack2[0]; - } - case SCHED_COMBAT_FACE: - { - return &slGruntCombatFace[0]; - } - case SCHED_GRUNT_WAIT_FACE_ENEMY: - { - return &slGruntWaitInCover[0]; - } - case SCHED_GRUNT_SWEEP: - { - return &slGruntSweep[0]; - } - case SCHED_GRUNT_COVER_AND_RELOAD: - { - return &slGruntHideReload[0]; - } - case SCHED_GRUNT_FOUND_ENEMY: - { - return &slGruntFoundEnemy[0]; - } - case SCHED_VICTORY_DANCE: - { - if (InSquad()) - { - if (!IsLeader()) - { - return &slGruntFail[0]; - } - } - - return &slGruntVictoryDance[0]; - } - case SCHED_GRUNT_SUPPRESS: - { - if (m_hEnemy->IsPlayer() && m_fFirstEncounter) - { - m_fFirstEncounter = FALSE; // after first encounter, leader won't issue handsigns anymore when he has a new enemy - return &slGruntSignalSuppress[0]; - } - else - { - return &slGruntSuppress[0]; - } - } - case SCHED_FAIL: - { - if (m_hEnemy != NULL) - { - // grunt has an enemy, so pick a different default fail schedule most likely to help recover. - return &slGruntCombatFail[0]; - } - - return &slGruntFail[0]; - } - case SCHED_GRUNT_REPEL: - { - if (pev->velocity.z > -128) - pev->velocity.z -= 32; - return &slGruntRepel[0]; - } - case SCHED_GRUNT_REPEL_ATTACK: - { - if (pev->velocity.z > -128) - pev->velocity.z -= 32; - return &slGruntRepelAttack[0]; - } - case SCHED_GRUNT_REPEL_LAND: - { - return &slGruntRepelLand[0]; - } - default: - { - return CSquadMonster ::GetScheduleOfType(Type); - } - } -} - -//========================================================= -// CHGruntRepel - when triggered, spawns a monster_human_grunt -// repelling down a line. -//========================================================= - -class CHGruntRepel : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void EXPORT RepelUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - int m_iSpriteTexture; // Don't save, precache -}; - -LINK_ENTITY_TO_CLASS(monster_grunt_repel, CHGruntRepel); - -void CHGruntRepel::Spawn(void) -{ - Precache(); - pev->solid = SOLID_NOT; - - SetUse(RepelUse); -} - -void CHGruntRepel::Precache(void) -{ - UTIL_PrecacheOther("monster_human_grunt"); - m_iSpriteTexture = PRECACHE_MODEL("sprites/rope.spr"); -} - -void CHGruntRepel::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_human_grunt", 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(SUB_Remove); - pBeam->pev->nextthink = gpGlobals->time + -4096.0 * tr.flFraction / pGrunt->pev->velocity.z + 0.5; - - UTIL_Remove(this); -} - -//========================================================= -// DEAD HGRUNT PROP -//========================================================= -class CDeadHGrunt : public CBaseMonster -{ -public: - void Spawn(void); - int Classify(void) { return CLASS_HUMAN_MILITARY; } - - void KeyValue(KeyValueData *pkvd); - - int m_iPose; // which sequence to display -- temporary, don't need to save - static char *m_szPoses[3]; -}; - -char *CDeadHGrunt::m_szPoses[] = {"deadstomach", "deadside", "deadsitting"}; - -void CDeadHGrunt::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "pose")) - { - m_iPose = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else - CBaseMonster::KeyValue(pkvd); -} - -LINK_ENTITY_TO_CLASS(monster_hgrunt_dead, CDeadHGrunt); - -//========================================================= -// ********** DeadHGrunt SPAWN ********** -//========================================================= -void CDeadHGrunt ::Spawn(void) -{ - PRECACHE_MODEL("models/hgrunt.mdl"); - SET_MODEL(ENT(pev), "models/hgrunt.mdl"); - - pev->effects = 0; - pev->yaw_speed = 8; - pev->sequence = 0; - m_bloodColor = BLOOD_COLOR_RED; - - pev->sequence = LookupSequence(m_szPoses[m_iPose]); - - if (pev->sequence == -1) - { - ALERT(at_console, "Dead hgrunt with bad pose\n"); - } - - // Corpses have less health - pev->health = 8; - - // map old bodies onto new bodies - switch (pev->body) - { - case 0: // Grunt with Gun - pev->body = 0; - pev->skin = 0; - SetBodygroup(HEAD_GROUP, HEAD_GRUNT); - SetBodygroup(GUN_GROUP, GUN_MP5); - break; - case 1: // Commander with Gun - pev->body = 0; - pev->skin = 0; - SetBodygroup(HEAD_GROUP, HEAD_COMMANDER); - SetBodygroup(GUN_GROUP, GUN_MP5); - break; - case 2: // Grunt no Gun - pev->body = 0; - pev->skin = 0; - SetBodygroup(HEAD_GROUP, HEAD_GRUNT); - SetBodygroup(GUN_GROUP, GUN_NONE); - break; - case 3: // Commander no Gun - pev->body = 0; - pev->skin = 0; - SetBodygroup(HEAD_GROUP, HEAD_COMMANDER); - SetBodygroup(GUN_GROUP, GUN_NONE); - break; - } - - MonsterInitDead(); -} diff --git a/dlls/Half-life/hornet.cpp b/dlls/Half-life/hornet.cpp deleted file mode 100644 index 28fcb5b6..00000000 --- a/dlls/Half-life/hornet.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -//========================================================= -// Hornets -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "soundent.h" -#include "hornet.h" -#include "gamerules.h" - -int iHornetTrail; -int iHornetPuff; - -LINK_ENTITY_TO_CLASS(hornet, CHornet); - -//========================================================= -// Save/Restore -//========================================================= -TYPEDESCRIPTION CHornet::m_SaveData[] = - { - DEFINE_FIELD(CHornet, m_flStopAttack, FIELD_TIME), - DEFINE_FIELD(CHornet, m_iHornetType, FIELD_INTEGER), - DEFINE_FIELD(CHornet, m_flFlySpeed, FIELD_FLOAT), -}; - -IMPLEMENT_SAVERESTORE(CHornet, CBaseMonster); - -//========================================================= -// don't let hornets gib, ever. -//========================================================= -int CHornet ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - // filter these bits a little. - bitsDamageType &= ~(DMG_ALWAYSGIB); - bitsDamageType |= DMG_NEVERGIB; - - return CBaseMonster ::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -//========================================================= -//========================================================= -void CHornet ::Spawn(void) -{ - Precache(); - - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - pev->takedamage = DAMAGE_YES; - pev->flags |= FL_MONSTER; - pev->health = 1; // weak! - - if (g_pGameRules->IsMultiplayer()) - { - // hornets don't live as long in multiplayer - m_flStopAttack = gpGlobals->time + 3.5; - } - else - { - m_flStopAttack = gpGlobals->time + 5.0; - } - - m_flFieldOfView = 0.9; // +- 25 degrees - - if (RANDOM_LONG(1, 5) <= 2) - { - m_iHornetType = HORNET_TYPE_RED; - m_flFlySpeed = HORNET_RED_SPEED; - } - else - { - m_iHornetType = HORNET_TYPE_ORANGE; - m_flFlySpeed = HORNET_ORANGE_SPEED; - } - - SET_MODEL(ENT(pev), "models/hornet.mdl"); - UTIL_SetSize(pev, Vector(-4, -4, -4), Vector(4, 4, 4)); - - SetTouch(DieTouch); - SetThink(StartTrack); - - edict_t *pSoundEnt = pev->owner; - if (!pSoundEnt) - pSoundEnt = edict(); - - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(pSoundEnt, CHAN_WEAPON, "agrunt/ag_fire1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(pSoundEnt, CHAN_WEAPON, "agrunt/ag_fire2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(pSoundEnt, CHAN_WEAPON, "agrunt/ag_fire3.wav", 1, ATTN_NORM); - break; - } - - if (!FNullEnt(pev->owner) && (pev->owner->v.flags & FL_CLIENT)) - { - pev->dmg = gSkillData.plrDmgHornet; - } - else - { - // no real owner, or owner isn't a client. - pev->dmg = gSkillData.monDmgHornet; - } - - pev->nextthink = gpGlobals->time + 0.1; - ResetSequenceInfo(); -} - -void CHornet ::Precache() -{ - PRECACHE_MODEL("models/hornet.mdl"); - - PRECACHE_SOUND("agrunt/ag_fire1.wav"); - PRECACHE_SOUND("agrunt/ag_fire2.wav"); - PRECACHE_SOUND("agrunt/ag_fire3.wav"); - - PRECACHE_SOUND("hornet/ag_buzz1.wav"); - PRECACHE_SOUND("hornet/ag_buzz2.wav"); - PRECACHE_SOUND("hornet/ag_buzz3.wav"); - - PRECACHE_SOUND("hornet/ag_hornethit1.wav"); - PRECACHE_SOUND("hornet/ag_hornethit2.wav"); - PRECACHE_SOUND("hornet/ag_hornethit3.wav"); - - iHornetPuff = PRECACHE_MODEL("sprites/muz1.spr"); - iHornetTrail = PRECACHE_MODEL("sprites/laserbeam.spr"); -} - -//========================================================= -// hornets will never get mad at each other, no matter who the owner is. -//========================================================= -int CHornet::IRelationship(CBaseEntity *pTarget) -{ - if (pTarget->pev->modelindex == pev->modelindex) - { - return R_NO; - } - - return CBaseMonster ::IRelationship(pTarget); -} - -//========================================================= -// ID's Hornet as their owner -//========================================================= -int CHornet::Classify(void) -{ - - if (pev->owner && pev->owner->v.flags & FL_CLIENT) - { - return CLASS_PLAYER_BIOWEAPON; - } - - return CLASS_ALIEN_BIOWEAPON; -} - -//========================================================= -// StartTrack - starts a hornet out tracking its target -//========================================================= -void CHornet ::StartTrack(void) -{ - IgniteTrail(); - - SetTouch(TrackTouch); - SetThink(TrackTarget); - - pev->nextthink = gpGlobals->time + 0.1; -} - -//========================================================= -// StartDart - starts a hornet out just flying straight. -//========================================================= -void CHornet ::StartDart(void) -{ - IgniteTrail(); - - SetTouch(DartTouch); - - SetThink(SUB_Remove); - pev->nextthink = gpGlobals->time + 4; -} - -void CHornet::IgniteTrail(void) -{ - /* - - ted's suggested trail colors: - -r161 -g25 -b97 - -r173 -g39 -b14 - -old colors - case HORNET_TYPE_RED: - WRITE_BYTE( 255 ); // r, g, b - WRITE_BYTE( 128 ); // r, g, b - WRITE_BYTE( 0 ); // r, g, b - break; - case HORNET_TYPE_ORANGE: - WRITE_BYTE( 0 ); // r, g, b - WRITE_BYTE( 100 ); // r, g, b - WRITE_BYTE( 255 ); // r, g, b - break; - -*/ - - // trail - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_BEAMFOLLOW); - WRITE_SHORT(entindex()); // entity - WRITE_SHORT(iHornetTrail); // model - WRITE_BYTE(10); // life - WRITE_BYTE(2); // width - - switch (m_iHornetType) - { - case HORNET_TYPE_RED: - WRITE_BYTE(179); // r, g, b - WRITE_BYTE(39); // r, g, b - WRITE_BYTE(14); // r, g, b - break; - case HORNET_TYPE_ORANGE: - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(128); // r, g, b - WRITE_BYTE(0); // r, g, b - break; - } - - WRITE_BYTE(128); // brightness - - MESSAGE_END(); -} - -//========================================================= -// Hornet is flying, gently tracking target -//========================================================= -void CHornet ::TrackTarget(void) -{ - Vector vecFlightDir; - Vector vecDirToEnemy; - float flDelta; - - StudioFrameAdvance(); - - if (gpGlobals->time > m_flStopAttack) - { - SetTouch(NULL); - SetThink(SUB_Remove); - pev->nextthink = gpGlobals->time + 0.1; - return; - } - - // UNDONE: The player pointer should come back after returning from another level - if (m_hEnemy == NULL) - { // enemy is dead. - Look(512); - m_hEnemy = BestVisibleEnemy(); - } - - if (m_hEnemy != NULL && FVisible(m_hEnemy)) - { - m_vecEnemyLKP = m_hEnemy->BodyTarget(pev->origin); - } - else - { - m_vecEnemyLKP = m_vecEnemyLKP + pev->velocity * m_flFlySpeed * 0.1; - } - - vecDirToEnemy = (m_vecEnemyLKP - pev->origin).Normalize(); - - if (pev->velocity.Length() < 0.1) - vecFlightDir = vecDirToEnemy; - else - vecFlightDir = pev->velocity.Normalize(); - - // measure how far the turn is, the wider the turn, the slow we'll go this time. - flDelta = DotProduct(vecFlightDir, vecDirToEnemy); - - if (flDelta < 0.5) - { // hafta turn wide again. play sound - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hornet/ag_buzz1.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hornet/ag_buzz2.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hornet/ag_buzz3.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); - break; - } - } - - if (flDelta <= 0 && m_iHornetType == HORNET_TYPE_RED) - { // no flying backwards, but we don't want to invert this, cause we'd go fast when we have to turn REAL far. - flDelta = 0.25; - } - - pev->velocity = (vecFlightDir + vecDirToEnemy).Normalize(); - - if (pev->owner && (pev->owner->v.flags & FL_MONSTER)) - { - // random pattern only applies to hornets fired by monsters, not players. - - pev->velocity.x += RANDOM_FLOAT(-0.10, 0.10); // scramble the flight dir a bit. - pev->velocity.y += RANDOM_FLOAT(-0.10, 0.10); - pev->velocity.z += RANDOM_FLOAT(-0.10, 0.10); - } - - switch (m_iHornetType) - { - case HORNET_TYPE_RED: - pev->velocity = pev->velocity * (m_flFlySpeed * flDelta); // scale the dir by the ( speed * width of turn ) - pev->nextthink = gpGlobals->time + RANDOM_FLOAT(0.1, 0.3); - break; - case HORNET_TYPE_ORANGE: - pev->velocity = pev->velocity * m_flFlySpeed; // do not have to slow down to turn. - pev->nextthink = gpGlobals->time + 0.1; // fixed think time - break; - } - - pev->angles = UTIL_VecToAngles(pev->velocity); - - pev->solid = SOLID_BBOX; - - // if hornet is close to the enemy, jet in a straight line for a half second. - // (only in the single player game) - if (m_hEnemy != NULL && !g_pGameRules->IsMultiplayer()) - { - if (flDelta >= 0.4 && (pev->origin - m_vecEnemyLKP).Length() <= 300) - { - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_SPRITE); - WRITE_COORD(pev->origin.x); // pos - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_SHORT(iHornetPuff); // model - // WRITE_BYTE( 0 ); // life * 10 - WRITE_BYTE(2); // size * 10 - WRITE_BYTE(128); // brightness - MESSAGE_END(); - - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hornet/ag_buzz1.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hornet/ag_buzz2.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hornet/ag_buzz3.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); - break; - } - pev->velocity = pev->velocity * 2; - pev->nextthink = gpGlobals->time + 1.0; - // don't attack again - m_flStopAttack = gpGlobals->time; - } - } -} - -//========================================================= -// Tracking Hornet hit something -//========================================================= -void CHornet ::TrackTouch(CBaseEntity *pOther) -{ - if (pOther->edict() == pev->owner || pOther->pev->modelindex == pev->modelindex) - { // bumped into the guy that shot it. - pev->solid = SOLID_NOT; - return; - } - - if (IRelationship(pOther) <= R_NO) - { - // hit something we don't want to hurt, so turn around. - - pev->velocity = pev->velocity.Normalize(); - - pev->velocity.x *= -1; - pev->velocity.y *= -1; - - pev->origin = pev->origin + pev->velocity * 4; // bounce the hornet off a bit. - pev->velocity = pev->velocity * m_flFlySpeed; - - return; - } - - DieTouch(pOther); -} - -void CHornet::DartTouch(CBaseEntity *pOther) -{ - DieTouch(pOther); -} - -void CHornet::DieTouch(CBaseEntity *pOther) -{ - if (pOther && pOther->pev->takedamage) - { // do the damage - - switch (RANDOM_LONG(0, 2)) - { // buzz when you plug someone - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hornet/ag_hornethit1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hornet/ag_hornethit2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "hornet/ag_hornethit3.wav", 1, ATTN_NORM); - break; - } - - pOther->TakeDamage(pev, VARS(pev->owner), pev->dmg, DMG_BULLET); - } - - pev->modelindex = 0; // so will disappear for the 0.1 secs we wait until NEXTTHINK gets rid - pev->solid = SOLID_NOT; - - SetThink(SUB_Remove); - pev->nextthink = gpGlobals->time + 1; // stick around long enough for the sound to finish! -} diff --git a/dlls/Half-life/hornet.h b/dlls/Half-life/hornet.h deleted file mode 100644 index 22f0a55c..00000000 --- a/dlls/Half-life/hornet.h +++ /dev/null @@ -1,57 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -//========================================================= -// Hornets -//========================================================= - -//========================================================= -// Hornet Defines -//========================================================= -#define HORNET_TYPE_RED 0 -#define HORNET_TYPE_ORANGE 1 -#define HORNET_RED_SPEED (float)600 -#define HORNET_ORANGE_SPEED (float)800 -#define HORNET_BUZZ_VOLUME (float)0.8 - -extern int iHornetPuff; - -//========================================================= -// Hornet - this is the projectile that the Alien Grunt fires. -//========================================================= -class CHornet : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - int Classify(void); - int IRelationship(CBaseEntity *pTarget); - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void IgniteTrail(void); - void EXPORT StartTrack(void); - void EXPORT StartDart(void); - void EXPORT TrackTarget(void); - void EXPORT TrackTouch(CBaseEntity *pOther); - void EXPORT DartTouch(CBaseEntity *pOther); - void EXPORT DieTouch(CBaseEntity *pOther); - - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - - float m_flStopAttack; - int m_iHornetType; - float m_flFlySpeed; -}; diff --git a/dlls/Half-life/hornetgun.cpp b/dlls/Half-life/hornetgun.cpp deleted file mode 100644 index 82d0b0a3..00000000 --- a/dlls/Half-life/hornetgun.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "hornet.h" -#include "gamerules.h" - -enum hgun_e -{ - HGUN_IDLE1 = 0, - HGUN_FIDGETSWAY, - HGUN_FIDGETSHAKE, - HGUN_DOWN, - HGUN_UP, - HGUN_SHOOT -}; - -class CHgun : public CBasePlayerWeapon -{ -public: - void Spawn(void); - void Precache(void); - int iItemSlot(void) { return 4; } - int GetItemInfo(ItemInfo *p); - int AddToPlayer(CBasePlayer *pPlayer); - - void PrimaryAttack(void); - void SecondaryAttack(void); - BOOL Deploy(void); - BOOL IsUseable(void); - void Holster(int skiplocal = 0); - void Reload(void); - void WeaponIdle(void); - float m_flNextAnimTime; - - float m_flRechargeTime; - - int m_iFirePhase; // don't save me. -}; -LINK_ENTITY_TO_CLASS(weapon_hornetgun, CHgun); - -BOOL CHgun::IsUseable(void) -{ - return TRUE; -} - -void CHgun::Spawn() -{ - Precache(); - m_iId = WEAPON_HORNETGUN; - SET_MODEL(ENT(pev), "models/w_hgun.mdl"); - - m_iDefaultAmmo = HIVEHAND_DEFAULT_GIVE; - m_iFirePhase = 0; - - FallInit(); // get ready to fall down. -} - -void CHgun::Precache(void) -{ - PRECACHE_MODEL("models/v_hgun.mdl"); - PRECACHE_MODEL("models/w_hgun.mdl"); - PRECACHE_MODEL("models/p_hgun.mdl"); - - UTIL_PrecacheOther("hornet"); -} - -int CHgun::AddToPlayer(CBasePlayer *pPlayer) -{ - if (CBasePlayerWeapon::AddToPlayer(pPlayer)) - { - if (g_pGameRules->IsMultiplayer()) - { - // in multiplayer, all hivehands come full. - pPlayer->m_rgAmmo[PrimaryAmmoIndex()] = HORNET_MAX_CARRY; - } - - MESSAGE_BEGIN(MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev); - WRITE_BYTE(m_iId); - MESSAGE_END(); - return TRUE; - } - return FALSE; -} - -int CHgun::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "Hornets"; - p->iMaxAmmo1 = HORNET_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = WEAPON_NOCLIP; - p->iSlot = 3; - p->iPosition = 3; - p->iId = m_iId = WEAPON_HORNETGUN; - p->iFlags = ITEM_FLAG_NOAUTOSWITCHEMPTY | ITEM_FLAG_NOAUTORELOAD; - p->iWeight = HORNETGUN_WEIGHT; - - return 1; -} - -BOOL CHgun::Deploy() -{ - return DefaultDeploy("models/v_hgun.mdl", "models/p_hgun.mdl", HGUN_UP, "hive"); -} - -void CHgun::Holster(int skiplocal /* = 0 */) -{ - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - // m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 ); - SendWeaponAnim(HGUN_DOWN); - - //!!!HACKHACK - can't select hornetgun if it's empty! no way to get ammo for it, either. - if (!m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()]) - { - m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] = 1; - } -} - -void CHgun::PrimaryAttack() -{ - Reload(); - - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - { - return; - } - - UTIL_MakeVectors(m_pPlayer->pev->v_angle); - - CBaseEntity *pHornet = CBaseEntity::Create("hornet", m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12, m_pPlayer->pev->v_angle, m_pPlayer->edict()); - pHornet->pev->velocity = gpGlobals->v_forward * 300; - - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; - m_flRechargeTime = gpGlobals->time + 0.5; - - m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; - m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH; - - SendWeaponAnim(HGUN_SHOOT); - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - m_flNextPrimaryAttack = m_flNextPrimaryAttack + 0.25; - - if (m_flNextPrimaryAttack < gpGlobals->time) - { - m_flNextPrimaryAttack = gpGlobals->time + 0.25; - } - - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); -} - -void CHgun::SecondaryAttack(void) -{ - Reload(); - - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - { - return; - } - - CBaseEntity *pHornet; - Vector vecSrc; - - UTIL_MakeVectors(m_pPlayer->pev->v_angle); - - vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12; - - m_iFirePhase++; - switch (m_iFirePhase) - { - case 1: - vecSrc = vecSrc + gpGlobals->v_up * 8; - break; - case 2: - vecSrc = vecSrc + gpGlobals->v_up * 8; - vecSrc = vecSrc + gpGlobals->v_right * 8; - break; - case 3: - vecSrc = vecSrc + gpGlobals->v_right * 8; - break; - case 4: - vecSrc = vecSrc + gpGlobals->v_up * -8; - vecSrc = vecSrc + gpGlobals->v_right * 8; - break; - case 5: - vecSrc = vecSrc + gpGlobals->v_up * -8; - break; - case 6: - vecSrc = vecSrc + gpGlobals->v_up * -8; - vecSrc = vecSrc + gpGlobals->v_right * -8; - break; - case 7: - vecSrc = vecSrc + gpGlobals->v_right * -8; - break; - case 8: - vecSrc = vecSrc + gpGlobals->v_up * 8; - vecSrc = vecSrc + gpGlobals->v_right * -8; - m_iFirePhase = 0; - break; - } - - pHornet = CBaseEntity::Create("hornet", vecSrc, m_pPlayer->pev->v_angle, m_pPlayer->edict()); - pHornet->pev->velocity = gpGlobals->v_forward * 1200; - pHornet->pev->angles = UTIL_VecToAngles(pHornet->pev->velocity); - - pHornet->SetThink(CHornet::StartDart); - - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; - m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME; - m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH; - - m_flRechargeTime = gpGlobals->time + 0.5; - - SendWeaponAnim(HGUN_SHOOT); - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->time + 0.1; - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); - m_pPlayer->pev->punchangle.x = RANDOM_FLOAT(0, 2); -} - -void CHgun::Reload(void) -{ - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] >= HORNET_MAX_CARRY) - return; - - while (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < HORNET_MAX_CARRY && m_flRechargeTime < gpGlobals->time) - { - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]++; - m_flRechargeTime += 0.5; - } -} - -void CHgun::WeaponIdle(void) -{ - Reload(); - - if (m_flTimeWeaponIdle > gpGlobals->time) - return; - - int iAnim; - float flRand = RANDOM_FLOAT(0, 1); - if (flRand <= 0.75) - { - iAnim = HGUN_IDLE1; - m_flTimeWeaponIdle = gpGlobals->time + 30.0 / 16 * (2); - } - else if (flRand <= 0.875) - { - iAnim = HGUN_FIDGETSWAY; - m_flTimeWeaponIdle = gpGlobals->time + 40.0 / 16.0; - } - else - { - iAnim = HGUN_FIDGETSHAKE; - m_flTimeWeaponIdle = gpGlobals->time + 35.0 / 16.0; - } - SendWeaponAnim(iAnim); -} - -#endif \ No newline at end of file diff --git a/dlls/Half-life/houndeye.cpp b/dlls/Half-life/houndeye.cpp deleted file mode 100644 index 124ce6a2..00000000 --- a/dlls/Half-life/houndeye.cpp +++ /dev/null @@ -1,1282 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// Houndeye - spooky sonic dog. -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" -#include "animation.h" -#include "nodes.h" -#include "squadmonster.h" -#include "soundent.h" - -extern CGraph WorldGraph; - -// houndeye does 20 points of damage spread over a sphere 384 units in diameter, and each additional -// squad member increases the BASE damage by 110%, per the spec. -#define HOUNDEYE_MAX_SQUAD_SIZE 4 -#define HOUNDEYE_MAX_ATTACK_RADIUS 384 -#define HOUNDEYE_SQUAD_BONUS (float)1.1 - -#define HOUNDEYE_EYE_FRAMES 4 // how many different switchable maps for the eye - -#define HOUNDEYE_SOUND_STARTLE_VOLUME 128 // how loud a sound has to be to badly scare a sleeping houndeye - -//========================================================= -// monster-specific tasks -//========================================================= -enum -{ - TASK_HOUND_CLOSE_EYE = LAST_COMMON_TASK + 1, - TASK_HOUND_OPEN_EYE, - TASK_HOUND_THREAT_DISPLAY, - TASK_HOUND_FALL_ASLEEP, - TASK_HOUND_WAKE_UP, - TASK_HOUND_HOP_BACK -}; - -//========================================================= -// monster-specific schedule types -//========================================================= -enum -{ - SCHED_HOUND_AGITATED = LAST_COMMON_SCHEDULE + 1, - SCHED_HOUND_HOP_RETREAT, - SCHED_HOUND_FAIL, -}; - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define HOUND_AE_WARN 1 -#define HOUND_AE_STARTATTACK 2 -#define HOUND_AE_THUMP 3 -#define HOUND_AE_ANGERSOUND1 4 -#define HOUND_AE_ANGERSOUND2 5 -#define HOUND_AE_HOPBACK 6 -#define HOUND_AE_CLOSE_EYE 7 - -class CHoundeye : public CSquadMonster -{ -public: - void Spawn(void); - void Precache(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - void SetYawSpeed(void); - void WarmUpSound(void); - void AlertSound(void); - void DeathSound(void); - void WarnSound(void); - void PainSound(void); - void IdleSound(void); - void StartTask(Task_t *pTask); - void RunTask(Task_t *pTask); - void SonicAttack(void); - void PrescheduleThink(void); - void SetActivity(Activity NewActivity); - void WriteBeamColor(void); - BOOL CheckRangeAttack1(float flDot, float flDist); - BOOL FValidateHintType(short sHint); - BOOL FCanActiveIdle(void); - Schedule_t *GetScheduleOfType(int Type); - Schedule_t *CHoundeye ::GetSchedule(void); - - int Save(CSave &save); - int Restore(CRestore &restore); - - CUSTOM_SCHEDULES; - static TYPEDESCRIPTION m_SaveData[]; - - int m_iSpriteTexture; - BOOL m_fAsleep; // some houndeyes sleep in idle mode if this is set, the houndeye is lying down - BOOL m_fDontBlink; // don't try to open/close eye if this bit is set! - Vector m_vecPackCenter; // the center of the pack. The leader maintains this by averaging the origins of all pack members. -}; -LINK_ENTITY_TO_CLASS(monster_houndeye, CHoundeye); - -TYPEDESCRIPTION CHoundeye::m_SaveData[] = - { - DEFINE_FIELD(CHoundeye, m_iSpriteTexture, FIELD_INTEGER), - DEFINE_FIELD(CHoundeye, m_fAsleep, FIELD_BOOLEAN), - DEFINE_FIELD(CHoundeye, m_fDontBlink, FIELD_BOOLEAN), - DEFINE_FIELD(CHoundeye, m_vecPackCenter, FIELD_POSITION_VECTOR), -}; - -IMPLEMENT_SAVERESTORE(CHoundeye, CSquadMonster); - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CHoundeye ::Classify(void) -{ - return CLASS_ALIEN_MONSTER; -} - -//========================================================= -// FValidateHintType -//========================================================= -BOOL CHoundeye ::FValidateHintType(short sHint) -{ - int i; - - static short sHoundHints[] = - { - HINT_WORLD_MACHINERY, - HINT_WORLD_BLINKING_LIGHT, - HINT_WORLD_HUMAN_BLOOD, - HINT_WORLD_ALIEN_BLOOD, - }; - - for (i = 0; i < ARRAYSIZE(sHoundHints); i++) - { - if (sHoundHints[i] == sHint) - { - return TRUE; - } - } - - ALERT(at_aiconsole, "Couldn't validate hint type"); - return FALSE; -} - -//========================================================= -// FCanActiveIdle -//========================================================= -BOOL CHoundeye ::FCanActiveIdle(void) -{ - if (InSquad()) - { - CSquadMonster *pSquadLeader = MySquadLeader(); - - for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) - { - CSquadMonster *pMember = pSquadLeader->MySquadMember(i); - - if (pMember != NULL && pMember != this && pMember->m_iHintNode != NO_NODE) - { - // someone else in the group is active idling right now! - return FALSE; - } - } - - return TRUE; - } - - return TRUE; -} - -//========================================================= -// CheckRangeAttack1 - overridden for houndeyes so that they -// try to get within half of their max attack radius before -// attacking, so as to increase their chances of doing damage. -//========================================================= -BOOL CHoundeye ::CheckRangeAttack1(float flDot, float flDist) -{ - if (flDist <= (HOUNDEYE_MAX_ATTACK_RADIUS * 0.5) && flDot >= 0.3) - { - return TRUE; - } - return FALSE; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CHoundeye ::SetYawSpeed(void) -{ - int ys; - - ys = 90; - - switch (m_Activity) - { - case ACT_CROUCHIDLE: //sleeping! - ys = 0; - break; - case ACT_IDLE: - ys = 60; - break; - case ACT_WALK: - ys = 90; - break; - case ACT_RUN: - ys = 90; - break; - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - ys = 90; - break; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// SetActivity -//========================================================= -void CHoundeye ::SetActivity(Activity NewActivity) -{ - int iSequence; - - if (NewActivity == m_Activity) - return; - - if (m_MonsterState == MONSTERSTATE_COMBAT && NewActivity == ACT_IDLE && RANDOM_LONG(0, 1)) - { - // play pissed idle. - iSequence = LookupSequence("madidle"); - - m_Activity = NewActivity; // Go ahead and set this so it doesn't keep trying when the anim is not present - - // In case someone calls this with something other than the ideal activity - m_IdealActivity = m_Activity; - - // Set to the desired anim, or default anim if the desired is not present - if (iSequence > ACTIVITY_NOT_AVAILABLE) - { - pev->sequence = iSequence; // Set to the reset anim (if it's there) - pev->frame = 0; // FIX: frame counter shouldn't be reset when its the same activity as before - ResetSequenceInfo(); - SetYawSpeed(); - } - } - else - { - CSquadMonster ::SetActivity(NewActivity); - } -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CHoundeye ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case HOUND_AE_WARN: - // do stuff for this event. - WarnSound(); - break; - - case HOUND_AE_STARTATTACK: - WarmUpSound(); - break; - - case HOUND_AE_HOPBACK: - { - float flGravity = CVAR_GET_FLOAT("sv_gravity"); - - pev->flags &= ~FL_ONGROUND; - - pev->velocity = gpGlobals->v_forward * -200; - pev->velocity.z += (0.6 * flGravity) * 0.5; - - break; - } - - case HOUND_AE_THUMP: - // emit the shockwaves - SonicAttack(); - break; - - case HOUND_AE_ANGERSOUND1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_pain3.wav", 1, ATTN_NORM); - break; - - case HOUND_AE_ANGERSOUND2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_pain1.wav", 1, ATTN_NORM); - break; - - case HOUND_AE_CLOSE_EYE: - if (!m_fDontBlink) - { - pev->skin = HOUNDEYE_EYE_FRAMES - 1; - } - break; - - default: - CSquadMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CHoundeye ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/houndeye.mdl"); - UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 36)); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_YELLOW; - pev->effects = 0; - pev->health = gSkillData.houndeyeHealth; - pev->yaw_speed = 5; //!!! should we put this in the monster's changeanim function since turn rates may vary with state/anim? - m_flFieldOfView = 0.5; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - m_fAsleep = FALSE; // everyone spawns awake - m_fDontBlink = FALSE; - m_afCapability |= bits_CAP_SQUAD; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CHoundeye ::Precache() -{ - PRECACHE_MODEL("models/houndeye.mdl"); - - PRECACHE_SOUND("houndeye/he_alert1.wav"); - PRECACHE_SOUND("houndeye/he_alert2.wav"); - PRECACHE_SOUND("houndeye/he_alert3.wav"); - - PRECACHE_SOUND("houndeye/he_die1.wav"); - PRECACHE_SOUND("houndeye/he_die2.wav"); - PRECACHE_SOUND("houndeye/he_die3.wav"); - - PRECACHE_SOUND("houndeye/he_idle1.wav"); - PRECACHE_SOUND("houndeye/he_idle2.wav"); - PRECACHE_SOUND("houndeye/he_idle3.wav"); - - PRECACHE_SOUND("houndeye/he_hunt1.wav"); - PRECACHE_SOUND("houndeye/he_hunt2.wav"); - PRECACHE_SOUND("houndeye/he_hunt3.wav"); - - PRECACHE_SOUND("houndeye/he_pain1.wav"); - PRECACHE_SOUND("houndeye/he_pain3.wav"); - PRECACHE_SOUND("houndeye/he_pain4.wav"); - PRECACHE_SOUND("houndeye/he_pain5.wav"); - - PRECACHE_SOUND("houndeye/he_attack1.wav"); - PRECACHE_SOUND("houndeye/he_attack3.wav"); - - PRECACHE_SOUND("houndeye/he_blast1.wav"); - PRECACHE_SOUND("houndeye/he_blast2.wav"); - PRECACHE_SOUND("houndeye/he_blast3.wav"); - - m_iSpriteTexture = PRECACHE_MODEL("sprites/shockwave.spr"); -} - -//========================================================= -// IdleSound -//========================================================= -void CHoundeye ::IdleSound(void) -{ - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_idle1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_idle2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_idle3.wav", 1, ATTN_NORM); - break; - } -} - -//========================================================= -// IdleSound -//========================================================= -void CHoundeye ::WarmUpSound(void) -{ - switch (RANDOM_LONG(0, 1)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "houndeye/he_attack1.wav", 0.7, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "houndeye/he_attack3.wav", 0.7, ATTN_NORM); - break; - } -} - -//========================================================= -// WarnSound -//========================================================= -void CHoundeye ::WarnSound(void) -{ - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_hunt1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_hunt2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_hunt3.wav", 1, ATTN_NORM); - break; - } -} - -//========================================================= -// AlertSound -//========================================================= -void CHoundeye ::AlertSound(void) -{ - - if (InSquad() && !IsLeader()) - { - return; // only leader makes ALERT sound. - } - - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_alert1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_alert2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_alert3.wav", 1, ATTN_NORM); - break; - } -} - -//========================================================= -// DeathSound -//========================================================= -void CHoundeye ::DeathSound(void) -{ - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_die1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_die2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_die3.wav", 1, ATTN_NORM); - break; - } -} - -//========================================================= -// PainSound -//========================================================= -void CHoundeye ::PainSound(void) -{ - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_pain3.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_pain4.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "houndeye/he_pain5.wav", 1, ATTN_NORM); - break; - } -} - -//========================================================= -// WriteBeamColor - writes a color vector to the network -// based on the size of the group. -//========================================================= -void CHoundeye ::WriteBeamColor(void) -{ - BYTE bRed, bGreen, bBlue; - - if (InSquad()) - { - switch (SquadCount()) - { - case 2: - // no case for 0 or 1, cause those are impossible for monsters in Squads. - bRed = 101; - bGreen = 133; - bBlue = 221; - break; - case 3: - bRed = 67; - bGreen = 85; - bBlue = 255; - break; - case 4: - bRed = 62; - bGreen = 33; - bBlue = 211; - break; - default: - ALERT(at_aiconsole, "Unsupported Houndeye SquadSize!\n"); - bRed = 188; - bGreen = 220; - bBlue = 255; - break; - } - } - else - { - // solo houndeye - weakest beam - bRed = 188; - bGreen = 220; - bBlue = 255; - } - - WRITE_BYTE(bRed); - WRITE_BYTE(bGreen); - WRITE_BYTE(bBlue); -} - -//========================================================= -// SonicAttack -//========================================================= -void CHoundeye ::SonicAttack(void) -{ - float flAdjustedDamage; - float flDist; - - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "houndeye/he_blast1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "houndeye/he_blast2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "houndeye/he_blast3.wav", 1, ATTN_NORM); - break; - } - - // blast circles - MESSAGE_BEGIN(MSG_PAS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_BEAMCYLINDER); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z + 16); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z + 16 + HOUNDEYE_MAX_ATTACK_RADIUS / .2); // reach damage radius over .3 seconds - WRITE_SHORT(m_iSpriteTexture); - WRITE_BYTE(0); // startframe - WRITE_BYTE(0); // framerate - WRITE_BYTE(2); // life - WRITE_BYTE(16); // width - WRITE_BYTE(0); // noise - - WriteBeamColor(); - - WRITE_BYTE(255); //brightness - WRITE_BYTE(0); // speed - MESSAGE_END(); - - MESSAGE_BEGIN(MSG_PAS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_BEAMCYLINDER); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z + 16); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z + 16 + (HOUNDEYE_MAX_ATTACK_RADIUS / 2) / .2); // reach damage radius over .3 seconds - WRITE_SHORT(m_iSpriteTexture); - WRITE_BYTE(0); // startframe - WRITE_BYTE(0); // framerate - WRITE_BYTE(2); // life - WRITE_BYTE(16); // width - WRITE_BYTE(0); // noise - - WriteBeamColor(); - - WRITE_BYTE(255); //brightness - WRITE_BYTE(0); // speed - MESSAGE_END(); - - CBaseEntity *pEntity = NULL; - // iterate on all entities in the vicinity. - while ((pEntity = UTIL_FindEntityInSphere(pEntity, pev->origin, HOUNDEYE_MAX_ATTACK_RADIUS)) != NULL) - { - if (pEntity->pev->takedamage != DAMAGE_NO) - { - if (!FClassnameIs(pEntity->pev, "monster_houndeye")) - { // houndeyes don't hurt other houndeyes with their attack - - // houndeyes do FULL damage if the ent in question is visible. Half damage otherwise. - // This means that you must get out of the houndeye's attack range entirely to avoid damage. - // Calculate full damage first - - if (SquadCount() > 1) - { - // squad gets attack bonus. - flAdjustedDamage = gSkillData.houndeyeDmgBlast + gSkillData.houndeyeDmgBlast * (HOUNDEYE_SQUAD_BONUS * (SquadCount() - 1)); - } - else - { - // solo - flAdjustedDamage = gSkillData.houndeyeDmgBlast; - } - - flDist = (pEntity->Center() - pev->origin).Length(); - - flAdjustedDamage -= (flDist / HOUNDEYE_MAX_ATTACK_RADIUS) * flAdjustedDamage; - - if (!FVisible(pEntity)) - { - if (pEntity->IsPlayer()) - { - // if this entity is a client, and is not in full view, inflict half damage. We do this so that players still - // take the residual damage if they don't totally leave the houndeye's effective radius. We restrict it to clients - // so that monsters in other parts of the level don't take the damage and get pissed. - flAdjustedDamage *= 0.5; - } - else if (!FClassnameIs(pEntity->pev, "func_breakable") && !FClassnameIs(pEntity->pev, "func_pushable")) - { - // do not hurt nonclients through walls, but allow damage to be done to breakables - flAdjustedDamage = 0; - } - } - - //ALERT ( at_aiconsole, "Damage: %f\n", flAdjustedDamage ); - - if (flAdjustedDamage > 0) - { - pEntity->TakeDamage(pev, pev, flAdjustedDamage, DMG_SONIC | DMG_ALWAYSGIB); - } - } - } - } -} - -//========================================================= -// start task -//========================================================= -void CHoundeye ::StartTask(Task_t *pTask) -{ - m_iTaskStatus = TASKSTATUS_RUNNING; - - switch (pTask->iTask) - { - case TASK_HOUND_FALL_ASLEEP: - { - m_fAsleep = TRUE; // signal that hound is lying down (must stand again before doing anything else!) - m_iTaskStatus = TASKSTATUS_COMPLETE; - break; - } - case TASK_HOUND_WAKE_UP: - { - m_fAsleep = FALSE; // signal that hound is standing again - m_iTaskStatus = TASKSTATUS_COMPLETE; - break; - } - case TASK_HOUND_OPEN_EYE: - { - m_fDontBlink = FALSE; // turn blinking back on and that code will automatically open the eye - m_iTaskStatus = TASKSTATUS_COMPLETE; - break; - } - case TASK_HOUND_CLOSE_EYE: - { - pev->skin = 0; - m_fDontBlink = TRUE; // tell blink code to leave the eye alone. - break; - } - case TASK_HOUND_THREAT_DISPLAY: - { - m_IdealActivity = ACT_IDLE_ANGRY; - break; - } - case TASK_HOUND_HOP_BACK: - { - m_IdealActivity = ACT_LEAP; - break; - } - case TASK_RANGE_ATTACK1: - { - m_IdealActivity = ACT_RANGE_ATTACK1; - - /* - if ( InSquad() ) - { - // see if there is a battery to connect to. - CSquadMonster *pSquad = m_pSquadLeader; - - while ( pSquad ) - { - if ( pSquad->m_iMySlot == bits_SLOT_HOUND_BATTERY ) - { - // draw a beam. - MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); - WRITE_BYTE( TE_BEAMENTS ); - WRITE_SHORT( ENTINDEX( this->edict() ) ); - WRITE_SHORT( ENTINDEX( pSquad->edict() ) ); - WRITE_SHORT( m_iSpriteTexture ); - WRITE_BYTE( 0 ); // framestart - WRITE_BYTE( 0 ); // framerate - WRITE_BYTE( 10 ); // life - WRITE_BYTE( 40 ); // width - WRITE_BYTE( 10 ); // noise - WRITE_BYTE( 0 ); // r, g, b - WRITE_BYTE( 50 ); // r, g, b - WRITE_BYTE( 250); // r, g, b - WRITE_BYTE( 255 ); // brightness - WRITE_BYTE( 30 ); // speed - MESSAGE_END(); - break; - } - - pSquad = pSquad->m_pSquadNext; - } - } -*/ - - break; - } - case TASK_SPECIAL_ATTACK1: - { - m_IdealActivity = ACT_SPECIAL_ATTACK1; - break; - } - case TASK_GUARD: - { - m_IdealActivity = ACT_GUARD; - break; - } - default: - { - CSquadMonster ::StartTask(pTask); - break; - } - } -} - -//========================================================= -// RunTask -//========================================================= -void CHoundeye ::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_HOUND_THREAT_DISPLAY: - { - MakeIdealYaw(m_vecEnemyLKP); - ChangeYaw(pev->yaw_speed); - - if (m_fSequenceFinished) - { - TaskComplete(); - } - - break; - } - case TASK_HOUND_CLOSE_EYE: - { - if (pev->skin < HOUNDEYE_EYE_FRAMES - 1) - { - pev->skin++; - } - break; - } - case TASK_HOUND_HOP_BACK: - { - if (m_fSequenceFinished) - { - TaskComplete(); - } - break; - } - case TASK_SPECIAL_ATTACK1: - { - pev->skin = RANDOM_LONG(0, HOUNDEYE_EYE_FRAMES - 1); - - MakeIdealYaw(m_vecEnemyLKP); - ChangeYaw(pev->yaw_speed); - - float life; - life = ((255 - pev->frame) / (pev->framerate * m_flFrameRate)); - if (life < 0.1) - life = 0.1; - - MESSAGE_BEGIN(MSG_PAS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_IMPLOSION); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z + 16); - WRITE_BYTE(50 * life + 100); // radius - WRITE_BYTE(pev->frame / 25.0); // count - WRITE_BYTE(life * 10); // life - MESSAGE_END(); - - if (m_fSequenceFinished) - { - SonicAttack(); - TaskComplete(); - } - - break; - } - default: - { - CSquadMonster ::RunTask(pTask); - break; - } - } -} - -//========================================================= -// PrescheduleThink -//========================================================= -void CHoundeye::PrescheduleThink(void) -{ - // if the hound is mad and is running, make hunt noises. - if (m_MonsterState == MONSTERSTATE_COMBAT && m_Activity == ACT_RUN && RANDOM_FLOAT(0, 1) < 0.2) - { - WarnSound(); - } - - // at random, initiate a blink if not already blinking or sleeping - if (!m_fDontBlink) - { - if ((pev->skin == 0) && RANDOM_LONG(0, 0x7F) == 0) - { // start blinking! - pev->skin = HOUNDEYE_EYE_FRAMES - 1; - } - else if (pev->skin != 0) - { // already blinking - pev->skin--; - } - } - - // if you are the leader, average the origins of each pack member to get an approximate center. - if (IsLeader()) - { - CSquadMonster *pSquadMember; - int iSquadCount = 0; - - for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) - { - pSquadMember = MySquadMember(i); - - if (pSquadMember) - { - iSquadCount++; - m_vecPackCenter = m_vecPackCenter + pSquadMember->pev->origin; - } - } - - m_vecPackCenter = m_vecPackCenter / iSquadCount; - } -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= -Task_t tlHoundGuardPack[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_GUARD, (float)0}, -}; - -Schedule_t slHoundGuardPack[] = - { - {tlHoundGuardPack, - ARRAYSIZE(tlHoundGuardPack), - bits_COND_SEE_HATE | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_PROVOKED | - bits_COND_HEAR_SOUND, - - bits_SOUND_COMBAT | // sound flags - bits_SOUND_WORLD | - bits_SOUND_MEAT | - bits_SOUND_PLAYER, - "GuardPack"}, -}; - -// primary range attack -Task_t tlHoundYell1[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, - {TASK_SET_SCHEDULE, (float)SCHED_HOUND_AGITATED}, -}; - -Task_t tlHoundYell2[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, -}; - -Schedule_t slHoundRangeAttack[] = - { - {tlHoundYell1, - ARRAYSIZE(tlHoundYell1), - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "HoundRangeAttack1"}, - {tlHoundYell2, - ARRAYSIZE(tlHoundYell2), - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "HoundRangeAttack2"}, -}; - -// lie down and fall asleep -Task_t tlHoundSleep[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_WAIT_RANDOM, (float)5}, - {TASK_PLAY_SEQUENCE, (float)ACT_CROUCH}, - {TASK_SET_ACTIVITY, (float)ACT_CROUCHIDLE}, - {TASK_HOUND_FALL_ASLEEP, (float)0}, - {TASK_WAIT_RANDOM, (float)25}, - {TASK_HOUND_CLOSE_EYE, (float)0}, - //{ TASK_WAIT, (float)10 }, - //{ TASK_WAIT_RANDOM, (float)10 }, -}; - -Schedule_t slHoundSleep[] = - { - {tlHoundSleep, - ARRAYSIZE(tlHoundSleep), - bits_COND_HEAR_SOUND | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_NEW_ENEMY, - - bits_SOUND_COMBAT | - bits_SOUND_PLAYER | - bits_SOUND_WORLD, - "Hound Sleep"}, -}; - -// wake and stand up lazily -Task_t tlHoundWakeLazy[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_HOUND_OPEN_EYE, (float)0}, - {TASK_WAIT_RANDOM, (float)2.5}, - {TASK_PLAY_SEQUENCE, (float)ACT_STAND}, - {TASK_HOUND_WAKE_UP, (float)0}, -}; - -Schedule_t slHoundWakeLazy[] = - { - {tlHoundWakeLazy, - ARRAYSIZE(tlHoundWakeLazy), - 0, - 0, - "WakeLazy"}, -}; - -// wake and stand up with great urgency! -Task_t tlHoundWakeUrgent[] = - { - {TASK_HOUND_OPEN_EYE, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_HOP}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_HOUND_WAKE_UP, (float)0}, -}; - -Schedule_t slHoundWakeUrgent[] = - { - {tlHoundWakeUrgent, - ARRAYSIZE(tlHoundWakeUrgent), - 0, - 0, - "WakeUrgent"}, -}; - -Task_t tlHoundSpecialAttack1[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_SPECIAL_ATTACK1, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_IDLE_ANGRY}, -}; - -Schedule_t slHoundSpecialAttack1[] = - { - {tlHoundSpecialAttack1, - ARRAYSIZE(tlHoundSpecialAttack1), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_ENEMY_OCCLUDED, - - 0, - "Hound Special Attack1"}, -}; - -Task_t tlHoundAgitated[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_HOUND_THREAT_DISPLAY, 0}, -}; - -Schedule_t slHoundAgitated[] = - { - {tlHoundAgitated, - ARRAYSIZE(tlHoundAgitated), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "Hound Agitated"}, -}; - -Task_t tlHoundHopRetreat[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_HOUND_HOP_BACK, 0}, - {TASK_SET_SCHEDULE, (float)SCHED_TAKE_COVER_FROM_ENEMY}, -}; - -Schedule_t slHoundHopRetreat[] = - { - {tlHoundHopRetreat, - ARRAYSIZE(tlHoundHopRetreat), - 0, - 0, - "Hound Hop Retreat"}, -}; - -// hound fails in combat with client in the PVS -Task_t tlHoundCombatFailPVS[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_HOUND_THREAT_DISPLAY, 0}, - {TASK_WAIT_FACE_ENEMY, (float)1}, -}; - -Schedule_t slHoundCombatFailPVS[] = - { - {tlHoundCombatFailPVS, - ARRAYSIZE(tlHoundCombatFailPVS), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "HoundCombatFailPVS"}, -}; - -// hound fails in combat with no client in the PVS. Don't keep peeping! -Task_t tlHoundCombatFailNoPVS[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_HOUND_THREAT_DISPLAY, 0}, - {TASK_WAIT_FACE_ENEMY, (float)2}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_WAIT_PVS, 0}, -}; - -Schedule_t slHoundCombatFailNoPVS[] = - { - {tlHoundCombatFailNoPVS, - ARRAYSIZE(tlHoundCombatFailNoPVS), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "HoundCombatFailNoPVS"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CHoundeye){ - slHoundGuardPack, - slHoundRangeAttack, - &slHoundRangeAttack[1], - slHoundSleep, - slHoundWakeLazy, - slHoundWakeUrgent, - slHoundSpecialAttack1, - slHoundAgitated, - slHoundHopRetreat, - slHoundCombatFailPVS, - slHoundCombatFailNoPVS, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CHoundeye, CSquadMonster); - -//========================================================= -// GetScheduleOfType -//========================================================= -Schedule_t *CHoundeye ::GetScheduleOfType(int Type) -{ - if (m_fAsleep) - { - // if the hound is sleeping, must wake and stand! - if (HasConditions(bits_COND_HEAR_SOUND)) - { - CSound *pWakeSound; - - pWakeSound = PBestSound(); - ASSERT(pWakeSound != NULL); - if (pWakeSound) - { - MakeIdealYaw(pWakeSound->m_vecOrigin); - - if (FLSoundVolume(pWakeSound) >= HOUNDEYE_SOUND_STARTLE_VOLUME) - { - // awakened by a loud sound - return &slHoundWakeUrgent[0]; - } - } - // sound was not loud enough to scare the bejesus out of houndeye - return &slHoundWakeLazy[0]; - } - else if (HasConditions(bits_COND_NEW_ENEMY)) - { - // get up fast, to fight. - return &slHoundWakeUrgent[0]; - } - - else - { - // hound is waking up on its own - return &slHoundWakeLazy[0]; - } - } - switch (Type) - { - case SCHED_IDLE_STAND: - { - // we may want to sleep instead of stand! - if (InSquad() && !IsLeader() && !m_fAsleep && RANDOM_LONG(0, 29) < 1) - { - return &slHoundSleep[0]; - } - else - { - return CSquadMonster ::GetScheduleOfType(Type); - } - } - case SCHED_RANGE_ATTACK1: - { - return &slHoundRangeAttack[0]; - /* - if ( InSquad() ) - { - return &slHoundRangeAttack[ RANDOM_LONG( 0, 1 ) ]; - } - - return &slHoundRangeAttack[ 1 ]; -*/ - } - case SCHED_SPECIAL_ATTACK1: - { - return &slHoundSpecialAttack1[0]; - } - case SCHED_GUARD: - { - return &slHoundGuardPack[0]; - } - case SCHED_HOUND_AGITATED: - { - return &slHoundAgitated[0]; - } - case SCHED_HOUND_HOP_RETREAT: - { - return &slHoundHopRetreat[0]; - } - case SCHED_FAIL: - { - if (m_MonsterState == MONSTERSTATE_COMBAT) - { - if (!FNullEnt(FIND_CLIENT_IN_PVS(edict()))) - { - // client in PVS - return &slHoundCombatFailPVS[0]; - } - else - { - // client has taken off! - return &slHoundCombatFailNoPVS[0]; - } - } - else - { - return CSquadMonster ::GetScheduleOfType(Type); - } - } - default: - { - return CSquadMonster ::GetScheduleOfType(Type); - } - } -} - -//========================================================= -// GetSchedule -//========================================================= -Schedule_t *CHoundeye ::GetSchedule(void) -{ - switch (m_MonsterState) - { - case MONSTERSTATE_COMBAT: - { - // dead enemy - if (HasConditions(bits_COND_ENEMY_DEAD)) - { - // call base class, all code to handle dead enemies is centralized there. - return CBaseMonster ::GetSchedule(); - } - - if (HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE)) - { - if (RANDOM_FLOAT(0, 1) <= 0.4) - { - TraceResult tr; - UTIL_MakeVectors(pev->angles); - UTIL_TraceHull(pev->origin, pev->origin + gpGlobals->v_forward * -128, dont_ignore_monsters, head_hull, ENT(pev), &tr); - - if (tr.flFraction == 1.0) - { - // it's clear behind, so the hound will jump - return GetScheduleOfType(SCHED_HOUND_HOP_RETREAT); - } - } - - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_ENEMY); - } - - if (HasConditions(bits_COND_CAN_RANGE_ATTACK1)) - { - if (OccupySlot(bits_SLOTS_HOUND_ATTACK)) - { - return GetScheduleOfType(SCHED_RANGE_ATTACK1); - } - - return GetScheduleOfType(SCHED_HOUND_AGITATED); - } - break; - } - } - - return CSquadMonster ::GetSchedule(); -} diff --git a/dlls/Half-life/ichthyosaur.cpp b/dlls/Half-life/ichthyosaur.cpp deleted file mode 100644 index 01d3c8b2..00000000 --- a/dlls/Half-life/ichthyosaur.cpp +++ /dev/null @@ -1,1085 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -//========================================================= -// icthyosaur - evin, satan fish monster -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" -#include "flyingmonster.h" -#include "nodes.h" -#include "soundent.h" -#include "animation.h" -#include "effects.h" -#include "weapons.h" - -#define SEARCH_RETRY 16 - -#define ICHTHYOSAUR_SPEED 150 - -extern CGraph WorldGraph; - -#define EYE_MAD 0 -#define EYE_BASE 1 -#define EYE_CLOSED 2 -#define EYE_BACK 3 -#define EYE_LOOK 4 - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= - -// UNDONE: Save/restore here -class CIchthyosaur : public CFlyingMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - CUSTOM_SCHEDULES; - - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - Schedule_t *GetSchedule(void); - Schedule_t *GetScheduleOfType(int Type); - - void Killed(entvars_t *pevAttacker, int iGib); - void BecomeDead(void); - - void EXPORT CombatUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void EXPORT BiteTouch(CBaseEntity *pOther); - - void StartTask(Task_t *pTask); - void RunTask(Task_t *pTask); - - BOOL CheckMeleeAttack1(float flDot, float flDist); - BOOL CheckRangeAttack1(float flDot, float flDist); - - float ChangeYaw(int speed); - Activity GetStoppedActivity(void); - - void Move(float flInterval); - void MoveExecute(CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval); - void MonsterThink(void); - void Stop(void); - void Swim(void); - Vector DoProbe(const Vector &Probe); - - float VectorToPitch(const Vector &vec); - float FlPitchDiff(void); - float ChangePitch(int speed); - - Vector m_SaveVelocity; - float m_idealDist; - - float m_flBlink; - - float m_flEnemyTouched; - BOOL m_bOnAttack; - - float m_flMaxSpeed; - float m_flMinSpeed; - float m_flMaxDist; - - CBeam *m_pBeam; - - float m_flNextAlert; - - static const char *pIdleSounds[]; - static const char *pAlertSounds[]; - static const char *pAttackSounds[]; - static const char *pBiteSounds[]; - static const char *pDieSounds[]; - static const char *pPainSounds[]; - - void IdleSound(void); - void AlertSound(void); - void AttackSound(void); - void BiteSound(void); - void DeathSound(void); - void PainSound(void); -}; - -LINK_ENTITY_TO_CLASS(monster_ichthyosaur, CIchthyosaur); - -TYPEDESCRIPTION CIchthyosaur::m_SaveData[] = - { - DEFINE_FIELD(CIchthyosaur, m_SaveVelocity, FIELD_VECTOR), - DEFINE_FIELD(CIchthyosaur, m_idealDist, FIELD_FLOAT), - DEFINE_FIELD(CIchthyosaur, m_flBlink, FIELD_FLOAT), - DEFINE_FIELD(CIchthyosaur, m_flEnemyTouched, FIELD_FLOAT), - DEFINE_FIELD(CIchthyosaur, m_bOnAttack, FIELD_BOOLEAN), - DEFINE_FIELD(CIchthyosaur, m_flMaxSpeed, FIELD_FLOAT), - DEFINE_FIELD(CIchthyosaur, m_flMinSpeed, FIELD_FLOAT), - DEFINE_FIELD(CIchthyosaur, m_flMaxDist, FIELD_FLOAT), - DEFINE_FIELD(CIchthyosaur, m_flNextAlert, FIELD_TIME), -}; - -IMPLEMENT_SAVERESTORE(CIchthyosaur, CFlyingMonster); - -const char *CIchthyosaur::pIdleSounds[] = - { - "ichy/ichy_idle1.wav", - "ichy/ichy_idle2.wav", - "ichy/ichy_idle3.wav", - "ichy/ichy_idle4.wav", -}; - -const char *CIchthyosaur::pAlertSounds[] = - { - "ichy/ichy_alert2.wav", - "ichy/ichy_alert3.wav", -}; - -const char *CIchthyosaur::pAttackSounds[] = - { - "ichy/ichy_attack1.wav", - "ichy/ichy_attack2.wav", -}; - -const char *CIchthyosaur::pBiteSounds[] = - { - "ichy/ichy_bite1.wav", - "ichy/ichy_bite2.wav", -}; - -const char *CIchthyosaur::pPainSounds[] = - { - "ichy/ichy_pain2.wav", - "ichy/ichy_pain3.wav", - "ichy/ichy_pain5.wav", -}; - -const char *CIchthyosaur::pDieSounds[] = - { - "ichy/ichy_die2.wav", - "ichy/ichy_die4.wav", -}; - -#define EMIT_ICKY_SOUND(chan, array) \ - EMIT_SOUND_DYN(ENT(pev), chan, array[RANDOM_LONG(0, ARRAYSIZE(array) - 1)], 1.0, 0.6, 0, RANDOM_LONG(95, 105)); - -void CIchthyosaur ::IdleSound(void) -{ - EMIT_ICKY_SOUND(CHAN_VOICE, pIdleSounds); -} - -void CIchthyosaur ::AlertSound(void) -{ - EMIT_ICKY_SOUND(CHAN_VOICE, pAlertSounds); -} - -void CIchthyosaur ::AttackSound(void) -{ - EMIT_ICKY_SOUND(CHAN_VOICE, pAttackSounds); -} - -void CIchthyosaur ::BiteSound(void) -{ - EMIT_ICKY_SOUND(CHAN_WEAPON, pBiteSounds); -} - -void CIchthyosaur ::DeathSound(void) -{ - EMIT_ICKY_SOUND(CHAN_VOICE, pDieSounds); -} - -void CIchthyosaur ::PainSound(void) -{ - EMIT_ICKY_SOUND(CHAN_VOICE, pPainSounds); -} - -//========================================================= -// monster-specific tasks and states -//========================================================= -enum -{ - TASK_ICHTHYOSAUR_CIRCLE_ENEMY = LAST_COMMON_TASK + 1, - TASK_ICHTHYOSAUR_SWIM, - TASK_ICHTHYOSAUR_FLOAT, -}; - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - -static Task_t tlSwimAround[] = - { - {TASK_SET_ACTIVITY, (float)ACT_WALK}, - {TASK_ICHTHYOSAUR_SWIM, 0.0}, -}; - -static Schedule_t slSwimAround[] = - { - {tlSwimAround, - ARRAYSIZE(tlSwimAround), - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_SEE_ENEMY | - bits_COND_NEW_ENEMY | - bits_COND_HEAR_SOUND, - bits_SOUND_PLAYER | - bits_SOUND_COMBAT, - "SwimAround"}, -}; - -static Task_t tlSwimAgitated[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_RUN}, - {TASK_WAIT, (float)2.0}, -}; - -static Schedule_t slSwimAgitated[] = - { - {tlSwimAgitated, - ARRAYSIZE(tlSwimAgitated), - 0, - 0, - "SwimAgitated"}, -}; - -static Task_t tlCircleEnemy[] = - { - {TASK_SET_ACTIVITY, (float)ACT_WALK}, - {TASK_ICHTHYOSAUR_CIRCLE_ENEMY, 0.0}, -}; - -static Schedule_t slCircleEnemy[] = - { - {tlCircleEnemy, - ARRAYSIZE(tlCircleEnemy), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_CAN_MELEE_ATTACK1 | - bits_COND_CAN_RANGE_ATTACK1, - 0, - "CircleEnemy"}, -}; - -Task_t tlTwitchDie[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SOUND_DIE, (float)0}, - {TASK_DIE, (float)0}, - {TASK_ICHTHYOSAUR_FLOAT, (float)0}, -}; - -Schedule_t slTwitchDie[] = - { - {tlTwitchDie, - ARRAYSIZE(tlTwitchDie), - 0, - 0, - "Die"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CIchthyosaur){ - slSwimAround, - slSwimAgitated, - slCircleEnemy, - slTwitchDie, -}; -IMPLEMENT_CUSTOM_SCHEDULES(CIchthyosaur, CFlyingMonster); - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CIchthyosaur ::Classify(void) -{ - return CLASS_ALIEN_MONSTER; -} - -//========================================================= -// CheckMeleeAttack1 -//========================================================= -BOOL CIchthyosaur ::CheckMeleeAttack1(float flDot, float flDist) -{ - if (flDot >= 0.7 && m_flEnemyTouched > gpGlobals->time - 0.2) - { - return TRUE; - } - return FALSE; -} - -void CIchthyosaur::BiteTouch(CBaseEntity *pOther) -{ - // bite if we hit who we want to eat - if (pOther == m_hEnemy) - { - m_flEnemyTouched = gpGlobals->time; - m_bOnAttack = TRUE; - } -} - -void CIchthyosaur::CombatUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!ShouldToggle(useType, m_bOnAttack)) - return; - - if (m_bOnAttack) - { - m_bOnAttack = 0; - } - else - { - m_bOnAttack = 1; - } -} - -//========================================================= -// CheckRangeAttack1 - swim in for a chomp -// -//========================================================= -BOOL CIchthyosaur ::CheckRangeAttack1(float flDot, float flDist) -{ - if (flDot > -0.7 && (m_bOnAttack || (flDist <= 192 && m_idealDist <= 192))) - { - return TRUE; - } - - return FALSE; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CIchthyosaur ::SetYawSpeed(void) -{ - pev->yaw_speed = 100; -} - -//========================================================= -// Killed - overrides CFlyingMonster. -// -void CIchthyosaur ::Killed(entvars_t *pevAttacker, int iGib) -{ - CBaseMonster::Killed(pevAttacker, iGib); - pev->velocity = Vector(0, 0, 0); -} - -void CIchthyosaur::BecomeDead(void) -{ - pev->takedamage = DAMAGE_YES; // don't let autoaim aim at corpses. - - // give the corpse half of the monster's original maximum health. - pev->health = pev->max_health / 2; - pev->max_health = 5; // max_health now becomes a counter for how many blood decals the corpse can place. -} - -#define ICHTHYOSAUR_AE_SHAKE_RIGHT 1 -#define ICHTHYOSAUR_AE_SHAKE_LEFT 2 - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CIchthyosaur ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - int bDidAttack = FALSE; - switch (pEvent->event) - { - case ICHTHYOSAUR_AE_SHAKE_RIGHT: - case ICHTHYOSAUR_AE_SHAKE_LEFT: - { - if (m_hEnemy != NULL && FVisible(m_hEnemy)) - { - CBaseEntity *pHurt = m_hEnemy; - - if (m_flEnemyTouched < gpGlobals->time - 0.2 && (m_hEnemy->BodyTarget(pev->origin) - pev->origin).Length() > (32 + 16 + 32)) - break; - - Vector vecShootDir = ShootAtEnemy(pev->origin); - UTIL_MakeAimVectors(pev->angles); - - if (DotProduct(vecShootDir, gpGlobals->v_forward) > 0.707) - { - m_bOnAttack = TRUE; - pHurt->pev->punchangle.z = -18; - pHurt->pev->punchangle.x = 5; - pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_right * 300; - if (pHurt->IsPlayer()) - { - pHurt->pev->angles.x += RANDOM_FLOAT(-35, 35); - pHurt->pev->angles.y += RANDOM_FLOAT(-90, 90); - pHurt->pev->angles.z = 0; - pHurt->pev->fixangle = TRUE; - } - pHurt->TakeDamage(pev, pev, gSkillData.ichthyosaurDmgShake, DMG_SLASH); - } - } - BiteSound(); - - bDidAttack = TRUE; - } - break; - default: - CFlyingMonster::HandleAnimEvent(pEvent); - break; - } - - if (bDidAttack) - { - Vector vecSrc = pev->origin + gpGlobals->v_forward * 32; - UTIL_Bubbles(vecSrc - Vector(8, 8, 8), vecSrc + Vector(8, 8, 8), 16); - } -} - -//========================================================= -// Spawn -//========================================================= -void CIchthyosaur ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/icky.mdl"); - UTIL_SetSize(pev, Vector(-32, -32, -32), Vector(32, 32, 32)); - - pev->solid = SOLID_BBOX; - pev->movetype = MOVETYPE_FLY; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->health = gSkillData.ichthyosaurHealth; - pev->view_ofs = Vector(0, 0, 16); - m_flFieldOfView = VIEW_FIELD_WIDE; - m_MonsterState = MONSTERSTATE_NONE; - SetBits(pev->flags, FL_SWIM); - SetFlyingSpeed(ICHTHYOSAUR_SPEED); - SetFlyingMomentum(2.5); // Set momentum constant - - m_afCapability = bits_CAP_RANGE_ATTACK1 | bits_CAP_SWIM; - - MonsterInit(); - - SetTouch(BiteTouch); - SetUse(CombatUse); - - m_idealDist = 384; - m_flMinSpeed = 80; - m_flMaxSpeed = 300; - m_flMaxDist = 384; - - Vector Forward; - UTIL_MakeVectorsPrivate(pev->angles, Forward, 0, 0); - pev->velocity = m_flightSpeed * Forward.Normalize(); - m_SaveVelocity = pev->velocity; -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CIchthyosaur ::Precache() -{ - PRECACHE_MODEL("models/icky.mdl"); - - PRECACHE_SOUND_ARRAY(pIdleSounds); - PRECACHE_SOUND_ARRAY(pAlertSounds); - PRECACHE_SOUND_ARRAY(pAttackSounds); - PRECACHE_SOUND_ARRAY(pBiteSounds); - PRECACHE_SOUND_ARRAY(pDieSounds); - PRECACHE_SOUND_ARRAY(pPainSounds); -} - -//========================================================= -// GetSchedule -//========================================================= -Schedule_t *CIchthyosaur::GetSchedule() -{ - // ALERT( at_console, "GetSchedule( )\n" ); - switch (m_MonsterState) - { - case MONSTERSTATE_IDLE: - m_flightSpeed = 80; - return GetScheduleOfType(SCHED_IDLE_WALK); - - case MONSTERSTATE_ALERT: - m_flightSpeed = 150; - return GetScheduleOfType(SCHED_IDLE_WALK); - - case MONSTERSTATE_COMBAT: - m_flMaxSpeed = 400; - // eat them - if (HasConditions(bits_COND_CAN_MELEE_ATTACK1)) - { - return GetScheduleOfType(SCHED_MELEE_ATTACK1); - } - // chase them down and eat them - if (HasConditions(bits_COND_CAN_RANGE_ATTACK1)) - { - return GetScheduleOfType(SCHED_CHASE_ENEMY); - } - if (HasConditions(bits_COND_HEAVY_DAMAGE)) - { - m_bOnAttack = TRUE; - } - if (pev->health < pev->max_health - 20) - { - m_bOnAttack = TRUE; - } - - return GetScheduleOfType(SCHED_STANDOFF); - } - - return CFlyingMonster ::GetSchedule(); -} - -//========================================================= -//========================================================= -Schedule_t *CIchthyosaur ::GetScheduleOfType(int Type) -{ - // ALERT( at_console, "GetScheduleOfType( %d ) %d\n", Type, m_bOnAttack ); - switch (Type) - { - case SCHED_IDLE_WALK: - return slSwimAround; - case SCHED_STANDOFF: - return slCircleEnemy; - case SCHED_FAIL: - return slSwimAgitated; - case SCHED_DIE: - return slTwitchDie; - case SCHED_CHASE_ENEMY: - AttackSound(); - } - - return CBaseMonster ::GetScheduleOfType(Type); -} - -//========================================================= -// Start task - selects the correct activity and performs -// any necessary calculations to start the next task on the -// schedule. -//========================================================= -void CIchthyosaur::StartTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_ICHTHYOSAUR_CIRCLE_ENEMY: - break; - case TASK_ICHTHYOSAUR_SWIM: - break; - case TASK_SMALL_FLINCH: - if (m_idealDist > 128) - { - m_flMaxDist = 512; - m_idealDist = 512; - } - else - { - m_bOnAttack = TRUE; - } - CFlyingMonster::StartTask(pTask); - break; - - case TASK_ICHTHYOSAUR_FLOAT: - pev->skin = EYE_BASE; - SetSequenceByName("bellyup"); - break; - - default: - CFlyingMonster::StartTask(pTask); - break; - } -} - -void CIchthyosaur ::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_ICHTHYOSAUR_CIRCLE_ENEMY: - if (m_hEnemy == NULL) - { - TaskComplete(); - } - else if (FVisible(m_hEnemy)) - { - Vector vecFrom = m_hEnemy->EyePosition(); - - Vector vecDelta = (pev->origin - vecFrom).Normalize(); - Vector vecSwim = CrossProduct(vecDelta, Vector(0, 0, 1)).Normalize(); - - if (DotProduct(vecSwim, m_SaveVelocity) < 0) - vecSwim = vecSwim * -1.0; - - Vector vecPos = vecFrom + vecDelta * m_idealDist + vecSwim * 32; - - // ALERT( at_console, "vecPos %.0f %.0f %.0f\n", vecPos.x, vecPos.y, vecPos.z ); - - TraceResult tr; - - UTIL_TraceHull(vecFrom, vecPos, ignore_monsters, large_hull, m_hEnemy->edict(), &tr); - - if (tr.flFraction > 0.5) - vecPos = tr.vecEndPos; - - m_SaveVelocity = m_SaveVelocity * 0.8 + 0.2 * (vecPos - pev->origin).Normalize() * m_flightSpeed; - - // ALERT( at_console, "m_SaveVelocity %.2f %.2f %.2f\n", m_SaveVelocity.x, m_SaveVelocity.y, m_SaveVelocity.z ); - - if (HasConditions(bits_COND_ENEMY_FACING_ME) && m_hEnemy->FVisible(this)) - { - m_flNextAlert -= 0.1; - - if (m_idealDist < m_flMaxDist) - { - m_idealDist += 4; - } - if (m_flightSpeed > m_flMinSpeed) - { - m_flightSpeed -= 2; - } - else if (m_flightSpeed < m_flMinSpeed) - { - m_flightSpeed += 2; - } - if (m_flMinSpeed < m_flMaxSpeed) - { - m_flMinSpeed += 0.5; - } - } - else - { - m_flNextAlert += 0.1; - - if (m_idealDist > 128) - { - m_idealDist -= 4; - } - if (m_flightSpeed < m_flMaxSpeed) - { - m_flightSpeed += 4; - } - } - // ALERT( at_console, "%.0f\n", m_idealDist ); - } - else - { - m_flNextAlert = gpGlobals->time + 0.2; - } - - if (m_flNextAlert < gpGlobals->time) - { - // ALERT( at_console, "AlertSound()\n"); - AlertSound(); - m_flNextAlert = gpGlobals->time + RANDOM_FLOAT(3, 5); - } - - break; - case TASK_ICHTHYOSAUR_SWIM: - if (m_fSequenceFinished) - { - TaskComplete(); - } - break; - case TASK_DIE: - if (m_fSequenceFinished) - { - pev->deadflag = DEAD_DEAD; - - TaskComplete(); - } - break; - - case TASK_ICHTHYOSAUR_FLOAT: - pev->angles.x = UTIL_ApproachAngle(0, pev->angles.x, 20); - pev->velocity = pev->velocity * 0.8; - if (pev->waterlevel > 1 && pev->velocity.z < 64) - { - pev->velocity.z += 8; - } - else - { - pev->velocity.z -= 8; - } - // ALERT( at_console, "%f\n", pev->velocity.z ); - break; - - default: - CFlyingMonster ::RunTask(pTask); - break; - } -} - -float CIchthyosaur::VectorToPitch(const Vector &vec) -{ - float pitch; - if (vec.z == 0 && vec.x == 0) - pitch = 0; - else - { - pitch = (int)(atan2(vec.z, sqrt(vec.x * vec.x + vec.y * vec.y)) * 180 / M_PI); - if (pitch < 0) - pitch += 360; - } - return pitch; -} - -//========================================================= -void CIchthyosaur::Move(float flInterval) -{ - CFlyingMonster::Move(flInterval); -} - -float CIchthyosaur::FlPitchDiff(void) -{ - float flPitchDiff; - float flCurrentPitch; - - flCurrentPitch = UTIL_AngleMod(pev->angles.z); - - if (flCurrentPitch == pev->idealpitch) - { - return 0; - } - - flPitchDiff = pev->idealpitch - flCurrentPitch; - - if (pev->idealpitch > flCurrentPitch) - { - if (flPitchDiff >= 180) - flPitchDiff = flPitchDiff - 360; - } - else - { - if (flPitchDiff <= -180) - flPitchDiff = flPitchDiff + 360; - } - return flPitchDiff; -} - -float CIchthyosaur ::ChangePitch(int speed) -{ - if (pev->movetype == MOVETYPE_FLY) - { - float diff = FlPitchDiff(); - float target = 0; - if (m_IdealActivity != GetStoppedActivity()) - { - if (diff < -20) - target = 45; - else if (diff > 20) - target = -45; - } - pev->angles.x = UTIL_Approach(target, pev->angles.x, 220.0 * 0.1); - } - return 0; -} - -float CIchthyosaur::ChangeYaw(int speed) -{ - if (pev->movetype == MOVETYPE_FLY) - { - float diff = FlYawDiff(); - float target = 0; - - if (m_IdealActivity != GetStoppedActivity()) - { - if (diff < -20) - target = 20; - else if (diff > 20) - target = -20; - } - pev->angles.z = UTIL_Approach(target, pev->angles.z, 220.0 * 0.1); - } - return CFlyingMonster::ChangeYaw(speed); -} - -Activity CIchthyosaur::GetStoppedActivity(void) -{ - if (pev->movetype != MOVETYPE_FLY) // UNDONE: Ground idle here, IDLE may be something else - return ACT_IDLE; - return ACT_WALK; -} - -void CIchthyosaur::MoveExecute(CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval) -{ - m_SaveVelocity = vecDir * m_flightSpeed; -} - -void CIchthyosaur::MonsterThink(void) -{ - CFlyingMonster::MonsterThink(); - - if (pev->deadflag == DEAD_NO) - { - if (m_MonsterState != MONSTERSTATE_SCRIPT) - { - Swim(); - - // blink the eye - if (m_flBlink < gpGlobals->time) - { - pev->skin = EYE_CLOSED; - if (m_flBlink + 0.2 < gpGlobals->time) - { - m_flBlink = gpGlobals->time + RANDOM_FLOAT(3, 4); - if (m_bOnAttack) - pev->skin = EYE_MAD; - else - pev->skin = EYE_BASE; - } - } - } - } -} - -void CIchthyosaur ::Stop(void) -{ - if (!m_bOnAttack) - m_flightSpeed = 80.0; -} - -void CIchthyosaur::Swim() -{ - int retValue = 0; - - Vector start = pev->origin; - - Vector Angles; - Vector Forward, Right, Up; - - if (FBitSet(pev->flags, FL_ONGROUND)) - { - pev->angles.x = 0; - pev->angles.y += RANDOM_FLOAT(-45, 45); - ClearBits(pev->flags, FL_ONGROUND); - - Angles = Vector(-pev->angles.x, pev->angles.y, pev->angles.z); - UTIL_MakeVectorsPrivate(Angles, Forward, Right, Up); - - pev->velocity = Forward * 200 + Up * 200; - - return; - } - - if (m_bOnAttack && m_flightSpeed < m_flMaxSpeed) - { - m_flightSpeed += 40; - } - if (m_flightSpeed < 180) - { - if (m_IdealActivity == ACT_RUN) - SetActivity(ACT_WALK); - if (m_IdealActivity == ACT_WALK) - pev->framerate = m_flightSpeed / 150.0; - // ALERT( at_console, "walk %.2f\n", pev->framerate ); - } - else - { - if (m_IdealActivity == ACT_WALK) - SetActivity(ACT_RUN); - if (m_IdealActivity == ACT_RUN) - pev->framerate = m_flightSpeed / 150.0; - // ALERT( at_console, "run %.2f\n", pev->framerate ); - } - -/* - if (!m_pBeam) - { - m_pBeam = CBeam::BeamCreate( "sprites/laserbeam.spr", 80 ); - m_pBeam->PointEntInit( pev->origin + m_SaveVelocity, entindex( ) ); - m_pBeam->SetEndAttachment( 1 ); - m_pBeam->SetColor( 255, 180, 96 ); - m_pBeam->SetBrightness( 192 ); - } -*/ -#define PROBE_LENGTH 150 - Angles = UTIL_VecToAngles(m_SaveVelocity); - Angles.x = -Angles.x; - UTIL_MakeVectorsPrivate(Angles, Forward, Right, Up); - - Vector f, u, l, r, d; - f = DoProbe(start + PROBE_LENGTH * Forward); - r = DoProbe(start + PROBE_LENGTH / 3 * Forward + Right); - l = DoProbe(start + PROBE_LENGTH / 3 * Forward - Right); - u = DoProbe(start + PROBE_LENGTH / 3 * Forward + Up); - d = DoProbe(start + PROBE_LENGTH / 3 * Forward - Up); - - Vector SteeringVector = f + r + l + u + d; - m_SaveVelocity = (m_SaveVelocity + SteeringVector / 2).Normalize(); - - Angles = Vector(-pev->angles.x, pev->angles.y, pev->angles.z); - UTIL_MakeVectorsPrivate(Angles, Forward, Right, Up); - // ALERT( at_console, "%f : %f\n", Angles.x, Forward.z ); - - float flDot = DotProduct(Forward, m_SaveVelocity); - if (flDot > 0.5) - pev->velocity = m_SaveVelocity = m_SaveVelocity * m_flightSpeed; - else if (flDot > 0) - pev->velocity = m_SaveVelocity = m_SaveVelocity * m_flightSpeed * (flDot + 0.5); - else - pev->velocity = m_SaveVelocity = m_SaveVelocity * 80; - - // ALERT( at_console, "%.0f %.0f\n", m_flightSpeed, pev->velocity.Length() ); - - // ALERT( at_console, "Steer %f %f %f\n", SteeringVector.x, SteeringVector.y, SteeringVector.z ); - - /* - m_pBeam->SetStartPos( pev->origin + pev->velocity ); - m_pBeam->RelinkBeam( ); -*/ - - // ALERT( at_console, "speed %f\n", m_flightSpeed ); - - Angles = UTIL_VecToAngles(m_SaveVelocity); - - // Smooth Pitch - // - if (Angles.x > 180) - Angles.x = Angles.x - 360; - pev->angles.x = UTIL_Approach(Angles.x, pev->angles.x, 50 * 0.1); - if (pev->angles.x < -80) - pev->angles.x = -80; - if (pev->angles.x > 80) - pev->angles.x = 80; - - // Smooth Yaw and generate Roll - // - float turn = 360; - // ALERT( at_console, "Y %.0f %.0f\n", Angles.y, pev->angles.y ); - - if (fabs(Angles.y - pev->angles.y) < fabs(turn)) - { - turn = Angles.y - pev->angles.y; - } - if (fabs(Angles.y - pev->angles.y + 360) < fabs(turn)) - { - turn = Angles.y - pev->angles.y + 360; - } - if (fabs(Angles.y - pev->angles.y - 360) < fabs(turn)) - { - turn = Angles.y - pev->angles.y - 360; - } - - float speed = m_flightSpeed * 0.1; - - // ALERT( at_console, "speed %.0f %f\n", turn, speed ); - if (fabs(turn) > speed) - { - if (turn < 0.0) - { - turn = -speed; - } - else - { - turn = speed; - } - } - pev->angles.y += turn; - pev->angles.z -= turn; - pev->angles.y = fmod((pev->angles.y + 360.0), 360.0); - - static float yaw_adj; - - yaw_adj = yaw_adj * 0.8 + turn; - - // ALERT( at_console, "yaw %f : %f\n", turn, yaw_adj ); - - SetBoneController(0, -yaw_adj / 4.0); - - // Roll Smoothing - // - turn = 360; - if (fabs(Angles.z - pev->angles.z) < fabs(turn)) - { - turn = Angles.z - pev->angles.z; - } - if (fabs(Angles.z - pev->angles.z + 360) < fabs(turn)) - { - turn = Angles.z - pev->angles.z + 360; - } - if (fabs(Angles.z - pev->angles.z - 360) < fabs(turn)) - { - turn = Angles.z - pev->angles.z - 360; - } - speed = m_flightSpeed / 2 * 0.1; - if (fabs(turn) < speed) - { - pev->angles.z += turn; - } - else - { - if (turn < 0.0) - { - pev->angles.z -= speed; - } - else - { - pev->angles.z += speed; - } - } - if (pev->angles.z < -20) - pev->angles.z = -20; - if (pev->angles.z > 20) - pev->angles.z = 20; - - UTIL_MakeVectorsPrivate(Vector(-Angles.x, Angles.y, Angles.z), Forward, Right, Up); - - // UTIL_MoveToOrigin ( ENT(pev), pev->origin + Forward * speed, speed, MOVE_STRAFE ); -} - -Vector CIchthyosaur::DoProbe(const Vector &Probe) -{ - Vector WallNormal = Vector(0, 0, -1); // WATER normal is Straight Down for fish. - float frac; - BOOL bBumpedSomething = ProbeZ(pev->origin, Probe, &frac); - - TraceResult tr; - TRACE_MONSTER_HULL(edict(), pev->origin, Probe, dont_ignore_monsters, edict(), &tr); - if (tr.fAllSolid || tr.flFraction < 0.99) - { - if (tr.flFraction < 0.0) - tr.flFraction = 0.0; - if (tr.flFraction > 1.0) - tr.flFraction = 1.0; - if (tr.flFraction < frac) - { - frac = tr.flFraction; - bBumpedSomething = TRUE; - WallNormal = tr.vecPlaneNormal; - } - } - - if (bBumpedSomething && (m_hEnemy == NULL || tr.pHit != m_hEnemy->edict())) - { - Vector ProbeDir = Probe - pev->origin; - - Vector NormalToProbeAndWallNormal = CrossProduct(ProbeDir, WallNormal); - Vector SteeringVector = CrossProduct(NormalToProbeAndWallNormal, ProbeDir); - - float SteeringForce = m_flightSpeed * (1 - frac) * (DotProduct(WallNormal.Normalize(), m_SaveVelocity.Normalize())); - if (SteeringForce < 0.0) - { - SteeringForce = -SteeringForce; - } - SteeringVector = SteeringForce * SteeringVector.Normalize(); - - return SteeringVector; - } - return Vector(0, 0, 0); -} - -#endif \ No newline at end of file diff --git a/dlls/Half-life/islave.cpp b/dlls/Half-life/islave.cpp deleted file mode 100644 index d40a24ec..00000000 --- a/dlls/Half-life/islave.cpp +++ /dev/null @@ -1,840 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// Alien slave monster -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "squadmonster.h" -#include "schedule.h" -#include "effects.h" -#include "weapons.h" -#include "soundent.h" - -extern DLL_GLOBAL int g_iSkillLevel; - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define ISLAVE_AE_CLAW (1) -#define ISLAVE_AE_CLAWRAKE (2) -#define ISLAVE_AE_ZAP_POWERUP (3) -#define ISLAVE_AE_ZAP_SHOOT (4) -#define ISLAVE_AE_ZAP_DONE (5) - -#define ISLAVE_MAX_BEAMS 8 - -class CISlave : public CSquadMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int ISoundMask(void); - int Classify(void); - int IRelationship(CBaseEntity *pTarget); - void HandleAnimEvent(MonsterEvent_t *pEvent); - BOOL CheckRangeAttack1(float flDot, float flDist); - BOOL CheckRangeAttack2(float flDot, float flDist); - void CallForHelp(char *szClassname, float flDist, EHANDLE hEnemy, Vector &vecLocation); - void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - - void DeathSound(void); - void PainSound(void); - void AlertSound(void); - void IdleSound(void); - - void Killed(entvars_t *pevAttacker, int iGib); - - void StartTask(Task_t *pTask); - Schedule_t *GetSchedule(void); - Schedule_t *GetScheduleOfType(int Type); - CUSTOM_SCHEDULES; - - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void ClearBeams(); - void ArmBeam(int side); - void WackBeam(int side, CBaseEntity *pEntity); - void ZapBeam(int side); - void BeamGlow(void); - - int m_iBravery; - - CBeam *m_pBeam[ISLAVE_MAX_BEAMS]; - - int m_iBeams; - float m_flNextAttack; - - int m_voicePitch; - - EHANDLE m_hDead; - - static const char *pAttackHitSounds[]; - static const char *pAttackMissSounds[]; - static const char *pPainSounds[]; - static const char *pDeathSounds[]; -}; -LINK_ENTITY_TO_CLASS(monster_alien_slave, CISlave); -LINK_ENTITY_TO_CLASS(monster_vortigaunt, CISlave); - -TYPEDESCRIPTION CISlave::m_SaveData[] = - { - DEFINE_FIELD(CISlave, m_iBravery, FIELD_INTEGER), - - DEFINE_ARRAY(CISlave, m_pBeam, FIELD_CLASSPTR, ISLAVE_MAX_BEAMS), - DEFINE_FIELD(CISlave, m_iBeams, FIELD_INTEGER), - DEFINE_FIELD(CISlave, m_flNextAttack, FIELD_TIME), - - DEFINE_FIELD(CISlave, m_voicePitch, FIELD_INTEGER), - - DEFINE_FIELD(CISlave, m_hDead, FIELD_EHANDLE), - -}; - -IMPLEMENT_SAVERESTORE(CISlave, CSquadMonster); - -const char *CISlave::pAttackHitSounds[] = - { - "zombie/claw_strike1.wav", - "zombie/claw_strike2.wav", - "zombie/claw_strike3.wav", -}; - -const char *CISlave::pAttackMissSounds[] = - { - "zombie/claw_miss1.wav", - "zombie/claw_miss2.wav", -}; - -const char *CISlave::pPainSounds[] = - { - "aslave/slv_pain1.wav", - "aslave/slv_pain2.wav", -}; - -const char *CISlave::pDeathSounds[] = - { - "aslave/slv_die1.wav", - "aslave/slv_die2.wav", -}; - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CISlave ::Classify(void) -{ - return CLASS_ALIEN_MILITARY; -} - -int CISlave::IRelationship(CBaseEntity *pTarget) -{ - if ((pTarget->IsPlayer())) - if ((pev->spawnflags & SF_MONSTER_WAIT_UNTIL_PROVOKED) && !(m_afMemory & bits_MEMORY_PROVOKED)) - return R_NO; - return CBaseMonster::IRelationship(pTarget); -} - -void CISlave ::CallForHelp(char *szClassname, float flDist, EHANDLE hEnemy, Vector &vecLocation) -{ - // ALERT( at_aiconsole, "help " ); - - // skip ones not on my netname - if (FStringNull(pev->netname)) - return; - - CBaseEntity *pEntity = NULL; - - while ((pEntity = UTIL_FindEntityByString(pEntity, "netname", STRING(pev->netname))) != NULL) - { - float d = (pev->origin - pEntity->pev->origin).Length(); - if (d < flDist) - { - CBaseMonster *pMonster = pEntity->MyMonsterPointer(); - if (pMonster) - { - pMonster->m_afMemory |= bits_MEMORY_PROVOKED; - pMonster->PushEnemy(hEnemy, vecLocation); - } - } - } -} - -//========================================================= -// ALertSound - scream -//========================================================= -void CISlave ::AlertSound(void) -{ - if (m_hEnemy != NULL) - { - SENTENCEG_PlayRndSz(ENT(pev), "SLV_ALERT", 0.85, ATTN_NORM, 0, m_voicePitch); - - CallForHelp("monster_alien_slave", 512, m_hEnemy, m_vecEnemyLKP); - } -} - -//========================================================= -// IdleSound -//========================================================= -void CISlave ::IdleSound(void) -{ - if (RANDOM_LONG(0, 2) == 0) - { - SENTENCEG_PlayRndSz(ENT(pev), "SLV_IDLE", 0.85, ATTN_NORM, 0, m_voicePitch); - } - -#if 0 - int side = RANDOM_LONG( 0, 1 ) * 2 - 1; - - ClearBeams( ); - ArmBeam( side ); - - UTIL_MakeAimVectors( pev->angles ); - Vector vecSrc = pev->origin + gpGlobals->v_right * 2 * side; - MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc ); - WRITE_BYTE(TE_DLIGHT); - WRITE_COORD(vecSrc.x); // X - WRITE_COORD(vecSrc.y); // Y - WRITE_COORD(vecSrc.z); // Z - WRITE_BYTE( 8 ); // radius * 0.1 - WRITE_BYTE( 255 ); // r - WRITE_BYTE( 180 ); // g - WRITE_BYTE( 96 ); // b - WRITE_BYTE( 10 ); // time * 10 - WRITE_BYTE( 0 ); // decay * 0.1 - MESSAGE_END( ); - - EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "debris/zap1.wav", 1, ATTN_NORM, 0, 100 ); -#endif -} - -//========================================================= -// PainSound -//========================================================= -void CISlave ::PainSound(void) -{ - if (RANDOM_LONG(0, 2) == 0) - { - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pPainSounds[RANDOM_LONG(0, ARRAYSIZE(pPainSounds) - 1)], 1.0, ATTN_NORM, 0, m_voicePitch); - } -} - -//========================================================= -// DieSound -//========================================================= - -void CISlave ::DeathSound(void) -{ - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pDeathSounds[RANDOM_LONG(0, ARRAYSIZE(pDeathSounds) - 1)], 1.0, ATTN_NORM, 0, m_voicePitch); -} - -//========================================================= -// ISoundMask - returns a bit mask indicating which types -// of sounds this monster regards. -//========================================================= -int CISlave ::ISoundMask(void) -{ - return bits_SOUND_WORLD | - bits_SOUND_COMBAT | - bits_SOUND_DANGER | - bits_SOUND_PLAYER; -} - -void CISlave::Killed(entvars_t *pevAttacker, int iGib) -{ - ClearBeams(); - CSquadMonster::Killed(pevAttacker, iGib); -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CISlave ::SetYawSpeed(void) -{ - int ys; - - switch (m_Activity) - { - case ACT_WALK: - ys = 50; - break; - case ACT_RUN: - ys = 70; - break; - case ACT_IDLE: - ys = 50; - break; - default: - ys = 90; - break; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -// -// Returns number of events handled, 0 if none. -//========================================================= -void CISlave ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - // ALERT( at_console, "event %d : %f\n", pEvent->event, pev->frame ); - switch (pEvent->event) - { - case ISLAVE_AE_CLAW: - { - // SOUND HERE! - CBaseEntity *pHurt = CheckTraceHullAttack(70, gSkillData.slaveDmgClaw, DMG_SLASH); - if (pHurt) - { - if (pHurt->pev->flags & (FL_MONSTER | FL_CLIENT)) - { - pHurt->pev->punchangle.z = -18; - pHurt->pev->punchangle.x = 5; - } - // Play a random attack hit sound - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pAttackHitSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackHitSounds) - 1)], 1.0, ATTN_NORM, 0, m_voicePitch); - } - else - { - // Play a random attack miss sound - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pAttackMissSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackMissSounds) - 1)], 1.0, ATTN_NORM, 0, m_voicePitch); - } - } - break; - - case ISLAVE_AE_CLAWRAKE: - { - CBaseEntity *pHurt = CheckTraceHullAttack(70, gSkillData.slaveDmgClawrake, DMG_SLASH); - if (pHurt) - { - if (pHurt->pev->flags & (FL_MONSTER | FL_CLIENT)) - { - pHurt->pev->punchangle.z = -18; - pHurt->pev->punchangle.x = 5; - } - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pAttackHitSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackHitSounds) - 1)], 1.0, ATTN_NORM, 0, m_voicePitch); - } - else - { - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pAttackMissSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackMissSounds) - 1)], 1.0, ATTN_NORM, 0, m_voicePitch); - } - } - break; - - case ISLAVE_AE_ZAP_POWERUP: - { - // speed up attack when on hard - if (g_iSkillLevel == SKILL_HARD) - pev->framerate = 1.5; - - UTIL_MakeAimVectors(pev->angles); - - if (m_iBeams == 0) - { - Vector vecSrc = pev->origin + gpGlobals->v_forward * 2; - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSrc); - WRITE_BYTE(TE_DLIGHT); - WRITE_COORD(vecSrc.x); // X - WRITE_COORD(vecSrc.y); // Y - WRITE_COORD(vecSrc.z); // Z - WRITE_BYTE(12); // radius * 0.1 - WRITE_BYTE(255); // r - WRITE_BYTE(180); // g - WRITE_BYTE(96); // b - WRITE_BYTE(20 / pev->framerate); // time * 10 - WRITE_BYTE(0); // decay * 0.1 - MESSAGE_END(); - } - if (m_hDead != NULL) - { - WackBeam(-1, m_hDead); - WackBeam(1, m_hDead); - } - else - { - ArmBeam(-1); - ArmBeam(1); - BeamGlow(); - } - - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0, 100 + m_iBeams * 10); - pev->skin = m_iBeams / 2; - } - break; - - case ISLAVE_AE_ZAP_SHOOT: - { - ClearBeams(); - - if (m_hDead != NULL) - { - Vector vecDest = m_hDead->pev->origin + Vector(0, 0, 38); - TraceResult trace; - UTIL_TraceHull(vecDest, vecDest, dont_ignore_monsters, human_hull, m_hDead->edict(), &trace); - - if (!trace.fStartSolid) - { - CBaseEntity *pNew = Create("monster_alien_slave", m_hDead->pev->origin, m_hDead->pev->angles); - CBaseMonster *pNewMonster = pNew->MyMonsterPointer(); - pNew->pev->spawnflags |= 1; - WackBeam(-1, pNew); - WackBeam(1, pNew); - UTIL_Remove(m_hDead); - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "hassault/hw_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG(130, 160)); - - /* - CBaseEntity *pEffect = Create( "test_effect", pNew->Center(), pev->angles ); - pEffect->Use( this, this, USE_ON, 1 ); - */ - break; - } - } - ClearMultiDamage(); - - UTIL_MakeAimVectors(pev->angles); - - ZapBeam(-1); - ZapBeam(1); - - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "hassault/hw_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG(130, 160)); - // STOP_SOUND( ENT(pev), CHAN_WEAPON, "debris/zap4.wav" ); - ApplyMultiDamage(pev, pev); - - m_flNextAttack = gpGlobals->time + RANDOM_FLOAT(0.5, 4.0); - } - break; - - case ISLAVE_AE_ZAP_DONE: - { - ClearBeams(); - } - break; - - default: - CSquadMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// CheckRangeAttack1 - normal beam attack -//========================================================= -BOOL CISlave ::CheckRangeAttack1(float flDot, float flDist) -{ - if (m_flNextAttack > gpGlobals->time) - { - return FALSE; - } - - return CSquadMonster::CheckRangeAttack1(flDot, flDist); -} - -//========================================================= -// CheckRangeAttack2 - check bravery and try to resurect dead comrades -//========================================================= -BOOL CISlave ::CheckRangeAttack2(float flDot, float flDist) -{ - return FALSE; - - if (m_flNextAttack > gpGlobals->time) - { - return FALSE; - } - - m_hDead = NULL; - m_iBravery = 0; - - CBaseEntity *pEntity = NULL; - while ((pEntity = UTIL_FindEntityByClassname(pEntity, "monster_alien_slave")) != NULL) - { - TraceResult tr; - - UTIL_TraceLine(EyePosition(), pEntity->EyePosition(), ignore_monsters, ENT(pev), &tr); - if (tr.flFraction == 1.0 || tr.pHit == pEntity->edict()) - { - if (pEntity->pev->deadflag == DEAD_DEAD) - { - float d = (pev->origin - pEntity->pev->origin).Length(); - if (d < flDist) - { - m_hDead = pEntity; - flDist = d; - } - m_iBravery--; - } - else - { - m_iBravery++; - } - } - } - if (m_hDead != NULL) - return TRUE; - else - return FALSE; -} - -//========================================================= -// StartTask -//========================================================= -void CISlave ::StartTask(Task_t *pTask) -{ - ClearBeams(); - - CSquadMonster ::StartTask(pTask); -} - -//========================================================= -// Spawn -//========================================================= -void CISlave ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/islave.mdl"); - UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->effects = 0; - pev->health = gSkillData.slaveHealth; - pev->view_ofs = Vector(0, 0, 64); // position of the eyes relative to monster's origin. - m_flFieldOfView = VIEW_FIELD_WIDE; // NOTE: we need a wide field of view so npc will notice player and say hello - m_MonsterState = MONSTERSTATE_NONE; - m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_RANGE_ATTACK2 | bits_CAP_DOORS_GROUP; - - m_voicePitch = RANDOM_LONG(85, 110); - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CISlave ::Precache() -{ - int i; - - PRECACHE_MODEL("models/islave.mdl"); - PRECACHE_MODEL("sprites/lgtning.spr"); - PRECACHE_SOUND("debris/zap1.wav"); - PRECACHE_SOUND("debris/zap4.wav"); - PRECACHE_SOUND("weapons/electro4.wav"); - PRECACHE_SOUND("hassault/hw_shoot1.wav"); - PRECACHE_SOUND("zombie/zo_pain2.wav"); - PRECACHE_SOUND("headcrab/hc_headbite.wav"); - PRECACHE_SOUND("weapons/cbar_miss1.wav"); - - for (i = 0; i < ARRAYSIZE(pAttackHitSounds); i++) - PRECACHE_SOUND((char *)pAttackHitSounds[i]); - - for (i = 0; i < ARRAYSIZE(pAttackMissSounds); i++) - PRECACHE_SOUND((char *)pAttackMissSounds[i]); - - for (i = 0; i < ARRAYSIZE(pPainSounds); i++) - PRECACHE_SOUND((char *)pPainSounds[i]); - - for (i = 0; i < ARRAYSIZE(pDeathSounds); i++) - PRECACHE_SOUND((char *)pDeathSounds[i]); - - UTIL_PrecacheOther("test_effect"); -} - -//========================================================= -// TakeDamage - get provoked when injured -//========================================================= - -int CISlave ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - // don't slash one of your own - if ((bitsDamageType & DMG_SLASH) && pevAttacker && IRelationship(Instance(pevAttacker)) < R_DL) - return 0; - - m_afMemory |= bits_MEMORY_PROVOKED; - return CSquadMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -void CISlave::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - if (bitsDamageType & DMG_SHOCK) - return; - - CSquadMonster::TraceAttack(pevAttacker, flDamage, vecDir, ptr, bitsDamageType); -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - -// primary range attack -Task_t tlSlaveAttack1[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_FACE_IDEAL, (float)0}, - {TASK_RANGE_ATTACK1, (float)0}, -}; - -Schedule_t slSlaveAttack1[] = - { - {tlSlaveAttack1, - ARRAYSIZE(tlSlaveAttack1), - bits_COND_CAN_MELEE_ATTACK1 | - bits_COND_HEAR_SOUND | - bits_COND_HEAVY_DAMAGE, - - bits_SOUND_DANGER, - "Slave Range Attack1"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CISlave){ - slSlaveAttack1, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CISlave, CSquadMonster); - -//========================================================= -//========================================================= -Schedule_t *CISlave ::GetSchedule(void) -{ - ClearBeams(); - - /* - if (pev->spawnflags) - { - pev->spawnflags = 0; - return GetScheduleOfType( SCHED_RELOAD ); - } -*/ - - if (HasConditions(bits_COND_HEAR_SOUND)) - { - CSound *pSound; - pSound = PBestSound(); - - ASSERT(pSound != NULL); - - if (pSound && (pSound->m_iType & bits_SOUND_DANGER)) - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_BEST_SOUND); - if (pSound->m_iType & bits_SOUND_COMBAT) - m_afMemory |= bits_MEMORY_PROVOKED; - } - - switch (m_MonsterState) - { - case MONSTERSTATE_COMBAT: - // dead enemy - if (HasConditions(bits_COND_ENEMY_DEAD)) - { - // call base class, all code to handle dead enemies is centralized there. - return CBaseMonster ::GetSchedule(); - } - - if (pev->health < 20 || m_iBravery < 0) - { - if (!HasConditions(bits_COND_CAN_MELEE_ATTACK1)) - { - m_failSchedule = SCHED_CHASE_ENEMY; - if (HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE)) - { - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_ENEMY); - } - if (HasConditions(bits_COND_SEE_ENEMY) && HasConditions(bits_COND_ENEMY_FACING_ME)) - { - // ALERT( at_console, "exposed\n"); - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_ENEMY); - } - } - } - break; - } - return CSquadMonster::GetSchedule(); -} - -Schedule_t *CISlave ::GetScheduleOfType(int Type) -{ - switch (Type) - { - case SCHED_FAIL: - if (HasConditions(bits_COND_CAN_MELEE_ATTACK1)) - { - return CSquadMonster ::GetScheduleOfType(SCHED_MELEE_ATTACK1); - ; - } - break; - case SCHED_RANGE_ATTACK1: - return slSlaveAttack1; - case SCHED_RANGE_ATTACK2: - return slSlaveAttack1; - } - return CSquadMonster ::GetScheduleOfType(Type); -} - -//========================================================= -// ArmBeam - small beam from arm to nearby geometry -//========================================================= - -void CISlave ::ArmBeam(int side) -{ - TraceResult tr; - float flDist = 1.0; - - if (m_iBeams >= ISLAVE_MAX_BEAMS) - return; - - UTIL_MakeAimVectors(pev->angles); - Vector vecSrc = pev->origin + gpGlobals->v_up * 36 + gpGlobals->v_right * side * 16 + gpGlobals->v_forward * 32; - - for (int i = 0; i < 3; i++) - { - Vector vecAim = gpGlobals->v_right * side * RANDOM_FLOAT(0, 1) + gpGlobals->v_up * RANDOM_FLOAT(-1, 1); - TraceResult tr1; - UTIL_TraceLine(vecSrc, vecSrc + vecAim * 512, dont_ignore_monsters, ENT(pev), &tr1); - if (flDist > tr1.flFraction) - { - tr = tr1; - flDist = tr.flFraction; - } - } - - // Couldn't find anything close enough - if (flDist == 1.0) - return; - - DecalGunshot(&tr, BULLET_PLAYER_CROWBAR); - - m_pBeam[m_iBeams] = CBeam::BeamCreate("sprites/lgtning.spr", 30); - if (!m_pBeam[m_iBeams]) - return; - - m_pBeam[m_iBeams]->PointEntInit(tr.vecEndPos, entindex()); - m_pBeam[m_iBeams]->SetEndAttachment(side < 0 ? 2 : 1); - // m_pBeam[m_iBeams]->SetColor( 180, 255, 96 ); - m_pBeam[m_iBeams]->SetColor(96, 128, 16); - m_pBeam[m_iBeams]->SetBrightness(64); - m_pBeam[m_iBeams]->SetNoise(80); - m_iBeams++; -} - -//========================================================= -// BeamGlow - brighten all beams -//========================================================= -void CISlave ::BeamGlow() -{ - int b = m_iBeams * 32; - if (b > 255) - b = 255; - - for (int i = 0; i < m_iBeams; i++) - { - if (m_pBeam[i]->GetBrightness() != 255) - { - m_pBeam[i]->SetBrightness(b); - } - } -} - -//========================================================= -// WackBeam - regenerate dead colleagues -//========================================================= -void CISlave ::WackBeam(int side, CBaseEntity *pEntity) -{ - Vector vecDest; - float flDist = 1.0; - - if (m_iBeams >= ISLAVE_MAX_BEAMS) - return; - - if (pEntity == NULL) - return; - - m_pBeam[m_iBeams] = CBeam::BeamCreate("sprites/lgtning.spr", 30); - if (!m_pBeam[m_iBeams]) - return; - - m_pBeam[m_iBeams]->PointEntInit(pEntity->Center(), entindex()); - m_pBeam[m_iBeams]->SetEndAttachment(side < 0 ? 2 : 1); - m_pBeam[m_iBeams]->SetColor(180, 255, 96); - m_pBeam[m_iBeams]->SetBrightness(255); - m_pBeam[m_iBeams]->SetNoise(80); - m_iBeams++; -} - -//========================================================= -// ZapBeam - heavy damage directly forward -//========================================================= -void CISlave ::ZapBeam(int side) -{ - Vector vecSrc, vecAim; - TraceResult tr; - CBaseEntity *pEntity; - - if (m_iBeams >= ISLAVE_MAX_BEAMS) - return; - - vecSrc = pev->origin + gpGlobals->v_up * 36; - vecAim = ShootAtEnemy(vecSrc); - float deflection = 0.01; - vecAim = vecAim + side * gpGlobals->v_right * RANDOM_FLOAT(0, deflection) + gpGlobals->v_up * RANDOM_FLOAT(-deflection, deflection); - UTIL_TraceLine(vecSrc, vecSrc + vecAim * 1024, dont_ignore_monsters, ENT(pev), &tr); - - m_pBeam[m_iBeams] = CBeam::BeamCreate("sprites/lgtning.spr", 50); - if (!m_pBeam[m_iBeams]) - return; - - m_pBeam[m_iBeams]->PointEntInit(tr.vecEndPos, entindex()); - m_pBeam[m_iBeams]->SetEndAttachment(side < 0 ? 2 : 1); - m_pBeam[m_iBeams]->SetColor(180, 255, 96); - m_pBeam[m_iBeams]->SetBrightness(255); - m_pBeam[m_iBeams]->SetNoise(20); - m_iBeams++; - - pEntity = CBaseEntity::Instance(tr.pHit); - if (pEntity != NULL && pEntity->pev->takedamage) - { - pEntity->TraceAttack(pev, gSkillData.slaveDmgZap, vecAim, &tr, DMG_SHOCK); - } - UTIL_EmitAmbientSound(ENT(pev), tr.vecEndPos, "weapons/electro4.wav", 0.5, ATTN_NORM, 0, RANDOM_LONG(140, 160)); -} - -//========================================================= -// ClearBeams - remove all beams -//========================================================= -void CISlave ::ClearBeams() -{ - for (int i = 0; i < ISLAVE_MAX_BEAMS; i++) - { - if (m_pBeam[i]) - { - UTIL_Remove(m_pBeam[i]); - m_pBeam[i] = NULL; - } - } - m_iBeams = 0; - pev->skin = 0; - - STOP_SOUND(ENT(pev), CHAN_WEAPON, "debris/zap4.wav"); -} diff --git a/dlls/Half-life/items.cpp b/dlls/Half-life/items.cpp deleted file mode 100644 index 6747f6e3..00000000 --- a/dlls/Half-life/items.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -/* - -===== items.cpp ======================================================== - - functions governing the selection/use of weapons for players - -*/ - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "weapons.h" -#include "player.h" -#include "skill.h" -#include "items.h" -#include "gamerules.h" - -extern int gmsgItemPickup; - -class CWorldItem : public CBaseEntity -{ -public: - void KeyValue(KeyValueData *pkvd); - void Spawn(void); - int m_iType; -}; - -LINK_ENTITY_TO_CLASS(world_items, CWorldItem); - -void CWorldItem::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "type")) - { - m_iType = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else - CBaseEntity::KeyValue(pkvd); -} - -void CWorldItem::Spawn(void) -{ - CBaseEntity *pEntity = NULL; - - switch (m_iType) - { - case 44: // ITEM_BATTERY: - pEntity = CBaseEntity::Create("item_battery", pev->origin, pev->angles); - break; - case 42: // ITEM_ANTIDOTE: - pEntity = CBaseEntity::Create("item_antidote", pev->origin, pev->angles); - break; - case 43: // ITEM_SECURITY: - pEntity = CBaseEntity::Create("item_security", pev->origin, pev->angles); - break; - case 45: // ITEM_SUIT: - pEntity = CBaseEntity::Create("item_suit", pev->origin, pev->angles); - break; - } - - if (!pEntity) - { - ALERT(at_console, "unable to create world_item %d\n", m_iType); - } - else - { - pEntity->pev->target = pev->target; - pEntity->pev->targetname = pev->targetname; - pEntity->pev->spawnflags = pev->spawnflags; - } - - REMOVE_ENTITY(edict()); -} - -void CItem::Spawn(void) -{ - pev->movetype = MOVETYPE_TOSS; - pev->solid = SOLID_TRIGGER; - UTIL_SetOrigin(pev, pev->origin); - UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 16)); - SetTouch(ItemTouch); - - if (DROP_TO_FLOOR(ENT(pev)) == 0) - { - ALERT(at_error, "Item %s fell out of level at %f,%f,%f", STRING(pev->classname), pev->origin.x, pev->origin.y, pev->origin.z); - UTIL_Remove(this); - return; - } -} - -extern int gEvilImpulse101; - -void CItem::ItemTouch(CBaseEntity *pOther) -{ - // if it's not a player, ignore - if (!pOther->IsPlayer()) - { - return; - } - - CBasePlayer *pPlayer = (CBasePlayer *)pOther; - - // ok, a player is touching this item, but can he have it? - if (!g_pGameRules->CanHaveItem(pPlayer, this)) - { - // no? Ignore the touch. - return; - } - - if (MyTouch(pPlayer)) - { - SUB_UseTargets(pOther, USE_TOGGLE, 0); - SetTouch(NULL); - - // player grabbed the item. - g_pGameRules->PlayerGotItem(pPlayer, this); - if (g_pGameRules->ItemShouldRespawn(this) == GR_ITEM_RESPAWN_YES) - { - Respawn(); - } - else - { - UTIL_Remove(this); - } - } - else if (gEvilImpulse101) - { - UTIL_Remove(this); - } -} - -CBaseEntity *CItem::Respawn(void) -{ - SetTouch(NULL); - pev->effects |= EF_NODRAW; - - UTIL_SetOrigin(pev, g_pGameRules->VecItemRespawnSpot(this)); // blip to whereever you should respawn. - - SetThink(Materialize); - pev->nextthink = g_pGameRules->FlItemRespawnTime(this); - return this; -} - -void CItem::Materialize(void) -{ - if (pev->effects & EF_NODRAW) - { - // changing from invisible state to visible. - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "items/suitchargeok1.wav", 1, ATTN_NORM, 0, 150); - pev->effects &= ~EF_NODRAW; - pev->effects |= EF_MUZZLEFLASH; - } - - SetTouch(ItemTouch); -} - -#define SF_SUIT_SHORTLOGON 0x0001 - -class CItemSuit : public CItem -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_suit.mdl"); - CItem::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_suit.mdl"); - } - BOOL MyTouch(CBasePlayer *pPlayer) - { - if (pPlayer->pev->weapons & (1 << WEAPON_SUIT)) - return FALSE; - - if (pev->spawnflags & SF_SUIT_SHORTLOGON) - EMIT_SOUND_SUIT(pPlayer->edict(), "!HEV_A0"); // short version of suit logon, - else - EMIT_SOUND_SUIT(pPlayer->edict(), "!HEV_AAx"); // long version of suit logon - - pPlayer->pev->weapons |= (1 << WEAPON_SUIT); - return TRUE; - } -}; - -LINK_ENTITY_TO_CLASS(item_suit, CItemSuit); - -class CItemBattery : public CItem -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_battery.mdl"); - CItem::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_battery.mdl"); - PRECACHE_SOUND("items/gunpickup2.wav"); - } - BOOL MyTouch(CBasePlayer *pPlayer) - { - if ((pPlayer->pev->armorvalue < MAX_NORMAL_BATTERY) && - (pPlayer->pev->weapons & (1 << WEAPON_SUIT))) - { - int pct; - char szcharge[64]; - - pPlayer->pev->armorvalue += gSkillData.batteryCapacity; - pPlayer->pev->armorvalue = min(pPlayer->pev->armorvalue, MAX_NORMAL_BATTERY); - - EMIT_SOUND(pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM); - - MESSAGE_BEGIN(MSG_ONE, gmsgItemPickup, NULL, pPlayer->pev); - WRITE_STRING(STRING(pev->classname)); - MESSAGE_END(); - - // Suit reports new power level - // For some reason this wasn't working in release build -- round it. - pct = (int)((float)(pPlayer->pev->armorvalue * 100.0) * (1.0 / MAX_NORMAL_BATTERY) + 0.5); - pct = (pct / 5); - if (pct > 0) - pct--; - - _snprintf(szcharge, sizeof(szcharge), "!HEV_%1dP", pct ); - - //EMIT_SOUND_SUIT(ENT(pev), szcharge); - pPlayer->SetSuitUpdate(szcharge, FALSE, SUIT_NEXT_IN_30SEC); - return TRUE; - } - return FALSE; - } -}; - -LINK_ENTITY_TO_CLASS(item_battery, CItemBattery); - -class CItemAntidote : public CItem -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_antidote.mdl"); - CItem::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_antidote.mdl"); - } - BOOL MyTouch(CBasePlayer *pPlayer) - { - pPlayer->SetSuitUpdate("!HEV_DET4", FALSE, SUIT_NEXT_IN_1MIN); - - pPlayer->m_rgItems[ITEM_ANTIDOTE] += 1; - return TRUE; - } -}; - -LINK_ENTITY_TO_CLASS(item_antidote, CItemAntidote); - -class CItemSecurity : public CItem -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_security.mdl"); - CItem::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_security.mdl"); - } - BOOL MyTouch(CBasePlayer *pPlayer) - { - pPlayer->m_rgItems[ITEM_SECURITY] += 1; - return TRUE; - } -}; - -LINK_ENTITY_TO_CLASS(item_security, CItemSecurity); - -class CItemLongJump : public CItem -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_longjump.mdl"); - CItem::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_longjump.mdl"); - } - BOOL MyTouch(CBasePlayer *pPlayer) - { - if (pPlayer->m_fLongJump) - { - return FALSE; - } - - if ((pPlayer->pev->weapons & (1 << WEAPON_SUIT))) - { - pPlayer->m_fLongJump = TRUE; // player now has longjump module - - g_engfuncs.pfnSetPhysicsKeyValue(pPlayer->edict(), "slj", "1"); - - MESSAGE_BEGIN(MSG_ONE, gmsgItemPickup, NULL, pPlayer->pev); - WRITE_STRING(STRING(pev->classname)); - MESSAGE_END(); - - EMIT_SOUND_SUIT(pPlayer->edict(), "!HEV_A1"); // Play the longjump sound UNDONE: Kelly? correct sound? - return TRUE; - } - return FALSE; - } -}; - -LINK_ENTITY_TO_CLASS(item_longjump, CItemLongJump); diff --git a/dlls/Half-life/leech.cpp b/dlls/Half-life/leech.cpp deleted file mode 100644 index 4bb93f9f..00000000 --- a/dlls/Half-life/leech.cpp +++ /dev/null @@ -1,689 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// leech - basic little swimming monster -//========================================================= -// -// UNDONE: -// DONE:Steering force model for attack -// DONE:Attack animation control / damage -// DONE:Establish range of up/down motion and steer around vertical obstacles -// DONE:Re-evaluate height periodically -// DONE:Fall (MOVETYPE_TOSS) and play different anim if out of water -// Test in complex room (c2a3?) -// DONE:Sounds? - Kelly will fix -// Blood cloud? Hurt effect? -// Group behavior? -// DONE:Save/restore -// Flop animation - just bind to ACT_TWITCH -// Fix fatal push into wall case -// -// Try this on a bird -// Try this on a model with hulls/tracehull? -// - -#include "float.h" -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" - -// Animation events -#define LEECH_AE_ATTACK 1 -#define LEECH_AE_FLOP 2 - -// Movement constants - -#define LEECH_ACCELERATE 10 -#define LEECH_CHECK_DIST 45 -#define LEECH_SWIM_SPEED 50 -#define LEECH_SWIM_ACCEL 80 -#define LEECH_SWIM_DECEL 10 -#define LEECH_TURN_RATE 90 -#define LEECH_SIZEX 10 -#define LEECH_FRAMETIME 0.1 - -#define DEBUG_BEAMS 0 - -#if DEBUG_BEAMS -#include "effects.h" -#endif - -class CLeech : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - - void EXPORT SwimThink(void); - void EXPORT DeadThink(void); - void Touch(CBaseEntity *pOther) - { - if (pOther->IsPlayer()) - { - // If the client is pushing me, give me some base velocity - if (gpGlobals->trace_ent && gpGlobals->trace_ent == edict()) - { - pev->basevelocity = pOther->pev->velocity; - pev->flags |= FL_BASEVELOCITY; - } - } - } - - void SetObjectCollisionBox(void) - { - pev->absmin = pev->origin + Vector(-8, -8, 0); - pev->absmax = pev->origin + Vector(8, 8, 2); - } - - void AttackSound(void); - void AlertSound(void); - void UpdateMotion(void); - float ObstacleDistance(CBaseEntity *pTarget); - void MakeVectors(void); - void RecalculateWaterlevel(void); - void SwitchLeechState(void); - - // Base entity functions - void HandleAnimEvent(MonsterEvent_t *pEvent); - int BloodColor(void) { return DONT_BLEED; } - void Killed(entvars_t *pevAttacker, int iGib); - void Activate(void); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - int Classify(void) { return CLASS_INSECT; } - int IRelationship(CBaseEntity *pTarget); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - static const char *pAttackSounds[]; - static const char *pAlertSounds[]; - -private: - // UNDONE: Remove unused boid vars, do group behavior - float m_flTurning; // is this boid turning? - BOOL m_fPathBlocked; // TRUE if there is an obstacle ahead - float m_flAccelerate; - float m_obstacle; - float m_top; - float m_bottom; - float m_height; - float m_waterTime; - float m_sideTime; // Timer to randomly check clearance on sides - float m_zTime; - float m_stateTime; - float m_attackSoundTime; - -#if DEBUG_BEAMS - CBeam *m_pb; - CBeam *m_pt; -#endif -}; - -LINK_ENTITY_TO_CLASS(monster_leech, CLeech); - -TYPEDESCRIPTION CLeech::m_SaveData[] = - { - DEFINE_FIELD(CLeech, m_flTurning, FIELD_FLOAT), - DEFINE_FIELD(CLeech, m_fPathBlocked, FIELD_BOOLEAN), - DEFINE_FIELD(CLeech, m_flAccelerate, FIELD_FLOAT), - DEFINE_FIELD(CLeech, m_obstacle, FIELD_FLOAT), - DEFINE_FIELD(CLeech, m_top, FIELD_FLOAT), - DEFINE_FIELD(CLeech, m_bottom, FIELD_FLOAT), - DEFINE_FIELD(CLeech, m_height, FIELD_FLOAT), - DEFINE_FIELD(CLeech, m_waterTime, FIELD_TIME), - DEFINE_FIELD(CLeech, m_sideTime, FIELD_TIME), - DEFINE_FIELD(CLeech, m_zTime, FIELD_TIME), - DEFINE_FIELD(CLeech, m_stateTime, FIELD_TIME), - DEFINE_FIELD(CLeech, m_attackSoundTime, FIELD_TIME), -}; - -IMPLEMENT_SAVERESTORE(CLeech, CBaseMonster); - -const char *CLeech::pAttackSounds[] = - { - "leech/leech_bite1.wav", - "leech/leech_bite2.wav", - "leech/leech_bite3.wav", -}; - -const char *CLeech::pAlertSounds[] = - { - "leech/leech_alert1.wav", - "leech/leech_alert2.wav", -}; - -void CLeech::Spawn(void) -{ - Precache(); - SET_MODEL(ENT(pev), "models/leech.mdl"); - // Just for fun - // SET_MODEL(ENT(pev), "models/icky.mdl"); - - // UTIL_SetSize( pev, g_vecZero, g_vecZero ); - UTIL_SetSize(pev, Vector(-1, -1, 0), Vector(1, 1, 2)); - // Don't push the minz down too much or the water check will fail because this entity is really point-sized - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_FLY; - SetBits(pev->flags, FL_SWIM); - pev->health = gSkillData.leechHealth; - - m_flFieldOfView = -0.5; // 180 degree FOV - m_flDistLook = 750; - MonsterInit(); - SetThink(SwimThink); - SetUse(NULL); - SetTouch(NULL); - pev->view_ofs = g_vecZero; - - m_flTurning = 0; - m_fPathBlocked = FALSE; - SetActivity(ACT_SWIM); - SetState(MONSTERSTATE_IDLE); - m_stateTime = gpGlobals->time + RANDOM_FLOAT(1, 5); -} - -void CLeech::Activate(void) -{ - RecalculateWaterlevel(); -} - -void CLeech::RecalculateWaterlevel(void) -{ - // Calculate boundaries - Vector vecTest = pev->origin - Vector(0, 0, 400); - - TraceResult tr; - - UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); - if (tr.flFraction != 1.0) - m_bottom = tr.vecEndPos.z + 1; - else - m_bottom = vecTest.z; - - m_top = UTIL_WaterLevel(pev->origin, pev->origin.z, pev->origin.z + 400) - 1; - - // Chop off 20% of the outside range - float newBottom = m_bottom * 0.8 + m_top * 0.2; - m_top = m_bottom * 0.2 + m_top * 0.8; - m_bottom = newBottom; - m_height = RANDOM_FLOAT(m_bottom, m_top); - m_waterTime = gpGlobals->time + RANDOM_FLOAT(5, 7); -} - -void CLeech::SwitchLeechState(void) -{ - m_stateTime = gpGlobals->time + RANDOM_FLOAT(3, 6); - if (m_MonsterState == MONSTERSTATE_COMBAT) - { - m_hEnemy = NULL; - SetState(MONSTERSTATE_IDLE); - // We may be up against the player, so redo the side checks - m_sideTime = 0; - } - else - { - Look(m_flDistLook); - CBaseEntity *pEnemy = BestVisibleEnemy(); - if (pEnemy && pEnemy->pev->waterlevel != 0) - { - m_hEnemy = pEnemy; - SetState(MONSTERSTATE_COMBAT); - m_stateTime = gpGlobals->time + RANDOM_FLOAT(18, 25); - AlertSound(); - } - } -} - -int CLeech::IRelationship(CBaseEntity *pTarget) -{ - if (pTarget->IsPlayer()) - return R_DL; - return CBaseMonster::IRelationship(pTarget); -} - -void CLeech::AttackSound(void) -{ - if (gpGlobals->time > m_attackSoundTime) - { - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, pAttackSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackSounds) - 1)], 1.0, ATTN_NORM, 0, PITCH_NORM); - m_attackSoundTime = gpGlobals->time + 0.5; - } -} - -void CLeech::AlertSound(void) -{ - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, pAlertSounds[RANDOM_LONG(0, ARRAYSIZE(pAlertSounds) - 1)], 1.0, ATTN_NORM * 0.5, 0, PITCH_NORM); -} - -void CLeech::Precache(void) -{ - int i; - - //PRECACHE_MODEL("models/icky.mdl"); - PRECACHE_MODEL("models/leech.mdl"); - - for (i = 0; i < ARRAYSIZE(pAttackSounds); i++) - PRECACHE_SOUND((char *)pAttackSounds[i]); - for (i = 0; i < ARRAYSIZE(pAlertSounds); i++) - PRECACHE_SOUND((char *)pAlertSounds[i]); -} - -int CLeech::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - pev->velocity = g_vecZero; - - // Nudge the leech away from the damage - if (pevInflictor) - { - pev->velocity = (pev->origin - pevInflictor->origin).Normalize() * 25; - } - - return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -void CLeech::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case LEECH_AE_ATTACK: - AttackSound(); - CBaseEntity *pEnemy; - - pEnemy = m_hEnemy; - if (pEnemy != NULL) - { - Vector dir, face; - - UTIL_MakeVectorsPrivate(pev->angles, face, NULL, NULL); - face.z = 0; - dir = (pEnemy->pev->origin - pev->origin); - dir.z = 0; - dir = dir.Normalize(); - face = face.Normalize(); - - if (DotProduct(dir, face) > 0.9) // Only take damage if the leech is facing the prey - pEnemy->TakeDamage(pev, pev, gSkillData.leechDmgBite, DMG_SLASH); - } - m_stateTime -= 2; - break; - - case LEECH_AE_FLOP: - // Play flop sound - break; - - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -void CLeech::MakeVectors(void) -{ - Vector tmp = pev->angles; - tmp.x = -tmp.x; - UTIL_MakeVectors(tmp); -} - -// -// ObstacleDistance - returns normalized distance to obstacle -// -float CLeech::ObstacleDistance(CBaseEntity *pTarget) -{ - TraceResult tr; - Vector vecTest; - - // use VELOCITY, not angles, not all boids point the direction they are flying - //Vector vecDir = UTIL_VecToAngles( pev->velocity ); - MakeVectors(); - - // check for obstacle ahead - vecTest = pev->origin + gpGlobals->v_forward * LEECH_CHECK_DIST; - UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); - - if (tr.fStartSolid) - { - pev->speed = -LEECH_SWIM_SPEED * 0.5; - // ALERT( at_console, "Stuck from (%f %f %f) to (%f %f %f)\n", pev->oldorigin.x, pev->oldorigin.y, pev->oldorigin.z, pev->origin.x, pev->origin.y, pev->origin.z ); - // UTIL_SetOrigin( pev, pev->oldorigin ); - } - - if (tr.flFraction != 1.0) - { - if ((pTarget == NULL || tr.pHit != pTarget->edict())) - { - return tr.flFraction; - } - else - { - if (fabs(m_height - pev->origin.z) > 10) - return tr.flFraction; - } - } - - if (m_sideTime < gpGlobals->time) - { - // extra wide checks - vecTest = pev->origin + gpGlobals->v_right * LEECH_SIZEX * 2 + gpGlobals->v_forward * LEECH_CHECK_DIST; - UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); - if (tr.flFraction != 1.0) - return tr.flFraction; - - vecTest = pev->origin - gpGlobals->v_right * LEECH_SIZEX * 2 + gpGlobals->v_forward * LEECH_CHECK_DIST; - UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); - if (tr.flFraction != 1.0) - return tr.flFraction; - - // Didn't hit either side, so stop testing for another 0.5 - 1 seconds - m_sideTime = gpGlobals->time + RANDOM_FLOAT(0.5, 1); - } - return 1.0; -} - -void CLeech::DeadThink(void) -{ - if (m_fSequenceFinished) - { - if (m_Activity == ACT_DIEFORWARD) - { - SetThink(NULL); - StopAnimation(); - return; - } - else if (pev->flags & FL_ONGROUND) - { - pev->solid = SOLID_NOT; - SetActivity(ACT_DIEFORWARD); - } - } - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - // Apply damage velocity, but keep out of the walls - if (pev->velocity.x != 0 || pev->velocity.y != 0) - { - TraceResult tr; - - // Look 0.5 seconds ahead - UTIL_TraceLine(pev->origin, pev->origin + pev->velocity * 0.5, missile, edict(), &tr); - if (tr.flFraction != 1.0) - { - pev->velocity.x = 0; - pev->velocity.y = 0; - } - } -} - -void CLeech::UpdateMotion(void) -{ - float flapspeed = (pev->speed - m_flAccelerate) / LEECH_ACCELERATE; - m_flAccelerate = m_flAccelerate * 0.8 + pev->speed * 0.2; - - if (flapspeed < 0) - flapspeed = -flapspeed; - flapspeed += 1.0; - if (flapspeed < 0.5) - flapspeed = 0.5; - if (flapspeed > 1.9) - flapspeed = 1.9; - - pev->framerate = flapspeed; - - if (!m_fPathBlocked) - pev->avelocity.y = pev->ideal_yaw; - else - pev->avelocity.y = pev->ideal_yaw * m_obstacle; - - if (pev->avelocity.y > 150) - m_IdealActivity = ACT_TURN_LEFT; - else if (pev->avelocity.y < -150) - m_IdealActivity = ACT_TURN_RIGHT; - else - m_IdealActivity = ACT_SWIM; - - // lean - float targetPitch, delta; - delta = m_height - pev->origin.z; - - if (delta < -10) - targetPitch = -30; - else if (delta > 10) - targetPitch = 30; - else - targetPitch = 0; - - pev->angles.x = UTIL_Approach(targetPitch, pev->angles.x, 60 * LEECH_FRAMETIME); - - // bank - pev->avelocity.z = -(pev->angles.z + (pev->avelocity.y * 0.25)); - - if (m_MonsterState == MONSTERSTATE_COMBAT && HasConditions(bits_COND_CAN_MELEE_ATTACK1)) - m_IdealActivity = ACT_MELEE_ATTACK1; - - // Out of water check - if (!pev->waterlevel) - { - pev->movetype = MOVETYPE_TOSS; - m_IdealActivity = ACT_TWITCH; - pev->velocity = g_vecZero; - - // Animation will intersect the floor if either of these is non-zero - pev->angles.z = 0; - pev->angles.x = 0; - - if (pev->framerate < 1.0) - pev->framerate = 1.0; - } - else if (pev->movetype == MOVETYPE_TOSS) - { - pev->movetype = MOVETYPE_FLY; - pev->flags &= ~FL_ONGROUND; - RecalculateWaterlevel(); - m_waterTime = gpGlobals->time + 2; // Recalc again soon, water may be rising - } - - if (m_Activity != m_IdealActivity) - { - SetActivity(m_IdealActivity); - } - float flInterval = StudioFrameAdvance(); - DispatchAnimEvents(flInterval); - -#if DEBUG_BEAMS - if (!m_pb) - m_pb = CBeam::BeamCreate("sprites/laserbeam.spr", 5); - if (!m_pt) - m_pt = CBeam::BeamCreate("sprites/laserbeam.spr", 5); - m_pb->PointsInit(pev->origin, pev->origin + gpGlobals->v_forward * LEECH_CHECK_DIST); - m_pt->PointsInit(pev->origin, pev->origin - gpGlobals->v_right * (pev->avelocity.y * 0.25)); - if (m_fPathBlocked) - { - float color = m_obstacle * 30; - if (m_obstacle == 1.0) - color = 0; - if (color > 255) - color = 255; - m_pb->SetColor(255, (int)color, (int)color); - } - else - m_pb->SetColor(255, 255, 0); - m_pt->SetColor(0, 0, 255); -#endif -} - -void CLeech::SwimThink(void) -{ - TraceResult tr; - float flLeftSide; - float flRightSide; - float targetSpeed; - float targetYaw = 0; - CBaseEntity *pTarget; - - if (FNullEnt(FIND_CLIENT_IN_PVS(edict()))) - { - pev->nextthink = gpGlobals->time + RANDOM_FLOAT(1, 1.5); - pev->velocity = g_vecZero; - return; - } - else - pev->nextthink = gpGlobals->time + 0.1; - - targetSpeed = LEECH_SWIM_SPEED; - - if (m_waterTime < gpGlobals->time) - RecalculateWaterlevel(); - - if (m_stateTime < gpGlobals->time) - SwitchLeechState(); - - ClearConditions(bits_COND_CAN_MELEE_ATTACK1); - switch (m_MonsterState) - { - case MONSTERSTATE_COMBAT: - pTarget = m_hEnemy; - if (!pTarget) - SwitchLeechState(); - else - { - // Chase the enemy's eyes - m_height = pTarget->pev->origin.z + pTarget->pev->view_ofs.z - 5; - // Clip to viable water area - if (m_height < m_bottom) - m_height = m_bottom; - else if (m_height > m_top) - m_height = m_top; - Vector location = pTarget->pev->origin - pev->origin; - location.z += (pTarget->pev->view_ofs.z); - if (location.Length() < 40) - SetConditions(bits_COND_CAN_MELEE_ATTACK1); - // Turn towards target ent - targetYaw = UTIL_VecToYaw(location); - - targetYaw = UTIL_AngleDiff(targetYaw, UTIL_AngleMod(pev->angles.y)); - - if (targetYaw < (-LEECH_TURN_RATE * 0.75)) - targetYaw = (-LEECH_TURN_RATE * 0.75); - else if (targetYaw > (LEECH_TURN_RATE * 0.75)) - targetYaw = (LEECH_TURN_RATE * 0.75); - else - targetSpeed *= 2; - } - - break; - - default: - if (m_zTime < gpGlobals->time) - { - float newHeight = RANDOM_FLOAT(m_bottom, m_top); - m_height = 0.5 * m_height + 0.5 * newHeight; - m_zTime = gpGlobals->time + RANDOM_FLOAT(1, 4); - } - if (RANDOM_LONG(0, 100) < 10) - targetYaw = RANDOM_LONG(-30, 30); - pTarget = NULL; - // oldorigin test - if ((pev->origin - pev->oldorigin).Length() < 1) - { - // If leech didn't move, there must be something blocking it, so try to turn - m_sideTime = 0; - } - - break; - } - - m_obstacle = ObstacleDistance(pTarget); - pev->oldorigin = pev->origin; - if (m_obstacle < 0.1) - m_obstacle = 0.1; - - // is the way ahead clear? - if (m_obstacle == 1.0) - { - // if the leech is turning, stop the trend. - if (m_flTurning != 0) - { - m_flTurning = 0; - } - - m_fPathBlocked = FALSE; - pev->speed = UTIL_Approach(targetSpeed, pev->speed, LEECH_SWIM_ACCEL * LEECH_FRAMETIME); - pev->velocity = gpGlobals->v_forward * pev->speed; - } - else - { - m_obstacle = 1.0 / m_obstacle; - // IF we get this far in the function, the leader's path is blocked! - m_fPathBlocked = TRUE; - - if (m_flTurning == 0) // something in the way and leech is not already turning to avoid - { - Vector vecTest; - // measure clearance on left and right to pick the best dir to turn - vecTest = pev->origin + (gpGlobals->v_right * LEECH_SIZEX) + (gpGlobals->v_forward * LEECH_CHECK_DIST); - UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); - flRightSide = tr.flFraction; - - vecTest = pev->origin + (gpGlobals->v_right * -LEECH_SIZEX) + (gpGlobals->v_forward * LEECH_CHECK_DIST); - UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); - flLeftSide = tr.flFraction; - - // turn left, right or random depending on clearance ratio - float delta = (flRightSide - flLeftSide); - if (delta > 0.1 || (delta > -0.1 && RANDOM_LONG(0, 100) < 50)) - m_flTurning = -LEECH_TURN_RATE; - else - m_flTurning = LEECH_TURN_RATE; - } - pev->speed = UTIL_Approach(-(LEECH_SWIM_SPEED * 0.5), pev->speed, LEECH_SWIM_DECEL * LEECH_FRAMETIME * m_obstacle); - pev->velocity = gpGlobals->v_forward * pev->speed; - } - pev->ideal_yaw = m_flTurning + targetYaw; - UpdateMotion(); -} - -void CLeech::Killed(entvars_t *pevAttacker, int iGib) -{ - Vector vecSplatDir; - TraceResult tr; - - //ALERT(at_aiconsole, "Leech: killed\n"); - // tell owner ( if any ) that we're dead.This is mostly for MonsterMaker functionality. - CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner); - if (pOwner) - pOwner->DeathNotice(pev); - - // When we hit the ground, play the "death_end" activity - if (pev->waterlevel) - { - pev->angles.z = 0; - pev->angles.x = 0; - pev->origin.z += 1; - pev->avelocity = g_vecZero; - if (RANDOM_LONG(0, 99) < 70) - pev->avelocity.y = RANDOM_LONG(-720, 720); - - pev->gravity = 0.02; - ClearBits(pev->flags, FL_ONGROUND); - SetActivity(ACT_DIESIMPLE); - } - else - SetActivity(ACT_DIEFORWARD); - - pev->movetype = MOVETYPE_TOSS; - pev->takedamage = DAMAGE_NO; - SetThink(DeadThink); -} diff --git a/dlls/Half-life/maprules.cpp b/dlls/Half-life/maprules.cpp deleted file mode 100644 index 66412082..00000000 --- a/dlls/Half-life/maprules.cpp +++ /dev/null @@ -1,888 +0,0 @@ -/*** -* -* Copyright (c) 1996-2002, 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -// ------------------------------------------- -// -// maprules.cpp -// -// This module contains entities for implementing/changing game -// rules dynamically within each map (.BSP) -// -// ------------------------------------------- - -#include "extdll.h" -#include "eiface.h" -#include "util.h" -#include "gamerules.h" -#include "maprules.h" -#include "cbase.h" -#include "player.h" - -class CRuleEntity : public CBaseEntity -{ -public: - void Spawn(void); - void KeyValue(KeyValueData *pkvd); - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void SetMaster(int iszMaster) { m_iszMaster = iszMaster; } - -protected: - BOOL CanFireForActivator(CBaseEntity *pActivator); - -private: - string_t m_iszMaster; -}; - -TYPEDESCRIPTION CRuleEntity::m_SaveData[] = - { - DEFINE_FIELD(CRuleEntity, m_iszMaster, FIELD_STRING), -}; - -IMPLEMENT_SAVERESTORE(CRuleEntity, CBaseEntity); - -void CRuleEntity::Spawn(void) -{ - pev->solid = SOLID_NOT; - pev->movetype = MOVETYPE_NONE; - pev->effects = EF_NODRAW; -} - -void CRuleEntity::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "master")) - { - SetMaster(ALLOC_STRING(pkvd->szValue)); - pkvd->fHandled = TRUE; - } - else - CBaseEntity::KeyValue(pkvd); -} - -BOOL CRuleEntity::CanFireForActivator(CBaseEntity *pActivator) -{ - if (m_iszMaster) - { - if (UTIL_IsMasterTriggered(m_iszMaster, pActivator)) - return TRUE; - else - return FALSE; - } - - return TRUE; -} - -// -// CRulePointEntity -- base class for all rule "point" entities (not brushes) -// -class CRulePointEntity : public CRuleEntity -{ -public: - void Spawn(void); -}; - -void CRulePointEntity::Spawn(void) -{ - CRuleEntity::Spawn(); - pev->frame = 0; - pev->model = 0; -} - -// -// CRuleBrushEntity -- base class for all rule "brush" entities (not brushes) -// Default behavior is to set up like a trigger, invisible, but keep the model for volume testing -// -class CRuleBrushEntity : public CRuleEntity -{ -public: - void Spawn(void); - -private: -}; - -void CRuleBrushEntity::Spawn(void) -{ - SET_MODEL(edict(), STRING(pev->model)); - CRuleEntity::Spawn(); -} - -// CGameScore / game_score -- award points to player / team -// Points +/- total -// Flag: Allow negative scores SF_SCORE_NEGATIVE -// Flag: Award points to team in teamplay SF_SCORE_TEAM - -#define SF_SCORE_NEGATIVE 0x0001 -#define SF_SCORE_TEAM 0x0002 - -class CGameScore : public CRulePointEntity -{ -public: - void Spawn(void); - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void KeyValue(KeyValueData *pkvd); - - inline int Points(void) { return pev->frags; } - inline BOOL AllowNegativeScore(void) { return pev->spawnflags & SF_SCORE_NEGATIVE; } - inline BOOL AwardToTeam(void) { return pev->spawnflags & SF_SCORE_TEAM; } - - inline void SetPoints(int points) { pev->frags = points; } - -private: -}; - -LINK_ENTITY_TO_CLASS(game_score, CGameScore); - -void CGameScore::Spawn(void) -{ - CRulePointEntity::Spawn(); -} - -void CGameScore::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "points")) - { - SetPoints(atoi(pkvd->szValue)); - pkvd->fHandled = TRUE; - } - else - CRulePointEntity::KeyValue(pkvd); -} - -void CGameScore::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!CanFireForActivator(pActivator)) - return; - - // Only players can use this - if (pActivator->IsPlayer()) - { - if (AwardToTeam()) - { - pActivator->AddPointsToTeam(Points(), AllowNegativeScore()); - } - else - { - pActivator->AddPoints(Points(), AllowNegativeScore()); - } - } -} - -// CGameEnd / game_end -- Ends the game in MP - -class CGameEnd : public CRulePointEntity -{ -public: - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - -private: -}; - -LINK_ENTITY_TO_CLASS(game_end, CGameEnd); - -void CGameEnd::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!CanFireForActivator(pActivator)) - return; - - g_pGameRules->EndMultiplayerGame(); -} - -// -// CGameText / game_text -- NON-Localized HUD Message (use env_message to display a titles.txt message) -// Flag: All players SF_ENVTEXT_ALLPLAYERS -// - -#define SF_ENVTEXT_ALLPLAYERS 0x0001 - -class CGameText : public CRulePointEntity -{ -public: - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void KeyValue(KeyValueData *pkvd); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - inline BOOL MessageToAll(void) { return (pev->spawnflags & SF_ENVTEXT_ALLPLAYERS); } - inline void MessageSet(const char *pMessage) { pev->message = ALLOC_STRING(pMessage); } - inline const char *MessageGet(void) { return STRING(pev->message); } - msstring ms_npcname; - bool sayasnpc; - -private: - hudtextparms_t m_textParms; -}; - -LINK_ENTITY_TO_CLASS(game_text, CGameText); -LINK_ENTITY_TO_CLASS(ms_text, CGameText); //Thothie AUG2007a - To get around FGD issues - -// Save parms as a block. Will break save/restore if the structure changes, but this entity didn't ship with Half-Life, so -// it can't impact saved Half-Life games. -TYPEDESCRIPTION CGameText::m_SaveData[] = - { - DEFINE_ARRAY(CGameText, m_textParms, FIELD_CHARACTER, sizeof(hudtextparms_t)), -}; - -IMPLEMENT_SAVERESTORE(CGameText, CRulePointEntity); - -void CGameText::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "channel")) - { - m_textParms.channel = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "x")) - { - m_textParms.x = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "y")) - { - m_textParms.y = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "effect")) - { - m_textParms.effect = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "color")) - { - int color[4]; - UTIL_StringToIntArray(color, 4, pkvd->szValue); - m_textParms.r1 = color[0]; - m_textParms.g1 = color[1]; - m_textParms.b1 = color[2]; - m_textParms.a1 = color[3]; - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "color2")) - { - int color[4]; - UTIL_StringToIntArray(color, 4, pkvd->szValue); - m_textParms.r2 = color[0]; - m_textParms.g2 = color[1]; - m_textParms.b2 = color[2]; - m_textParms.a2 = color[3]; - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "fadein")) - { - m_textParms.fadeinTime = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "fadeout")) - { - m_textParms.fadeoutTime = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "holdtime")) - { - m_textParms.holdTime = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "fxtime")) - { - m_textParms.fxTime = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "npcname")) - { - ms_npcname = pkvd->szValue; - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "sayasnpc")) - { - ms_sayasnpc = (atoi(pkvd->szValue) == 1) ? true : false; - pkvd->fHandled = TRUE; - } - else - CRulePointEntity::KeyValue(pkvd); -} - -void CGameText::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!CanFireForActivator(pActivator)) - return; - - if (MessageToAll()) - { - UTIL_HudMessageAll(m_textParms, MessageGet()); - } - else - { - if (pActivator->IsNetClient()) - { - UTIL_HudMessage(pActivator, m_textParms, MessageGet()); - } - } -} - -// -// CGameTeamMaster / game_team_master -- "Masters" like multisource, but based on the team of the activator -// Only allows mastered entity to fire if the team matches my team -// -// team index (pulled from server team list "mp_teamlist" -// Flag: Remove on Fire -// Flag: Any team until set? -- Any team can use this until the team is set (otherwise no teams can use it) -// - -#define SF_TEAMMASTER_FIREONCE 0x0001 -#define SF_TEAMMASTER_ANYTEAM 0x0002 - -class CGameTeamMaster : public CRulePointEntity -{ -public: - void KeyValue(KeyValueData *pkvd); - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - int ObjectCaps(void) { return CRulePointEntity::ObjectCaps() | FCAP_MASTER; } - - BOOL IsTriggered(CBaseEntity *pActivator); - const char *TeamID(void); - inline BOOL RemoveOnFire(void) { return (pev->spawnflags & SF_TEAMMASTER_FIREONCE) ? TRUE : FALSE; } - inline BOOL AnyTeam(void) { return (pev->spawnflags & SF_TEAMMASTER_ANYTEAM) ? TRUE : FALSE; } - -private: - BOOL TeamMatch(CBaseEntity *pActivator); - - int m_teamIndex; - USE_TYPE triggerType; -}; - -LINK_ENTITY_TO_CLASS(game_team_master, CGameTeamMaster); - -void CGameTeamMaster::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "teamindex")) - { - m_teamIndex = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "triggerstate")) - { - int type = atoi(pkvd->szValue); - switch (type) - { - case 0: - triggerType = USE_OFF; - break; - case 2: - triggerType = USE_TOGGLE; - break; - default: - triggerType = USE_ON; - break; - } - pkvd->fHandled = TRUE; - } - else - CRulePointEntity::KeyValue(pkvd); -} - -void CGameTeamMaster::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!CanFireForActivator(pActivator)) - return; - - if (useType == USE_SET) - { - if (value < 0) - { - m_teamIndex = -1; - } - else - { - m_teamIndex = g_pGameRules->GetTeamIndex(pActivator->TeamID()); - } - return; - } - - if (TeamMatch(pActivator)) - { - SUB_UseTargets(pActivator, triggerType, value); - if (RemoveOnFire()) - UTIL_Remove(this); - } -} - -BOOL CGameTeamMaster::IsTriggered(CBaseEntity *pActivator) -{ - return TeamMatch(pActivator); -} - -const char *CGameTeamMaster::TeamID(void) -{ - if (m_teamIndex < 0) // Currently set to "no team" - return ""; - - return g_pGameRules->GetIndexedTeamName(m_teamIndex); // UNDONE: Fill this in with the team from the "teamlist" -} - -BOOL CGameTeamMaster::TeamMatch(CBaseEntity *pActivator) -{ - if (m_teamIndex < 0 && AnyTeam()) - return TRUE; - - if (!pActivator) - return FALSE; - - return UTIL_TeamsMatch(pActivator->TeamID(), TeamID()); -} - -// -// CGameTeamSet / game_team_set -- Changes the team of the entity it targets to the activator's team -// Flag: Fire once -// Flag: Clear team -- Sets the team to "NONE" instead of activator - -#define SF_TEAMSET_FIREONCE 0x0001 -#define SF_TEAMSET_CLEARTEAM 0x0002 - -class CGameTeamSet : public CRulePointEntity -{ -public: - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - inline BOOL RemoveOnFire(void) { return (pev->spawnflags & SF_TEAMSET_FIREONCE) ? TRUE : FALSE; } - inline BOOL ShouldClearTeam(void) { return (pev->spawnflags & SF_TEAMSET_CLEARTEAM) ? TRUE : FALSE; } - -private: -}; - -LINK_ENTITY_TO_CLASS(game_team_set, CGameTeamSet); - -void CGameTeamSet::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!CanFireForActivator(pActivator)) - return; - - if (ShouldClearTeam()) - { - SUB_UseTargets(pActivator, USE_SET, -1); - } - else - { - SUB_UseTargets(pActivator, USE_SET, 0); - } - - if (RemoveOnFire()) - { - UTIL_Remove(this); - } -} - -// -// CGamePlayerZone / game_player_zone -- players in the zone fire my target when I'm fired -// -// Needs master? -class CGamePlayerZone : public CRuleBrushEntity -{ -public: - void KeyValue(KeyValueData *pkvd); - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - -private: - string_t m_iszInTarget; - string_t m_iszOutTarget; - string_t m_iszInCount; - string_t m_iszOutCount; -}; - -LINK_ENTITY_TO_CLASS(game_zone_player, CGamePlayerZone); -TYPEDESCRIPTION CGamePlayerZone::m_SaveData[] = - { - DEFINE_FIELD(CGamePlayerZone, m_iszInTarget, FIELD_STRING), - DEFINE_FIELD(CGamePlayerZone, m_iszOutTarget, FIELD_STRING), - DEFINE_FIELD(CGamePlayerZone, m_iszInCount, FIELD_STRING), - DEFINE_FIELD(CGamePlayerZone, m_iszOutCount, FIELD_STRING), -}; - -IMPLEMENT_SAVERESTORE(CGamePlayerZone, CRuleBrushEntity); - -void CGamePlayerZone::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "intarget")) - { - m_iszInTarget = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "outtarget")) - { - m_iszOutTarget = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "incount")) - { - m_iszInCount = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "outcount")) - { - m_iszOutCount = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else - CRuleBrushEntity::KeyValue(pkvd); -} - -void CGamePlayerZone::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - int playersInCount = 0; - int playersOutCount = 0; - - if (!CanFireForActivator(pActivator)) - return; - - CBaseEntity *pPlayer = NULL; - - for (int i = 1; i <= gpGlobals->maxClients; i++) - { - pPlayer = UTIL_PlayerByIndex(i); - if (pPlayer) - { - TraceResult trace; - int hullNumber; - - hullNumber = human_hull; - if (pPlayer->pev->flags & FL_DUCKING) - { - hullNumber = head_hull; - } - - UTIL_TraceModel(pPlayer->pev->origin, pPlayer->pev->origin, hullNumber, edict(), &trace); - - if (trace.fStartSolid) - { - playersInCount++; - if (m_iszInTarget) - { - FireTargets(STRING(m_iszInTarget), pPlayer, pActivator, useType, value); - } - } - else - { - playersOutCount++; - if (m_iszOutTarget) - { - FireTargets(STRING(m_iszOutTarget), pPlayer, pActivator, useType, value); - } - } - } - } - - if (m_iszInCount) - { - FireTargets(STRING(m_iszInCount), pActivator, this, USE_SET, playersInCount); - } - - if (m_iszOutCount) - { - FireTargets(STRING(m_iszOutCount), pActivator, this, USE_SET, playersOutCount); - } -} - -// -// CGamePlayerHurt / game_player_hurt -- Damages the player who fires it -// Flag: Fire once - -#define SF_PKILL_FIREONCE 0x0001 -class CGamePlayerHurt : public CRulePointEntity -{ -public: - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - inline BOOL RemoveOnFire(void) { return (pev->spawnflags & SF_PKILL_FIREONCE) ? TRUE : FALSE; } - -private: -}; - -LINK_ENTITY_TO_CLASS(game_player_hurt, CGamePlayerHurt); - -void CGamePlayerHurt::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!CanFireForActivator(pActivator)) - return; - - if (pActivator->IsPlayer()) - { - if (pev->dmg < 0) - pActivator->TakeHealth(-pev->dmg, DMG_GENERIC); - else - pActivator->TakeDamage(pev, pev, pev->dmg, DMG_GENERIC); - } - - SUB_UseTargets(pActivator, useType, value); - - if (RemoveOnFire()) - { - UTIL_Remove(this); - } -} - -// -// CGameCounter / game_counter -- Counts events and fires target -// Flag: Fire once -// Flag: Reset on Fire - -#define SF_GAMECOUNT_FIREONCE 0x0001 -#define SF_GAMECOUNT_RESET 0x0002 - -class CGameCounter : public CRulePointEntity -{ -public: - void Spawn(void); - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - inline BOOL RemoveOnFire(void) { return (pev->spawnflags & SF_GAMECOUNT_FIREONCE) ? TRUE : FALSE; } - inline BOOL ResetOnFire(void) { return (pev->spawnflags & SF_GAMECOUNT_RESET) ? TRUE : FALSE; } - - inline void CountUp(void) { pev->frags++; } - inline void CountDown(void) { pev->frags--; } - inline void ResetCount(void) { pev->frags = pev->dmg; } - inline int CountValue(void) { return pev->frags; } - inline int LimitValue(void) { return pev->health; } - - inline BOOL HitLimit(void) { return CountValue() == LimitValue(); } - -private: - inline void SetCountValue(int value) { pev->frags = value; } - inline void SetInitialValue(int value) { pev->dmg = value; } -}; - -LINK_ENTITY_TO_CLASS(game_counter, CGameCounter); - -void CGameCounter::Spawn(void) -{ - // Save off the initial count - SetInitialValue(CountValue()); - CRulePointEntity::Spawn(); -} - -void CGameCounter::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!CanFireForActivator(pActivator)) - return; - - switch (useType) - { - case USE_ON: - case USE_TOGGLE: - CountUp(); - break; - - case USE_OFF: - CountDown(); - break; - - case USE_SET: - SetCountValue((int)value); - break; - } - - if (HitLimit()) - { - SUB_UseTargets(pActivator, USE_TOGGLE, 0); - if (RemoveOnFire()) - { - UTIL_Remove(this); - } - - if (ResetOnFire()) - { - ResetCount(); - } - } -} - -// -// CGameCounterSet / game_counter_set -- Sets the counter's value -// Flag: Fire once - -#define SF_GAMECOUNTSET_FIREONCE 0x0001 - -class CGameCounterSet : public CRulePointEntity -{ -public: - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - inline BOOL RemoveOnFire(void) { return (pev->spawnflags & SF_GAMECOUNTSET_FIREONCE) ? TRUE : FALSE; } - -private: -}; - -LINK_ENTITY_TO_CLASS(game_counter_set, CGameCounterSet); - -void CGameCounterSet::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!CanFireForActivator(pActivator)) - return; - - SUB_UseTargets(pActivator, USE_SET, pev->frags); - - if (RemoveOnFire()) - { - UTIL_Remove(this); - } -} - -// -// CGamePlayerEquip / game_playerequip -- Sets the default player equipment -// Flag: USE Only - -#define SF_PLAYEREQUIP_USEONLY 0x0001 -#define MAX_EQUIP 32 - -class CGamePlayerEquip : public CRulePointEntity -{ -public: - void KeyValue(KeyValueData *pkvd); - void Touch(CBaseEntity *pOther); - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - - inline BOOL UseOnly(void) { return (pev->spawnflags & SF_PLAYEREQUIP_USEONLY) ? TRUE : FALSE; } - -private: - void EquipPlayer(CBaseEntity *pPlayer); - - string_t m_weaponNames[MAX_EQUIP]; - int m_weaponCount[MAX_EQUIP]; -}; - -LINK_ENTITY_TO_CLASS(game_player_equip, CGamePlayerEquip); - -void CGamePlayerEquip::KeyValue(KeyValueData *pkvd) -{ - CRulePointEntity::KeyValue(pkvd); - - if (!pkvd->fHandled) - { - for (int i = 0; i < MAX_EQUIP; i++) - { - if (!m_weaponNames[i]) - { - char tmp[128]; - - UTIL_StripToken(pkvd->szKeyName, tmp); - - m_weaponNames[i] = ALLOC_STRING(tmp); - m_weaponCount[i] = atoi(pkvd->szValue); - m_weaponCount[i] = max(1, m_weaponCount[i]); - pkvd->fHandled = TRUE; - break; - } - } - } -} - -void CGamePlayerEquip::Touch(CBaseEntity *pOther) -{ - if (!CanFireForActivator(pOther)) - return; - - if (UseOnly()) - return; - - EquipPlayer(pOther); -} - -void CGamePlayerEquip::EquipPlayer(CBaseEntity *pEntity) -{ - CBasePlayer *pPlayer = NULL; - - if (pEntity->IsPlayer()) - { - pPlayer = (CBasePlayer *)pEntity; - } - - if (!pPlayer) - return; - - for (int i = 0; i < MAX_EQUIP; i++) - { - if (!m_weaponNames[i]) - break; - for (int j = 0; j < m_weaponCount[i]; j++) - { - pPlayer->GiveNamedItem(STRING(m_weaponNames[i])); - } - } -} - -void CGamePlayerEquip::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - EquipPlayer(pActivator); -} - -// -// CGamePlayerTeam / game_player_team -- Changes the team of the player who fired it -// Flag: Fire once -// Flag: Kill Player -// Flag: Gib Player - -#define SF_PTEAM_FIREONCE 0x0001 -#define SF_PTEAM_KILL 0x0002 -#define SF_PTEAM_GIB 0x0004 - -class CGamePlayerTeam : public CRulePointEntity -{ -public: - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - -private: - inline BOOL RemoveOnFire(void) { return (pev->spawnflags & SF_PTEAM_FIREONCE) ? TRUE : FALSE; } - inline BOOL ShouldKillPlayer(void) { return (pev->spawnflags & SF_PTEAM_KILL) ? TRUE : FALSE; } - inline BOOL ShouldGibPlayer(void) { return (pev->spawnflags & SF_PTEAM_GIB) ? TRUE : FALSE; } - - const char *TargetTeamName(const char *pszTargetName); -}; - -LINK_ENTITY_TO_CLASS(game_player_team, CGamePlayerTeam); - -const char *CGamePlayerTeam::TargetTeamName(const char *pszTargetName) -{ - CBaseEntity *pTeamEntity = NULL; - - while ((pTeamEntity = UTIL_FindEntityByTargetname(pTeamEntity, pszTargetName)) != NULL) - { - if (FClassnameIs(pTeamEntity->pev, "game_team_master")) - return pTeamEntity->TeamID(); - } - - return NULL; -} - -void CGamePlayerTeam::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!CanFireForActivator(pActivator)) - return; - - if (pActivator->IsPlayer()) - { - const char *pszTargetTeam = TargetTeamName(STRING(pev->target)); - if (pszTargetTeam) - { - CBasePlayer *pPlayer = (CBasePlayer *)pActivator; - g_pGameRules->ChangePlayerTeam(pPlayer, pszTargetTeam, ShouldKillPlayer(), ShouldGibPlayer()); - } - } - - if (RemoveOnFire()) - { - UTIL_Remove(this); - } -} diff --git a/dlls/Half-life/maprules.h b/dlls/Half-life/maprules.h deleted file mode 100644 index 62aa9828..00000000 --- a/dlls/Half-life/maprules.h +++ /dev/null @@ -1,19 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -#ifndef MAPRULES_H -#define MAPRULES_H - -#endif // MAPRULES_H diff --git a/dlls/Half-life/monstermaker.cpp b/dlls/Half-life/monstermaker.cpp deleted file mode 100644 index 9aef0fcb..00000000 --- a/dlls/Half-life/monstermaker.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -//========================================================= -// Monster Maker - this is an entity that creates monsters -// in the game. -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "saverestore.h" - -// Monstermaker spawnflags -#define SF_MONSTERMAKER_START_ON 1 // start active ( if has targetname ) -#define SF_MONSTERMAKER_CYCLIC 4 // drop one monster every time fired. -#define SF_MONSTERMAKER_MONSTERCLIP 8 // Children are blocked by monsterclip - -//========================================================= -// MonsterMaker - this ent creates monsters during the game. -//========================================================= -class CMonsterMaker : public CBaseMonster -{ -public: - void Spawn( void ); - void Precache( void ); - void KeyValue( KeyValueData* pkvd); - void EXPORT ToggleUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void EXPORT CyclicUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void EXPORT MakerThink ( void ); - void DeathNotice ( entvars_t *pevChild );// monster maker children use this to tell the monster maker that they have died. - void MakeMonster( void ); - - virtual int Save( CSave &save ); - virtual int Restore( CRestore &restore ); - - static TYPEDESCRIPTION m_SaveData[]; - - string_t m_iszMonsterClassname;// classname of the monster(s) that will be created. - - int m_cNumMonsters;// max number of monsters this ent can create - - - int m_cLiveChildren;// how many monsters made by this monster maker that are currently alive - int m_iMaxLiveChildren;// max number of monsters that this maker may have out at one time. - - float m_flGround; // z coord of the ground under me, used to make sure no monsters are under the maker when it drops a new child - - BOOL m_fActive; - BOOL m_fFadeChildren;// should we make the children fadeout? -}; - -LINK_ENTITY_TO_CLASS( monstermaker, CMonsterMaker ); - -TYPEDESCRIPTION CMonsterMaker::m_SaveData[] = -{ - DEFINE_FIELD( CMonsterMaker, m_iszMonsterClassname, FIELD_STRING ), - DEFINE_FIELD( CMonsterMaker, m_cNumMonsters, FIELD_INTEGER ), - DEFINE_FIELD( CMonsterMaker, m_cLiveChildren, FIELD_INTEGER ), - DEFINE_FIELD( CMonsterMaker, m_flGround, FIELD_FLOAT ), - DEFINE_FIELD( CMonsterMaker, m_iMaxLiveChildren, FIELD_INTEGER ), - DEFINE_FIELD( CMonsterMaker, m_fActive, FIELD_BOOLEAN ), - DEFINE_FIELD( CMonsterMaker, m_fFadeChildren, FIELD_BOOLEAN ), -}; - - -IMPLEMENT_SAVERESTORE( CMonsterMaker, CBaseMonster ); - -void CMonsterMaker :: KeyValue( KeyValueData *pkvd ) -{ - - if ( FStrEq(pkvd->szKeyName, "monstercount") ) - { - m_cNumMonsters = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if ( FStrEq(pkvd->szKeyName, "m_imaxlivechildren") ) - { - m_iMaxLiveChildren = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if ( FStrEq(pkvd->szKeyName, "monstertype") ) - { - m_iszMonsterClassname = ALLOC_STRING( pkvd->szValue ); - pkvd->fHandled = TRUE; - } - else - CBaseMonster::KeyValue( pkvd ); -} - - -void CMonsterMaker :: Spawn( ) -{ - pev->solid = SOLID_NOT; - - m_cLiveChildren = 0; - Precache(); - if ( !FStringNull ( pev->targetname ) ) - { - if ( pev->spawnflags & SF_MONSTERMAKER_CYCLIC ) - { - SetUse ( CyclicUse );// drop one monster each time we fire - } - else - { - SetUse ( ToggleUse );// so can be turned on/off - } - - if ( FBitSet ( pev->spawnflags, SF_MONSTERMAKER_START_ON ) ) - {// start making monsters as soon as monstermaker spawns - m_fActive = TRUE; - SetThink ( MakerThink ); - } - else - {// wait to be activated. - m_fActive = FALSE; - SetThink ( SUB_DoNothing ); - } - } - else - {// no targetname, just start. - pev->nextthink = gpGlobals->time + m_flDelay; - m_fActive = TRUE; - SetThink ( MakerThink ); - } - - if ( m_cNumMonsters == 1 ) - { - m_fFadeChildren = FALSE; - } - else - { - m_fFadeChildren = TRUE; - } - - m_flGround = 0; -} - -void CMonsterMaker :: Precache( void ) -{ - CBaseMonster::Precache(); - - UTIL_PrecacheOther( STRING( m_iszMonsterClassname ) ); -} - -//========================================================= -// MakeMonster- this is the code that drops the monster -//========================================================= -void CMonsterMaker::MakeMonster( void ) -{ - edict_t *pent; - entvars_t *pevCreate; - - if ( m_iMaxLiveChildren > 0 && m_cLiveChildren >= m_iMaxLiveChildren ) - {// not allowed to make a new one yet. Too many live ones out right now. - return; - } - - if ( !m_flGround ) - { - // set altitude. Now that I'm activated, any breakables, etc should be out from under me. - TraceResult tr; - - UTIL_TraceLine ( pev->origin, pev->origin - Vector ( 0, 0, 2048 ), ignore_monsters, ENT(pev), &tr ); - m_flGround = tr.vecEndPos.z; - } - - 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; - - CBaseEntity *pList[2]; - int count = UTIL_EntitiesInBox( pList, 2, mins, maxs, FL_CLIENT|FL_MONSTER ); - if ( count ) - { - // don't build a stack of monsters! - return; - } - - pent = CREATE_NAMED_ENTITY( m_iszMonsterClassname ); - - if ( FNullEnt( pent ) ) - { - ALERT ( at_console, "NULL Ent in MonsterMaker!\n" ); - return; - } - - // If I have a target, fire! - if ( !FStringNull ( pev->target ) ) - { - // delay already overloaded for this entity, so can't call SUB_UseTargets() - FireTargets( STRING(pev->target), this, this, USE_TOGGLE, 0 ); - } - - pevCreate = VARS( pent ); - pevCreate->origin = pev->origin; - pevCreate->angles = pev->angles; - SetBits( pevCreate->spawnflags, SF_MONSTER_FALL_TO_GROUND ); - - // Children hit monsterclip brushes - if ( pev->spawnflags & SF_MONSTERMAKER_MONSTERCLIP ) - SetBits( pevCreate->spawnflags, SF_MONSTER_HITMONSTERCLIP ); - - DispatchSpawn( ENT( pevCreate ) ); - pevCreate->owner = edict(); - - if ( !FStringNull( pev->netname ) ) - { - // if I have a netname (overloaded), give the child monster that name as a targetname - pevCreate->targetname = pev->netname; - } - - m_cLiveChildren++;// count this monster - m_cNumMonsters--; - - if ( m_cNumMonsters == 0 ) - { - // Disable this forever. Don't kill it because it still gets death notices - SetThink( NULL ); - SetUse( NULL ); - } -} - -//========================================================= -// CyclicUse - drops one monster from the monstermaker -// each time we call this. -//========================================================= -void CMonsterMaker::CyclicUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - MakeMonster(); -} - -//========================================================= -// ToggleUse - activates/deactivates the monster maker -//========================================================= -void CMonsterMaker :: ToggleUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( !ShouldToggle( useType, m_fActive ) ) - return; - - if ( m_fActive ) - { - m_fActive = FALSE; - SetThink ( NULL ); - } - else - { - m_fActive = TRUE; - SetThink ( MakerThink ); - } - - pev->nextthink = gpGlobals->time; -} - -//========================================================= -// MakerThink - creates a new monster every so often -//========================================================= -void CMonsterMaker :: MakerThink ( void ) -{ - pev->nextthink = gpGlobals->time + m_flDelay; - - MakeMonster(); -} - - -//========================================================= -//========================================================= -void CMonsterMaker :: DeathNotice ( entvars_t *pevChild ) -{ - // ok, we've gotten the deathnotice from our child, now clear out its owner if we don't want it to fade. - m_cLiveChildren--; - - if ( !m_fFadeChildren ) - { - pevChild->owner = NULL; - } -} - - diff --git a/dlls/Half-life/mortar.cpp b/dlls/Half-life/mortar.cpp deleted file mode 100644 index b09890e7..00000000 --- a/dlls/Half-life/mortar.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -/* - -===== mortar.cpp ======================================================== - - the "LaBuznik" mortar device - -*/ - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "saverestore.h" -#include "Weapons.h" -#include "decals.h" -#include "soundent.h" - -class CFuncMortarField : public CBaseToggle -{ -public: - void Spawn(void); - void Precache(void); - void KeyValue(KeyValueData *pkvd); - - // Bmodels don't go across transitions - virtual int ObjectCaps(void) { return CBaseToggle ::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - - static TYPEDESCRIPTION m_SaveData[]; - - void EXPORT FieldUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - - int m_iszXController; - int m_iszYController; - float m_flSpread; - float m_flDelay; - int m_iCount; - int m_fControl; -}; - -LINK_ENTITY_TO_CLASS(func_mortar_field, CFuncMortarField); - -TYPEDESCRIPTION CFuncMortarField::m_SaveData[] = - { - DEFINE_FIELD(CFuncMortarField, m_iszXController, FIELD_STRING), - DEFINE_FIELD(CFuncMortarField, m_iszYController, FIELD_STRING), - DEFINE_FIELD(CFuncMortarField, m_flSpread, FIELD_FLOAT), - DEFINE_FIELD(CFuncMortarField, m_flDelay, FIELD_FLOAT), - DEFINE_FIELD(CFuncMortarField, m_iCount, FIELD_INTEGER), - DEFINE_FIELD(CFuncMortarField, m_fControl, FIELD_INTEGER), -}; - -IMPLEMENT_SAVERESTORE(CFuncMortarField, CBaseToggle); - -void CFuncMortarField ::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "m_iszXController")) - { - m_iszXController = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "m_iszYController")) - { - m_iszYController = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "m_flSpread")) - { - m_flSpread = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "m_fControl")) - { - m_fControl = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "m_iCount")) - { - m_iCount = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } -} - -// Drop bombs from above -void CFuncMortarField ::Spawn(void) -{ - pev->solid = SOLID_NOT; - SET_MODEL(ENT(pev), STRING(pev->model)); // set size and link into world - pev->movetype = MOVETYPE_NONE; - SetBits(pev->effects, EF_NODRAW); - SetUse(FieldUse); - Precache(); -} - -void CFuncMortarField ::Precache(void) -{ - PRECACHE_SOUND("weapons/mortar.wav"); - PRECACHE_SOUND("weapons/mortarhit.wav"); - PRECACHE_MODEL("sprites/lgtning.spr"); -} - -// If connected to a table, then use the table controllers, else hit where the trigger is. -void CFuncMortarField ::FieldUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - Vector vecStart; - - vecStart.x = RANDOM_FLOAT(pev->mins.x, pev->maxs.x); - vecStart.y = RANDOM_FLOAT(pev->mins.y, pev->maxs.y); - vecStart.z = pev->maxs.z; - - switch (m_fControl) - { - case 0: // random - break; - case 1: // Trigger Activator - if (pActivator != NULL) - { - vecStart.x = pActivator->pev->origin.x; - vecStart.y = pActivator->pev->origin.y; - } - break; - case 2: // table - { - CBaseEntity *pController; - - if (!FStringNull(m_iszXController)) - { - pController = UTIL_FindEntityByTargetname(NULL, STRING(m_iszXController)); - if (pController != NULL) - { - vecStart.x = pev->mins.x + pController->pev->ideal_yaw * (pev->size.x); - } - } - if (!FStringNull(m_iszYController)) - { - pController = UTIL_FindEntityByTargetname(NULL, STRING(m_iszYController)); - if (pController != NULL) - { - vecStart.y = pev->mins.y + pController->pev->ideal_yaw * (pev->size.y); - } - } - } - break; - } - - int pitch = RANDOM_LONG(95, 124); - - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "weapons/mortar.wav", 1.0, ATTN_NONE, 0, pitch); - - float t = 2.5; - for (int i = 0; i < m_iCount; i++) - { - Vector vecSpot = vecStart; - vecSpot.x += RANDOM_FLOAT(-m_flSpread, m_flSpread); - vecSpot.y += RANDOM_FLOAT(-m_flSpread, m_flSpread); - - TraceResult tr; - UTIL_TraceLine(vecSpot, vecSpot + Vector(0, 0, -1) * 4096, ignore_monsters, ENT(pev), &tr); - - edict_t *pentOwner = NULL; - if (pActivator) - pentOwner = pActivator->edict(); - - CBaseEntity *pMortar = Create("monster_mortar", tr.vecEndPos, Vector(0, 0, 0), pentOwner); - pMortar->pev->nextthink = gpGlobals->time + t; - t += RANDOM_FLOAT(0.2, 0.5); - - if (i == 0) - CSoundEnt::InsertSound(bits_SOUND_DANGER, tr.vecEndPos, 400, 0.3); - } -} - -class CMortar : public CGrenade -{ -public: - void Spawn(void); - void Precache(void); - - void EXPORT MortarExplode(void); - - int m_spriteTexture; -}; - -LINK_ENTITY_TO_CLASS(monster_mortar, CMortar); - -void CMortar::Spawn() -{ - pev->movetype = MOVETYPE_NONE; - pev->solid = SOLID_NOT; - - pev->dmg = 200; - - SetThink(MortarExplode); - pev->nextthink = 0; - - Precache(); -} - -void CMortar::Precache() -{ - m_spriteTexture = PRECACHE_MODEL("sprites/lgtning.spr"); -} - -void CMortar::MortarExplode(void) -{ -#if 1 - // mortar beam - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_BEAMPOINTS); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z + 1024); - WRITE_SHORT(m_spriteTexture); - WRITE_BYTE(0); // framerate - WRITE_BYTE(0); // framerate - WRITE_BYTE(1); // life - WRITE_BYTE(40); // width - WRITE_BYTE(0); // noise - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(160); // r, g, b - WRITE_BYTE(100); // r, g, b - WRITE_BYTE(128); // brightness - WRITE_BYTE(0); // speed - MESSAGE_END(); -#endif - -#if 0 - // blast circle - MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); - WRITE_BYTE( TE_BEAMTORUS); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z + 32); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z + 32 + pev->dmg * 2 / .2); // reach damage radius over .3 seconds - WRITE_SHORT(m_spriteTexture ); - WRITE_BYTE( 0 ); // startframe - WRITE_BYTE( 0 ); // framerate - WRITE_BYTE( 2 ); // life - WRITE_BYTE( 12 ); // width - WRITE_BYTE( 0 ); // noise - WRITE_BYTE( 255 ); // r, g, b - WRITE_BYTE( 160 ); // r, g, b - WRITE_BYTE( 100 ); // r, g, b - WRITE_BYTE( 255 ); // brightness - WRITE_BYTE( 0 ); // speed - MESSAGE_END(); -#endif - - TraceResult tr; - UTIL_TraceLine(pev->origin + Vector(0, 0, 1024), pev->origin - Vector(0, 0, 1024), dont_ignore_monsters, ENT(pev), &tr); - - Explode(&tr, DMG_BLAST | DMG_MORTAR); - UTIL_ScreenShake(tr.vecEndPos, 25.0, 150.0, 1.0, 750); - -#if 0 - int pitch = RANDOM_LONG(95,124); - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "weapons/mortarhit.wav", 1.0, 0.55, 0, pitch); - - // ForceSound( SNDRADIUS_MP5, bits_SOUND_COMBAT ); - - // ExplodeModel( pev->origin, 400, g_sModelIndexShrapnel, 30 ); - - RadiusDamage ( pev, VARS(pev->owner), pev->dmg, CLASS_NONE, DMG_BLAST ); - - /* - if ( RANDOM_FLOAT ( 0 , 1 ) < 0.5 ) - { - UTIL_DecalTrace( pTrace, DECAL_SCORCH1 ); - } - else - { - UTIL_DecalTrace( pTrace, DECAL_SCORCH2 ); - } - */ - - SetThink( SUB_Remove ); - pev->nextthink = gpGlobals->time + 0.1; -#endif -} - -#if 0 -void CMortar::ShootTimed( EVARS *pevOwner, Vector vecStart, float time ) -{ - CMortar *pMortar = GetClassPtr( (CMortar *)NULL ); - pMortar->Spawn(); - - TraceResult tr; - UTIL_TraceLine( vecStart, vecStart + Vector( 0, 0, -1 ) * 4096, ignore_monsters, ENT(pMortar->pev), &tr ); - - pMortar->pev->nextthink = gpGlobals->time + time; - - UTIL_SetOrigin( pMortar->pev, tr.vecEndPos ); -} -#endif \ No newline at end of file diff --git a/dlls/Half-life/mp5.cpp b/dlls/Half-life/mp5.cpp deleted file mode 100644 index 24a0a8c7..00000000 --- a/dlls/Half-life/mp5.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "soundent.h" -#include "gamerules.h" - -enum mp5_e -{ - MP5_LONGIDLE = 0, - MP5_IDLE1, - MP5_LAUNCH, - MP5_RELOAD, - MP5_DEPLOY, - MP5_FIRE1, - MP5_FIRE2, - MP5_FIRE3, -}; - -class CMP5 : public CBasePlayerWeapon -{ -public: - void Spawn(void); - void Precache(void); - int iItemSlot(void) { return 3; } - int GetItemInfo(ItemInfo *p); - int AddToPlayer(CBasePlayer *pPlayer); - - void PrimaryAttack(void); - void SecondaryAttack(void); - int SecondaryAmmoIndex(void); - BOOL Deploy(void); - void Reload(void); - void WeaponIdle(void); - float m_flNextAnimTime; - int m_iShell; - -private: - unsigned short m_usMP5; -}; -LINK_ENTITY_TO_CLASS(weapon_mp5, CMP5); -LINK_ENTITY_TO_CLASS(weapon_9mmAR, CMP5); - -//========================================================= -//========================================================= -int CMP5::SecondaryAmmoIndex(void) -{ - return m_iSecondaryAmmoType; -} - -void CMP5::Spawn() -{ - pev->classname = MAKE_STRING("weapon_9mmAR"); // hack to allow for old names - Precache(); - SET_MODEL(ENT(pev), "models/w_9mmAR.mdl"); - m_iId = WEAPON_MP5; - - m_iDefaultAmmo = MP5_DEFAULT_GIVE; - - FallInit(); // get ready to fall down. -} - -void CMP5::Precache(void) -{ - PRECACHE_MODEL("models/v_9mmAR.mdl"); - PRECACHE_MODEL("models/w_9mmAR.mdl"); - PRECACHE_MODEL("models/p_9mmAR.mdl"); - - m_iShell = PRECACHE_MODEL("models/shell.mdl"); // brass shellTE_MODEL - - PRECACHE_MODEL("models/grenade.mdl"); // grenade - - PRECACHE_MODEL("models/w_9mmARclip.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - - PRECACHE_SOUND("items/clipinsert1.wav"); - PRECACHE_SOUND("items/cliprelease1.wav"); - // PRECACHE_SOUND("items/guncock1.wav"); - - PRECACHE_SOUND("weapons/hks1.wav"); // H to the K - PRECACHE_SOUND("weapons/hks2.wav"); // H to the K - PRECACHE_SOUND("weapons/hks3.wav"); // H to the K - - PRECACHE_SOUND("weapons/glauncher.wav"); - PRECACHE_SOUND("weapons/glauncher2.wav"); - - PRECACHE_SOUND("weapons/357_cock1.wav"); - - m_usMP5 = PRECACHE_EVENT(1, "events/mp5.sc"); -} - -int CMP5::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "9mm"; - p->iMaxAmmo1 = _9MM_MAX_CARRY; - p->pszAmmo2 = "ARgrenades"; - p->iMaxAmmo2 = M203_GRENADE_MAX_CARRY; - p->iMaxClip = MP5_MAX_CLIP; - p->iSlot = 2; - p->iPosition = 0; - p->iFlags = 0; - p->iId = m_iId = WEAPON_MP5; - p->iWeight = MP5_WEIGHT; - - return 1; -} - -int CMP5::AddToPlayer(CBasePlayer *pPlayer) -{ - if (CBasePlayerWeapon::AddToPlayer(pPlayer)) - { - MESSAGE_BEGIN(MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev); - WRITE_BYTE(m_iId); - MESSAGE_END(); - return TRUE; - } - return FALSE; -} - -BOOL CMP5::Deploy() -{ - return DefaultDeploy("models/v_9mmAR.mdl", "models/p_9mmAR.mdl", MP5_DEPLOY, "mp5"); -} - -void CMP5::PrimaryAttack() -{ - // don't fire underwater - if (m_pPlayer->pev->waterlevel == 3) - { - PlayEmptySound(); - m_flNextPrimaryAttack = gpGlobals->time + 0.15; - return; - } - - if (m_iClip <= 0) - { - PlayEmptySound(); - m_flNextPrimaryAttack = gpGlobals->time + 0.15; - return; - } - - PLAYBACK_EVENT(0, m_pPlayer->edict(), m_usMP5); - - m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME; - m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; - - m_iClip--; - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - Vector vecSrc = m_pPlayer->GetGunPosition(); - Vector vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES); - - if (g_pGameRules->IsDeathmatch()) - { - // optimized multiplayer. Widened to make it easier to hit a moving player - m_pPlayer->FireBullets(1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, 8192, BULLET_PLAYER_MP5, 2); - } - else - { - // single player spread - m_pPlayer->FireBullets(1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_MP5, 2); - } - - if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - // HEV suit - indicate out of ammo condition - m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - - m_flNextPrimaryAttack = m_flNextPrimaryAttack + 0.1; - if (m_flNextPrimaryAttack < gpGlobals->time) - m_flNextPrimaryAttack = gpGlobals->time + 0.1; - - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); -} - -void CMP5::SecondaryAttack(void) -{ - // don't fire underwater - if (m_pPlayer->pev->waterlevel == 3) - { - PlayEmptySound(); - m_flNextPrimaryAttack = gpGlobals->time + 0.15; - return; - } - - if (m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] == 0) - { - PlayEmptySound(); - return; - } - - m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME; - m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH; - - m_pPlayer->m_iExtraSoundTypes = bits_SOUND_DANGER; - m_pPlayer->m_flStopExtraSoundTime = gpGlobals->time + 0.2; - - m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType]--; - - SendWeaponAnim(MP5_LAUNCH); - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - if (RANDOM_LONG(0, 1)) - { - // play this sound through BODY channel so we can hear it if player didn't stop firing MP3 - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/glauncher.wav", 0.8, ATTN_NORM); - } - else - { - // play this sound through BODY channel so we can hear it if player didn't stop firing MP3 - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/glauncher2.wav", 0.8, ATTN_NORM); - } - - UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle); - - // we don't add in player velocity anymore. - CGrenade::ShootContact(m_pPlayer->pev, - m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16, - gpGlobals->v_forward * 800); - - m_flNextPrimaryAttack = gpGlobals->time + 1; - m_flNextSecondaryAttack = gpGlobals->time + 1; - m_flTimeWeaponIdle = gpGlobals->time + 5; // idle pretty soon after shooting. - - if (!m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType]) - // HEV suit - indicate out of ammo condition - m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - - m_pPlayer->pev->punchangle.x -= 10; -} - -void CMP5::Reload(void) -{ - DefaultReload(MP5_MAX_CLIP, MP5_RELOAD, 1.5); -} - -void CMP5::WeaponIdle(void) -{ - ResetEmptySound(); - - m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES); - - if (m_flTimeWeaponIdle > gpGlobals->time) - return; - - int iAnim; - switch (RANDOM_LONG(0, 1)) - { - case 0: - iAnim = MP5_LONGIDLE; - break; - - default: - case 1: - iAnim = MP5_IDLE1; - break; - } - - SendWeaponAnim(iAnim); - - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); // how long till we do this again. -} - -class CMP5AmmoClip : public CBasePlayerAmmo -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_9mmARclip.mdl"); - CBasePlayerAmmo::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_9mmARclip.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - } - BOOL AddAmmo(CBaseEntity *pOther) - { - int bResult = (pOther->GiveAmmo(AMMO_MP5CLIP_GIVE, "9mm", _9MM_MAX_CARRY) != -1); - if (bResult) - { - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); - } - return bResult; - } -}; -LINK_ENTITY_TO_CLASS(ammo_mp5clip, CMP5AmmoClip); -LINK_ENTITY_TO_CLASS(ammo_9mmAR, CMP5AmmoClip); - -class CMP5Chainammo : public CBasePlayerAmmo -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_chainammo.mdl"); - CBasePlayerAmmo::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_chainammo.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - } - BOOL AddAmmo(CBaseEntity *pOther) - { - int bResult = (pOther->GiveAmmo(AMMO_CHAINBOX_GIVE, "9mm", _9MM_MAX_CARRY) != -1); - if (bResult) - { - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); - } - return bResult; - } -}; -LINK_ENTITY_TO_CLASS(ammo_9mmbox, CMP5Chainammo); - -class CMP5AmmoGrenade : public CBasePlayerAmmo -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_ARgrenade.mdl"); - CBasePlayerAmmo::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_ARgrenade.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - } - BOOL AddAmmo(CBaseEntity *pOther) - { - int bResult = (pOther->GiveAmmo(AMMO_M203BOX_GIVE, "ARgrenades", M203_GRENADE_MAX_CARRY) != -1); - - if (bResult) - { - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); - } - return bResult; - } -}; -LINK_ENTITY_TO_CLASS(ammo_mp5grenades, CMP5AmmoGrenade); -LINK_ENTITY_TO_CLASS(ammo_ARgrenades, CMP5AmmoGrenade); diff --git a/dlls/Half-life/nihilanth.cpp b/dlls/Half-life/nihilanth.cpp deleted file mode 100644 index 70dde94b..00000000 --- a/dlls/Half-life/nihilanth.cpp +++ /dev/null @@ -1,1774 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "effects.h" - -#define N_SCALE 15 -#define N_SPHERES 20 - -class CNihilanth : public CBaseMonster -{ -public: - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void Spawn(void); - void Precache(void); - int Classify(void) { return CLASS_ALIEN_MILITARY; }; - int BloodColor(void) { return BLOOD_COLOR_YELLOW; } - void Killed(entvars_t *pevAttacker, int iGib); - void GibMonster(void); - - void SetObjectCollisionBox(void) - { - pev->absmin = pev->origin + Vector(-16 * N_SCALE, -16 * N_SCALE, -48 * N_SCALE); - pev->absmax = pev->origin + Vector(16 * N_SCALE, 16 * N_SCALE, 28 * N_SCALE); - } - - void HandleAnimEvent(MonsterEvent_t *pEvent); - - void EXPORT StartupThink(void); - void EXPORT HuntThink(void); - void EXPORT CrashTouch(CBaseEntity *pOther); - void EXPORT DyingThink(void); - void EXPORT StartupUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void EXPORT NullThink(void); - void EXPORT CommandUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - - void FloatSequence(void); - void NextActivity(void); - - void Flight(void); - - BOOL AbsorbSphere(void); - BOOL EmitSphere(void); - void TargetSphere(USE_TYPE useType, float value); - CBaseEntity *RandomTargetname(const char *szName); - void ShootBalls(void); - void MakeFriend(Vector vecPos); - - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - - void PainSound(void); - void DeathSound(void); - - static const char *pAttackSounds[]; // vocalization: play sometimes when he launches an attack - static const char *pBallSounds[]; // the sound of the lightening ball launch - static const char *pShootSounds[]; // grunting vocalization: play sometimes when he launches an attack - static const char *pRechargeSounds[]; // vocalization: play when he recharges - static const char *pLaughSounds[]; // vocalization: play sometimes when hit and still has lots of health - static const char *pPainSounds[]; // vocalization: play sometimes when hit and has much less health and no more chargers - static const char *pDeathSounds[]; // vocalization: play as he dies - - // x_teleattack1.wav the looping sound of the teleport attack ball. - - float m_flForce; - - float m_flNextPainSound; - - Vector m_velocity; - Vector m_avelocity; - - Vector m_vecTarget; - Vector m_posTarget; - - Vector m_vecDesired; - Vector m_posDesired; - - float m_flMinZ; - float m_flMaxZ; - - Vector m_vecGoal; - - float m_flLastSeen; - float m_flPrevSeen; - - int m_irritation; - - int m_iLevel; - int m_iTeleport; - - EHANDLE m_hRecharger; - - EHANDLE m_hSphere[N_SPHERES]; - int m_iActiveSpheres; - - float m_flAdj; - - CSprite *m_pBall; - - char m_szRechargerTarget[64]; - char m_szDrawUse[64]; - char m_szTeleportUse[64]; - char m_szTeleportTouch[64]; - char m_szDeadUse[64]; - char m_szDeadTouch[64]; - - float m_flShootEnd; - float m_flShootTime; - - EHANDLE m_hFriend[3]; -}; - -LINK_ENTITY_TO_CLASS(monster_nihilanth, CNihilanth); - -TYPEDESCRIPTION CNihilanth::m_SaveData[] = - { - DEFINE_FIELD(CNihilanth, m_flForce, FIELD_FLOAT), - DEFINE_FIELD(CNihilanth, m_flNextPainSound, FIELD_TIME), - DEFINE_FIELD(CNihilanth, m_velocity, FIELD_VECTOR), - DEFINE_FIELD(CNihilanth, m_avelocity, FIELD_VECTOR), - DEFINE_FIELD(CNihilanth, m_vecTarget, FIELD_VECTOR), - DEFINE_FIELD(CNihilanth, m_posTarget, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CNihilanth, m_vecDesired, FIELD_VECTOR), - DEFINE_FIELD(CNihilanth, m_posDesired, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CNihilanth, m_flMinZ, FIELD_FLOAT), - DEFINE_FIELD(CNihilanth, m_flMaxZ, FIELD_FLOAT), - DEFINE_FIELD(CNihilanth, m_vecGoal, FIELD_VECTOR), - DEFINE_FIELD(CNihilanth, m_flLastSeen, FIELD_TIME), - DEFINE_FIELD(CNihilanth, m_flPrevSeen, FIELD_TIME), - DEFINE_FIELD(CNihilanth, m_irritation, FIELD_INTEGER), - DEFINE_FIELD(CNihilanth, m_iLevel, FIELD_INTEGER), - DEFINE_FIELD(CNihilanth, m_iTeleport, FIELD_INTEGER), - DEFINE_FIELD(CNihilanth, m_hRecharger, FIELD_EHANDLE), - DEFINE_ARRAY(CNihilanth, m_hSphere, FIELD_EHANDLE, N_SPHERES), - DEFINE_FIELD(CNihilanth, m_iActiveSpheres, FIELD_INTEGER), - DEFINE_FIELD(CNihilanth, m_flAdj, FIELD_FLOAT), - DEFINE_FIELD(CNihilanth, m_pBall, FIELD_CLASSPTR), - DEFINE_ARRAY(CNihilanth, m_szRechargerTarget, FIELD_CHARACTER, 64), - DEFINE_ARRAY(CNihilanth, m_szDrawUse, FIELD_CHARACTER, 64), - DEFINE_ARRAY(CNihilanth, m_szTeleportUse, FIELD_CHARACTER, 64), - DEFINE_ARRAY(CNihilanth, m_szTeleportTouch, FIELD_CHARACTER, 64), - DEFINE_ARRAY(CNihilanth, m_szDeadUse, FIELD_CHARACTER, 64), - DEFINE_ARRAY(CNihilanth, m_szDeadTouch, FIELD_CHARACTER, 64), - DEFINE_FIELD(CNihilanth, m_flShootEnd, FIELD_TIME), - DEFINE_FIELD(CNihilanth, m_flShootTime, FIELD_TIME), - DEFINE_ARRAY(CNihilanth, m_hFriend, FIELD_EHANDLE, 3), -}; - -IMPLEMENT_SAVERESTORE(CNihilanth, CBaseMonster); - -class CNihilanthHVR : public CBaseMonster -{ -public: - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void Spawn(void); - void Precache(void); - - void CircleInit(CBaseEntity *pTarget); - void AbsorbInit(void); - void TeleportInit(CNihilanth *pOwner, CBaseEntity *pEnemy, CBaseEntity *pTarget, CBaseEntity *pTouch); - void GreenBallInit(void); - void ZapInit(CBaseEntity *pEnemy); - - void EXPORT HoverThink(void); - BOOL CircleTarget(Vector vecTarget); - void EXPORT DissipateThink(void); - - void EXPORT ZapThink(void); - void EXPORT TeleportThink(void); - void EXPORT TeleportTouch(CBaseEntity *pOther); - - void EXPORT RemoveTouch(CBaseEntity *pOther); - void EXPORT BounceTouch(CBaseEntity *pOther); - void EXPORT ZapTouch(CBaseEntity *pOther); - - CBaseEntity *RandomClassname(const char *szName); - - // void EXPORT SphereUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - void MovetoTarget(Vector vecTarget); - virtual void Crawl(void); - - void Zap(void); - void Teleport(void); - - float m_flIdealVel; - Vector m_vecIdeal; - CNihilanth *m_pNihilanth; - EHANDLE m_hTouch; - int m_nFrames; -}; - -LINK_ENTITY_TO_CLASS(nihilanth_energy_ball, CNihilanthHVR); - -TYPEDESCRIPTION CNihilanthHVR::m_SaveData[] = - { - DEFINE_FIELD(CNihilanthHVR, m_flIdealVel, FIELD_FLOAT), - DEFINE_FIELD(CNihilanthHVR, m_vecIdeal, FIELD_VECTOR), - DEFINE_FIELD(CNihilanthHVR, m_pNihilanth, FIELD_CLASSPTR), - DEFINE_FIELD(CNihilanthHVR, m_hTouch, FIELD_EHANDLE), - DEFINE_FIELD(CNihilanthHVR, m_nFrames, FIELD_INTEGER), -}; - -IMPLEMENT_SAVERESTORE(CNihilanthHVR, CBaseMonster); - -//========================================================= -// Nihilanth, final Boss monster -//========================================================= - -const char *CNihilanth::pAttackSounds[] = - { - "X/x_attack1.wav", - "X/x_attack2.wav", - "X/x_attack3.wav", -}; - -const char *CNihilanth::pBallSounds[] = - { - "X/x_ballattack1.wav", -}; - -const char *CNihilanth::pShootSounds[] = - { - "X/x_shoot1.wav", -}; - -const char *CNihilanth::pRechargeSounds[] = - { - "X/x_recharge1.wav", - "X/x_recharge2.wav", - "X/x_recharge3.wav", -}; - -const char *CNihilanth::pLaughSounds[] = - { - "X/x_laugh1.wav", - "X/x_laugh2.wav", -}; - -const char *CNihilanth::pPainSounds[] = - { - "X/x_pain1.wav", - "X/x_pain2.wav", -}; - -const char *CNihilanth::pDeathSounds[] = - { - "X/x_die1.wav", -}; - -void CNihilanth ::Spawn(void) -{ - Precache(); - // motor - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - SET_MODEL(edict(), "models/nihilanth.mdl"); - // UTIL_SetSize(pev, Vector( -300, -300, 0), Vector(300, 300, 512)); - UTIL_SetSize(pev, Vector(-32, -32, 0), Vector(32, 32, 64)); - UTIL_SetOrigin(pev, pev->origin); - - pev->flags |= FL_MONSTER; - pev->takedamage = DAMAGE_AIM; - pev->health = gSkillData.nihilanthHealth; - pev->view_ofs = Vector(0, 0, 300); - - m_flFieldOfView = -1; // 360 degrees - - pev->sequence = 0; - ResetSequenceInfo(); - - InitBoneControllers(); - - SetThink(StartupThink); - pev->nextthink = gpGlobals->time + 0.1; - - m_vecDesired = Vector(1, 0, 0); - m_posDesired = Vector(pev->origin.x, pev->origin.y, 512); - - m_iLevel = 1; - m_iTeleport = 1; - - if (m_szRechargerTarget[0] == '\0') - strncpy(m_szRechargerTarget, "n_recharger", sizeof(m_szRechargerTarget) ); - if (m_szDrawUse[0] == '\0') - strncpy(m_szDrawUse, "n_draw", sizeof(m_szDrawUse) ); - if (m_szTeleportUse[0] == '\0') - strncpy(m_szTeleportUse, "n_leaving", sizeof(m_szTeleportUse) ); - if (m_szTeleportTouch[0] == '\0') - strncpy(m_szTeleportTouch, "n_teleport", sizeof(m_szTeleportTouch) ); - if (m_szDeadUse[0] == '\0') - strncpy(m_szDeadUse, "n_dead", sizeof(m_szDeadUse) ); - if (m_szDeadTouch[0] == '\0') - strncpy(m_szDeadTouch, "n_ending", sizeof(m_szDeadTouch) ); - - // near death - /* - m_iTeleport = 10; - m_iLevel = 10; - m_irritation = 2; - pev->health = 100; - */ -} - -void CNihilanth::Precache(void) -{ - PRECACHE_MODEL("models/nihilanth.mdl"); - PRECACHE_MODEL("sprites/lgtning.spr"); - UTIL_PrecacheOther("nihilanth_energy_ball"); - UTIL_PrecacheOther("monster_alien_controller"); - UTIL_PrecacheOther("monster_alien_slave"); - - PRECACHE_SOUND_ARRAY(pAttackSounds); - PRECACHE_SOUND_ARRAY(pBallSounds); - PRECACHE_SOUND_ARRAY(pShootSounds); - PRECACHE_SOUND_ARRAY(pRechargeSounds); - PRECACHE_SOUND_ARRAY(pLaughSounds); - PRECACHE_SOUND_ARRAY(pPainSounds); - PRECACHE_SOUND_ARRAY(pDeathSounds); - PRECACHE_SOUND("debris/beamstart7.wav"); -} - -void CNihilanth ::PainSound(void) -{ - if (m_flNextPainSound > gpGlobals->time) - return; - - m_flNextPainSound = gpGlobals->time + RANDOM_FLOAT(2, 5); - - if (pev->health > gSkillData.nihilanthHealth / 2) - { - EMIT_SOUND(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pLaughSounds), 1.0, 0.2); - } - else if (m_irritation >= 2) - { - EMIT_SOUND(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pPainSounds), 1.0, 0.2); - } -} - -void CNihilanth ::DeathSound(void) -{ - EMIT_SOUND(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDeathSounds), 1.0, 0.1); -} - -void CNihilanth::NullThink(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.5; -} - -void CNihilanth::StartupUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - SetThink(HuntThink); - pev->nextthink = gpGlobals->time + 0.1; - SetUse(CommandUse); -} - -void CNihilanth::StartupThink(void) -{ - m_irritation = 0; - m_flAdj = 512; - - CBaseEntity *pEntity; - - pEntity = UTIL_FindEntityByTargetname(NULL, "n_min"); - if (pEntity) - m_flMinZ = pEntity->pev->origin.z; - else - m_flMinZ = -4096; - - pEntity = UTIL_FindEntityByTargetname(NULL, "n_max"); - if (pEntity) - m_flMaxZ = pEntity->pev->origin.z; - else - m_flMaxZ = 4096; - - m_hRecharger = this; - for (int i = 0; i < N_SPHERES; i++) - { - EmitSphere(); - } - m_hRecharger = NULL; - - SetThink(HuntThink); - SetUse(CommandUse); - pev->nextthink = gpGlobals->time + 0.1; -} - -void CNihilanth ::Killed(entvars_t *pevAttacker, int iGib) -{ - CBaseMonster::Killed(pevAttacker, iGib); -} - -void CNihilanth ::DyingThink(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - DispatchAnimEvents(); - StudioFrameAdvance(); - - if (pev->deadflag == DEAD_NO) - { - DeathSound(); - pev->deadflag = DEAD_DYING; - - m_posDesired.z = m_flMaxZ; - } - - if (pev->deadflag == DEAD_DYING) - { - Flight(); - - if (fabs(pev->origin.z - m_flMaxZ) < 16) - { - pev->velocity = Vector(0, 0, 0); - FireTargets(m_szDeadUse, this, this, USE_ON, 1.0); - pev->deadflag = DEAD_DEAD; - } - } - - if (m_fSequenceFinished) - { - pev->avelocity.y += RANDOM_FLOAT(-100, 100); - if (pev->avelocity.y < -100) - pev->avelocity.y = -100; - if (pev->avelocity.y > 100) - pev->avelocity.y = 100; - - pev->sequence = LookupSequence("die1"); - } - - if (m_pBall) - { - if (m_pBall->pev->renderamt > 0) - { - m_pBall->pev->renderamt = max(0, m_pBall->pev->renderamt - 2); - } - else - { - UTIL_Remove(m_pBall); - m_pBall = NULL; - } - } - - Vector vecDir, vecSrc, vecAngles; - - UTIL_MakeAimVectors(pev->angles); - int iAttachment = RANDOM_LONG(1, 4); - - do - { - vecDir = Vector(RANDOM_FLOAT(-1, 1), RANDOM_FLOAT(-1, 1), RANDOM_FLOAT(-1, 1)); - } while (DotProduct(vecDir, vecDir) > 1.0); - - switch (RANDOM_LONG(1, 4)) - { - case 1: // head - vecDir.z = fabs(vecDir.z) * 0.5; - vecDir = vecDir + 2 * gpGlobals->v_up; - break; - case 2: // eyes - if (DotProduct(vecDir, gpGlobals->v_forward) < 0) - vecDir = vecDir * -1; - - vecDir = vecDir + 2 * gpGlobals->v_forward; - break; - case 3: // left hand - if (DotProduct(vecDir, gpGlobals->v_right) > 0) - vecDir = vecDir * -1; - vecDir = vecDir - 2 * gpGlobals->v_right; - break; - case 4: // right hand - if (DotProduct(vecDir, gpGlobals->v_right) < 0) - vecDir = vecDir * -1; - vecDir = vecDir + 2 * gpGlobals->v_right; - break; - } - - GetAttachment(iAttachment - 1, vecSrc, vecAngles); - - TraceResult tr; - - UTIL_TraceLine(vecSrc, vecSrc + vecDir * 4096, ignore_monsters, ENT(pev), &tr); - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_BEAMENTPOINT); - WRITE_SHORT(entindex() + 0x1000 * iAttachment); - WRITE_COORD(tr.vecEndPos.x); - WRITE_COORD(tr.vecEndPos.y); - WRITE_COORD(tr.vecEndPos.z); - WRITE_SHORT(g_sModelIndexLaser); - WRITE_BYTE(0); // frame start - WRITE_BYTE(10); // framerate - WRITE_BYTE(5); // life - WRITE_BYTE(100); // width - WRITE_BYTE(120); // noise - WRITE_BYTE(64); // r, g, b - WRITE_BYTE(128); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // brightness - WRITE_BYTE(10); // speed - MESSAGE_END(); - - GetAttachment(0, vecSrc, vecAngles); - CNihilanthHVR *pEntity = (CNihilanthHVR *)Create("nihilanth_energy_ball", vecSrc, pev->angles, edict()); - pEntity->pev->velocity = Vector(RANDOM_FLOAT(-0.7, 0.7), RANDOM_FLOAT(-0.7, 0.7), 1.0) * 600.0; - pEntity->GreenBallInit(); - - return; -} - -void CNihilanth::CrashTouch(CBaseEntity *pOther) -{ - // only crash if we hit something solid - if (pOther->pev->solid == SOLID_BSP) - { - SetTouch(NULL); - pev->nextthink = gpGlobals->time; - } -} - -void CNihilanth ::GibMonster(void) -{ - // EMIT_SOUND_DYN(edict(), CHAN_VOICE, "common/bodysplat.wav", 0.75, ATTN_NORM, 0, 200); -} - -void CNihilanth ::FloatSequence(void) -{ - if (m_irritation >= 2) - { - pev->sequence = LookupSequence("float_open"); - } - else if (m_avelocity.y > 30) - { - pev->sequence = LookupSequence("walk_r"); - } - else if (m_avelocity.y < -30) - { - pev->sequence = LookupSequence("walk_l"); - } - else if (m_velocity.z > 30) - { - pev->sequence = LookupSequence("walk_u"); - } - else if (m_velocity.z < -30) - { - pev->sequence = LookupSequence("walk_d"); - } - else - { - pev->sequence = LookupSequence("float"); - } -} - -void CNihilanth ::ShootBalls(void) -{ - if (m_flShootEnd > gpGlobals->time) - { - Vector vecHand, vecAngle; - - while (m_flShootTime < m_flShootEnd && m_flShootTime < gpGlobals->time) - { - if (m_hEnemy != NULL) - { - Vector vecSrc, vecDir; - CNihilanthHVR *pEntity; - - GetAttachment(2, vecHand, vecAngle); - vecSrc = vecHand + pev->velocity * (m_flShootTime - gpGlobals->time); - // vecDir = (m_posTarget - vecSrc).Normalize( ); - vecDir = (m_posTarget - pev->origin).Normalize(); - vecSrc = vecSrc + vecDir * (gpGlobals->time - m_flShootTime); - pEntity = (CNihilanthHVR *)Create("nihilanth_energy_ball", vecSrc, pev->angles, edict()); - pEntity->pev->velocity = vecDir * 200.0; - pEntity->ZapInit(m_hEnemy); - - GetAttachment(3, vecHand, vecAngle); - vecSrc = vecHand + pev->velocity * (m_flShootTime - gpGlobals->time); - // vecDir = (m_posTarget - vecSrc).Normalize( ); - vecDir = (m_posTarget - pev->origin).Normalize(); - vecSrc = vecSrc + vecDir * (gpGlobals->time - m_flShootTime); - pEntity = (CNihilanthHVR *)Create("nihilanth_energy_ball", vecSrc, pev->angles, edict()); - pEntity->pev->velocity = vecDir * 200.0; - pEntity->ZapInit(m_hEnemy); - } - m_flShootTime += 0.2; - } - } -} - -void CNihilanth ::MakeFriend(Vector vecStart) -{ - int i; - - for (i = 0; i < 3; i++) - { - if (m_hFriend[i] != NULL && !m_hFriend[i]->IsAlive()) - { - if (pev->rendermode == kRenderNormal) // don't do it if they are already fading - m_hFriend[i]->MyMonsterPointer()->FadeMonster(); - m_hFriend[i] = NULL; - } - - if (m_hFriend[i] == NULL) - { - if (RANDOM_LONG(0, 1) == 0) - { - int iNode = WorldGraph.FindNearestNode(vecStart, bits_NODE_AIR); - if (iNode != NO_NODE) - { - CNode &node = WorldGraph.Node(iNode); - TraceResult tr; - UTIL_TraceHull(node.m_vecOrigin + Vector(0, 0, 32), node.m_vecOrigin + Vector(0, 0, 32), dont_ignore_monsters, large_hull, NULL, &tr); - if (tr.fStartSolid == 0) - m_hFriend[i] = Create("monster_alien_controller", node.m_vecOrigin, pev->angles); - } - } - else - { - int iNode = WorldGraph.FindNearestNode(vecStart, bits_NODE_LAND | bits_NODE_WATER); - if (iNode != NO_NODE) - { - CNode &node = WorldGraph.Node(iNode); - TraceResult tr; - UTIL_TraceHull(node.m_vecOrigin + Vector(0, 0, 36), node.m_vecOrigin + Vector(0, 0, 36), dont_ignore_monsters, human_hull, NULL, &tr); - if (tr.fStartSolid == 0) - m_hFriend[i] = Create("monster_alien_slave", node.m_vecOrigin, pev->angles); - } - } - if (m_hFriend[i] != NULL) - { - EMIT_SOUND(m_hFriend[i]->edict(), CHAN_WEAPON, "debris/beamstart7.wav", 1.0, ATTN_NORM); - } - - return; - } - } -} - -void CNihilanth ::NextActivity() -{ - UTIL_MakeAimVectors(pev->angles); - - if (m_irritation >= 2) - { - if (m_pBall == NULL) - { - m_pBall = CSprite::SpriteCreate("sprites/tele1.spr", pev->origin, TRUE); - if (m_pBall) - { - m_pBall->SetTransparency(kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation); - m_pBall->SetAttachment(edict(), 1); - m_pBall->SetScale(4.0); - m_pBall->pev->framerate = 10.0; - m_pBall->TurnOn(); - } - } - - if (m_pBall) - { - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex() + 0x1000); // entity, attachment - WRITE_COORD(pev->origin.x); // origin - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(256); // radius - WRITE_BYTE(255); // R - WRITE_BYTE(192); // G - WRITE_BYTE(64); // B - WRITE_BYTE(200); // life * 10 - WRITE_COORD(0); // decay - MESSAGE_END(); - } - } - - if ((pev->health < gSkillData.nihilanthHealth / 2 || m_iActiveSpheres < N_SPHERES / 2) && m_hRecharger == NULL && m_iLevel <= 9) - { - char szName[64]; - - CBaseEntity *pEnt = NULL; - CBaseEntity *pRecharger = NULL; - float flDist = 8192; - - _snprintf(szName, sizeof(szName), "%s%d", m_szRechargerTarget, m_iLevel ); - - while ((pEnt = UTIL_FindEntityByTargetname(pEnt, szName)) != NULL) - { - float flLocal = (pEnt->pev->origin - pev->origin).Length(); - if (flLocal < flDist) - { - flDist = flLocal; - pRecharger = pEnt; - } - } - - if (pRecharger) - { - m_hRecharger = pRecharger; - m_posDesired = Vector(pev->origin.x, pev->origin.y, pRecharger->pev->origin.z); - m_vecDesired = (pRecharger->pev->origin - m_posDesired).Normalize(); - m_vecDesired.z = 0; - m_vecDesired = m_vecDesired.Normalize(); - } - else - { - m_hRecharger = NULL; - ALERT(at_aiconsole, "nihilanth can't find %s\n", szName); - m_iLevel++; - if (m_iLevel > 9) - m_irritation = 2; - } - } - - float flDist = (m_posDesired - pev->origin).Length(); - float flDot = DotProduct(m_vecDesired, gpGlobals->v_forward); - - if (m_hRecharger != NULL) - { - // at we at power up yet? - if (flDist < 128.0) - { - int iseq = LookupSequence("recharge"); - - if (iseq != pev->sequence) - { - char szText[64]; - - _snprintf(szText, sizeof(szText), "%s%d", m_szDrawUse, m_iLevel ); - FireTargets(szText, this, this, USE_ON, 1.0); - - ALERT(at_console, "fireing %s\n", szText); - } - pev->sequence = LookupSequence("recharge"); - } - else - { - FloatSequence(); - } - return; - } - - if (m_hEnemy != NULL && !m_hEnemy->IsAlive()) - { - m_hEnemy = NULL; - } - - if (m_flLastSeen + 15 < gpGlobals->time) - { - m_hEnemy = NULL; - } - - if (m_hEnemy == NULL) - { - Look(4096); - m_hEnemy = BestVisibleEnemy(); - } - - if (m_hEnemy != NULL && m_irritation != 0) - { - if (m_flLastSeen + 5 > gpGlobals->time && flDist < 256 && flDot > 0) - { - if (m_irritation >= 2 && pev->health < gSkillData.nihilanthHealth / 2.0) - { - pev->sequence = LookupSequence("attack1_open"); - } - else - { - if (RANDOM_LONG(0, 1) == 0) - { - pev->sequence = LookupSequence("attack1"); // zap - } - else - { - char szText[64]; - - _snprintf(szText, sizeof(szText), "%s%d", m_szTeleportTouch, m_iTeleport ); - CBaseEntity *pTouch = UTIL_FindEntityByTargetname(NULL, szText); - - _snprintf(szText, sizeof(szText), "%s%d", m_szTeleportUse, m_iTeleport ); - CBaseEntity *pTrigger = UTIL_FindEntityByTargetname(NULL, szText); - - if (pTrigger != NULL || pTouch != NULL) - { - pev->sequence = LookupSequence("attack2"); // teleport - } - else - { - m_iTeleport++; - pev->sequence = LookupSequence("attack1"); // zap - } - } - } - return; - } - } - - FloatSequence(); -} - -void CNihilanth ::HuntThink(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - DispatchAnimEvents(); - StudioFrameAdvance(); - - ShootBalls(); - - // if dead, force cancelation of current animation - if (pev->health <= 0) - { - SetThink(DyingThink); - m_fSequenceFinished = TRUE; - return; - } - - // ALERT( at_console, "health %.0f\n", pev->health ); - - // if damaged, try to abosorb some spheres - if (pev->health < gSkillData.nihilanthHealth && AbsorbSphere()) - { - pev->health += gSkillData.nihilanthHealth / N_SPHERES; - } - - // get new sequence - if (m_fSequenceFinished) - { - // if (!m_fSequenceLoops) - pev->frame = 0; - NextActivity(); - ResetSequenceInfo(); - pev->framerate = 2.0 - 1.0 * (pev->health / gSkillData.nihilanthHealth); - } - - // look for current enemy - if (m_hEnemy != NULL && m_hRecharger == NULL) - { - if (FVisible(m_hEnemy)) - { - if (m_flLastSeen < gpGlobals->time - 5) - m_flPrevSeen = gpGlobals->time; - m_flLastSeen = gpGlobals->time; - m_posTarget = m_hEnemy->pev->origin; - m_vecTarget = (m_posTarget - pev->origin).Normalize(); - m_vecDesired = m_vecTarget; - m_posDesired = Vector(pev->origin.x, pev->origin.y, m_posTarget.z + m_flAdj); - } - else - { - m_flAdj = min(m_flAdj + 10, 1000); - } - } - - // don't go too high - if (m_posDesired.z > m_flMaxZ) - m_posDesired.z = m_flMaxZ; - - // don't go too low - if (m_posDesired.z < m_flMinZ) - m_posDesired.z = m_flMinZ; - - Flight(); -} - -void CNihilanth ::Flight(void) -{ - // estimate where I'll be facing in one seconds - UTIL_MakeAimVectors(pev->angles + m_avelocity); - // Vector vecEst1 = pev->origin + m_velocity + gpGlobals->v_up * m_flForce - Vector( 0, 0, 384 ); - // float flSide = DotProduct( m_posDesired - vecEst1, gpGlobals->v_right ); - - float flSide = DotProduct(m_vecDesired, gpGlobals->v_right); - - if (flSide < 0) - { - if (m_avelocity.y < 180) - { - m_avelocity.y += 6; // 9 * (3.0/2.0); - } - } - else - { - if (m_avelocity.y > -180) - { - m_avelocity.y -= 6; // 9 * (3.0/2.0); - } - } - m_avelocity.y *= 0.98; - - // estimate where I'll be in two seconds - Vector vecEst = pev->origin + m_velocity * 2.0 + gpGlobals->v_up * m_flForce * 20; - - // add immediate force - UTIL_MakeAimVectors(pev->angles); - m_velocity.x += gpGlobals->v_up.x * m_flForce; - m_velocity.y += gpGlobals->v_up.y * m_flForce; - m_velocity.z += gpGlobals->v_up.z * m_flForce; - - float flSpeed = m_velocity.Length(); - float flDir = DotProduct(Vector(gpGlobals->v_forward.x, gpGlobals->v_forward.y, 0), Vector(m_velocity.x, m_velocity.y, 0)); - if (flDir < 0) - flSpeed = -flSpeed; - - float flDist = DotProduct(m_posDesired - vecEst, gpGlobals->v_forward); - - // sideways drag - m_velocity.x = m_velocity.x * (1.0 - fabs(gpGlobals->v_right.x) * 0.05); - m_velocity.y = m_velocity.y * (1.0 - fabs(gpGlobals->v_right.y) * 0.05); - m_velocity.z = m_velocity.z * (1.0 - fabs(gpGlobals->v_right.z) * 0.05); - - // general drag - m_velocity = m_velocity * 0.995; - - // apply power to stay correct height - if (m_flForce < 100 && vecEst.z < m_posDesired.z) - { - m_flForce += 10; - } - else if (m_flForce > -100 && vecEst.z > m_posDesired.z) - { - if (vecEst.z > m_posDesired.z) - m_flForce -= 10; - } - - UTIL_SetOrigin(pev, pev->origin + m_velocity * 0.1); - pev->angles = pev->angles + m_avelocity * 0.1; - - // ALERT( at_console, "%5.0f %5.0f : %4.0f : %3.0f : %2.0f\n", m_posDesired.z, pev->origin.z, m_velocity.z, m_avelocity.y, m_flForce ); -} - -BOOL CNihilanth ::AbsorbSphere(void) -{ - for (int i = 0; i < N_SPHERES; i++) - { - if (m_hSphere[i] != NULL) - { - CNihilanthHVR *pSphere = (CNihilanthHVR *)((CBaseEntity *)m_hSphere[i]); - pSphere->AbsorbInit(); - m_hSphere[i] = NULL; - m_iActiveSpheres--; - return TRUE; - } - } - return FALSE; -} - -BOOL CNihilanth ::EmitSphere(void) -{ - m_iActiveSpheres = 0; - int empty = 0; - - for (int i = 0; i < N_SPHERES; i++) - { - if (m_hSphere[i] != NULL) - { - m_iActiveSpheres++; - } - else - { - empty = i; - } - } - - if (m_iActiveSpheres >= N_SPHERES) - return FALSE; - - Vector vecSrc = m_hRecharger->pev->origin; - CNihilanthHVR *pEntity = (CNihilanthHVR *)Create("nihilanth_energy_ball", vecSrc, pev->angles, edict()); - pEntity->pev->velocity = pev->origin - vecSrc; - pEntity->CircleInit(this); - - m_hSphere[empty] = pEntity; - return TRUE; -} - -void CNihilanth ::TargetSphere(USE_TYPE useType, float value) -{ - CBaseMonster *pSphere; - for (int i = 0; i < N_SPHERES; i++) - { - if (m_hSphere[i] != NULL) - { - pSphere = m_hSphere[i]->MyMonsterPointer(); - if (pSphere->m_hEnemy == NULL) - break; - } - } - if (i == N_SPHERES) - { - return; - } - - Vector vecSrc, vecAngles; - GetAttachment(2, vecSrc, vecAngles); - UTIL_SetOrigin(pSphere->pev, vecSrc); - pSphere->Use(this, this, useType, value); - pSphere->pev->velocity = m_vecDesired * RANDOM_FLOAT(50, 100) + Vector(RANDOM_FLOAT(-50, 50), RANDOM_FLOAT(-50, 50), RANDOM_FLOAT(-50, 50)); -} - -void CNihilanth ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case 1: // shoot - break; - case 2: // zen - if (m_hEnemy != NULL) - { - if (RANDOM_LONG(0, 4) == 0) - EMIT_SOUND(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAttackSounds), 1.0, 0.2); - - EMIT_SOUND(edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pBallSounds), 1.0, 0.2); - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex() + 0x3000); // entity, attachment - WRITE_COORD(pev->origin.x); // origin - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(256); // radius - WRITE_BYTE(128); // R - WRITE_BYTE(128); // G - WRITE_BYTE(255); // B - WRITE_BYTE(10); // life * 10 - WRITE_COORD(128); // decay - MESSAGE_END(); - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex() + 0x4000); // entity, attachment - WRITE_COORD(pev->origin.x); // origin - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(256); // radius - WRITE_BYTE(128); // R - WRITE_BYTE(128); // G - WRITE_BYTE(255); // B - WRITE_BYTE(10); // life * 10 - WRITE_COORD(128); // decay - MESSAGE_END(); - - m_flShootTime = gpGlobals->time; - m_flShootEnd = gpGlobals->time + 1.0; - } - break; - case 3: // prayer - if (m_hEnemy != NULL) - { - char szText[32]; - - _snprintf(szText, sizeof(szText), "%s%d", m_szTeleportTouch, m_iTeleport ); - CBaseEntity *pTouch = UTIL_FindEntityByTargetname(NULL, szText); - - _snprintf(szText, sizeof(szText), "%s%d", m_szTeleportUse, m_iTeleport ); - CBaseEntity *pTrigger = UTIL_FindEntityByTargetname(NULL, szText); - - if (pTrigger != NULL || pTouch != NULL) - { - EMIT_SOUND(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAttackSounds), 1.0, 0.2); - - Vector vecSrc, vecAngles; - GetAttachment(2, vecSrc, vecAngles); - CNihilanthHVR *pEntity = (CNihilanthHVR *)Create("nihilanth_energy_ball", vecSrc, pev->angles, edict()); - pEntity->pev->velocity = pev->origin - vecSrc; - pEntity->TeleportInit(this, m_hEnemy, pTrigger, pTouch); - } - else - { - m_iTeleport++; // unexpected failure - - EMIT_SOUND(edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pBallSounds), 1.0, 0.2); - - ALERT(at_aiconsole, "nihilanth can't target %s\n", szText); - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex() + 0x3000); // entity, attachment - WRITE_COORD(pev->origin.x); // origin - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(256); // radius - WRITE_BYTE(128); // R - WRITE_BYTE(128); // G - WRITE_BYTE(255); // B - WRITE_BYTE(10); // life * 10 - WRITE_COORD(128); // decay - MESSAGE_END(); - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex() + 0x4000); // entity, attachment - WRITE_COORD(pev->origin.x); // origin - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(256); // radius - WRITE_BYTE(128); // R - WRITE_BYTE(128); // G - WRITE_BYTE(255); // B - WRITE_BYTE(10); // life * 10 - WRITE_COORD(128); // decay - MESSAGE_END(); - - m_flShootTime = gpGlobals->time; - m_flShootEnd = gpGlobals->time + 1.0; - } - } - break; - case 4: // get a sphere - { - if (m_hRecharger != NULL) - { - if (!EmitSphere()) - { - m_hRecharger = NULL; - } - } - } - break; - case 5: // start up sphere machine - { - EMIT_SOUND(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pRechargeSounds), 1.0, 0.2); - } - break; - case 6: - if (m_hEnemy != NULL) - { - Vector vecSrc, vecAngles; - GetAttachment(2, vecSrc, vecAngles); - CNihilanthHVR *pEntity = (CNihilanthHVR *)Create("nihilanth_energy_ball", vecSrc, pev->angles, edict()); - pEntity->pev->velocity = pev->origin - vecSrc; - pEntity->ZapInit(m_hEnemy); - } - break; - case 7: - /* - Vector vecSrc, vecAngles; - GetAttachment( 0, vecSrc, vecAngles ); - CNihilanthHVR *pEntity = (CNihilanthHVR *)Create( "nihilanth_energy_ball", vecSrc, pev->angles, edict() ); - pEntity->pev->velocity = Vector ( RANDOM_FLOAT( -0.7, 0.7 ), RANDOM_FLOAT( -0.7, 0.7 ), 1.0 ) * 600.0; - pEntity->GreenBallInit( ); - */ - break; - } -} - -void CNihilanth::CommandUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - switch (useType) - { - case USE_OFF: - { - CBaseEntity *pTouch = UTIL_FindEntityByTargetname(NULL, m_szDeadTouch); - if (pTouch && m_hEnemy != NULL) - pTouch->Touch(m_hEnemy); - } - break; - case USE_ON: - if (m_irritation == 0) - { - m_irritation = 1; - } - break; - case USE_SET: - break; - case USE_TOGGLE: - break; - } -} - -int CNihilanth ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (pevInflictor->owner == edict()) - return 0; - - if (flDamage >= pev->health) - { - pev->health = 1; - if (m_irritation != 3) - return 0; - } - - PainSound(); - - pev->health -= flDamage; - return 0; -} - -void CNihilanth::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - if (m_irritation == 3) - m_irritation = 2; - - if (m_irritation == 2 && ptr->iHitgroup == 2 && flDamage > 2) - m_irritation = 3; - - if (m_irritation != 3) - { - Vector vecBlood = (ptr->vecEndPos - pev->origin).Normalize(); - - UTIL_BloodStream(ptr->vecEndPos, vecBlood, BloodColor(), flDamage + (100 - 100 * (pev->health / gSkillData.nihilanthHealth))); - } - - // SpawnBlood(ptr->vecEndPos, BloodColor(), flDamage * 5.0);// a little surface blood. - AddMultiDamage(pevAttacker, this, flDamage, bitsDamageType); -} - -CBaseEntity *CNihilanth::RandomTargetname(const char *szName) -{ - int total = 0; - - CBaseEntity *pEntity = NULL; - CBaseEntity *pNewEntity = NULL; - while ((pNewEntity = UTIL_FindEntityByTargetname(pNewEntity, szName)) != NULL) - { - total++; - if (RANDOM_LONG(0, total - 1) < 1) - pEntity = pNewEntity; - } - return pEntity; -} - -//========================================================= -// Controller bouncy ball attack -//========================================================= - -void CNihilanthHVR ::Spawn(void) -{ - Precache(); - - pev->rendermode = kRenderTransAdd; - pev->renderamt = 255; - pev->scale = 3.0; -} - -void CNihilanthHVR ::Precache(void) -{ - PRECACHE_MODEL("sprites/flare6.spr"); - PRECACHE_MODEL("sprites/nhth1.spr"); - PRECACHE_MODEL("sprites/exit1.spr"); - PRECACHE_MODEL("sprites/tele1.spr"); - PRECACHE_MODEL("sprites/animglow01.spr"); - PRECACHE_MODEL("sprites/xspark4.spr"); - PRECACHE_MODEL("sprites/muzzleflash3.spr"); - PRECACHE_SOUND("debris/zap4.wav"); - PRECACHE_SOUND("weapons/electro4.wav"); - PRECACHE_SOUND("x/x_teleattack1.wav"); -} - -void CNihilanthHVR ::CircleInit(CBaseEntity *pTarget) -{ - pev->movetype = MOVETYPE_NOCLIP; - pev->solid = SOLID_NOT; - - // SET_MODEL(edict(), "sprites/flare6.spr"); - // pev->scale = 3.0; - // SET_MODEL(edict(), "sprites/xspark4.spr"); - SET_MODEL(edict(), "sprites/muzzleflash3.spr"); - pev->rendercolor.x = 255; - pev->rendercolor.y = 224; - pev->rendercolor.z = 192; - pev->scale = 2.0; - m_nFrames = 1; - pev->renderamt = 255; - - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); - UTIL_SetOrigin(pev, pev->origin); - - SetThink(HoverThink); - SetTouch(BounceTouch); - pev->nextthink = gpGlobals->time + 0.1; - - m_hTargetEnt = pTarget; -} - -CBaseEntity *CNihilanthHVR::RandomClassname(const char *szName) -{ - int total = 0; - - CBaseEntity *pEntity = NULL; - CBaseEntity *pNewEntity = NULL; - while ((pNewEntity = UTIL_FindEntityByClassname(pNewEntity, szName)) != NULL) - { - total++; - if (RANDOM_LONG(0, total - 1) < 1) - pEntity = pNewEntity; - } - return pEntity; -} - -void CNihilanthHVR ::HoverThink(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - if (m_hTargetEnt != NULL) - { - CircleTarget(m_hTargetEnt->pev->origin + Vector(0, 0, 16 * N_SCALE)); - } - else - { - UTIL_Remove(this); - } - - if (RANDOM_LONG(0, 99) < 5) - { - /* - CBaseEntity *pOther = RandomClassname( STRING(pev->classname) ); - - if (pOther && pOther != this) - { - MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); - WRITE_BYTE( TE_BEAMENTS ); - WRITE_SHORT( this->entindex() ); - WRITE_SHORT( pOther->entindex() ); - WRITE_SHORT( g_sModelIndexLaser ); - WRITE_BYTE( 0 ); // framestart - WRITE_BYTE( 0 ); // framerate - WRITE_BYTE( 10 ); // life - WRITE_BYTE( 80 ); // width - WRITE_BYTE( 80 ); // noise - WRITE_BYTE( 255 ); // r, g, b - WRITE_BYTE( 128 ); // r, g, b - WRITE_BYTE( 64 ); // r, g, b - WRITE_BYTE( 255 ); // brightness - WRITE_BYTE( 30 ); // speed - MESSAGE_END(); - } -*/ - /* - MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); - WRITE_BYTE( TE_BEAMENTS ); - WRITE_SHORT( this->entindex() ); - WRITE_SHORT( m_hTargetEnt->entindex() + 0x1000 ); - WRITE_SHORT( g_sModelIndexLaser ); - WRITE_BYTE( 0 ); // framestart - WRITE_BYTE( 0 ); // framerate - WRITE_BYTE( 10 ); // life - WRITE_BYTE( 80 ); // width - WRITE_BYTE( 80 ); // noise - WRITE_BYTE( 255 ); // r, g, b - WRITE_BYTE( 128 ); // r, g, b - WRITE_BYTE( 64 ); // r, g, b - WRITE_BYTE( 255 ); // brightness - WRITE_BYTE( 30 ); // speed - MESSAGE_END(); -*/ - } - - pev->frame = ((int)pev->frame + 1) % m_nFrames; -} - -void CNihilanthHVR ::ZapInit(CBaseEntity *pEnemy) -{ - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - SET_MODEL(edict(), "sprites/nhth1.spr"); - - pev->rendercolor.x = 255; - pev->rendercolor.y = 255; - pev->rendercolor.z = 255; - pev->scale = 2.0; - - pev->velocity = (pEnemy->pev->origin - pev->origin).Normalize() * 200; - - m_hEnemy = pEnemy; - SetThink(ZapThink); - SetTouch(ZapTouch); - pev->nextthink = gpGlobals->time + 0.1; - - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0, 100); -} - -void CNihilanthHVR ::ZapThink(void) -{ - pev->nextthink = gpGlobals->time + 0.05; - - // check world boundaries - if (m_hEnemy == NULL || pev->origin.x < -4096 || pev->origin.x > 4096 || pev->origin.y < -4096 || pev->origin.y > 4096 || pev->origin.z < -4096 || pev->origin.z > 4096) - { - SetTouch(NULL); - UTIL_Remove(this); - return; - } - - if (pev->velocity.Length() < 2000) - { - pev->velocity = pev->velocity * 1.2; - } - - // MovetoTarget( m_hEnemy->Center( ) ); - - if ((m_hEnemy->Center() - pev->origin).Length() < 256) - { - TraceResult tr; - - UTIL_TraceLine(pev->origin, m_hEnemy->Center(), dont_ignore_monsters, edict(), &tr); - - CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); - if (pEntity != NULL && pEntity->pev->takedamage) - { - ClearMultiDamage(); - pEntity->TraceAttack(pev, gSkillData.nihilanthZap, pev->velocity, &tr, DMG_SHOCK); - ApplyMultiDamage(pev, pev); - } - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_BEAMENTPOINT); - WRITE_SHORT(entindex()); - WRITE_COORD(tr.vecEndPos.x); - WRITE_COORD(tr.vecEndPos.y); - WRITE_COORD(tr.vecEndPos.z); - WRITE_SHORT(g_sModelIndexLaser); - WRITE_BYTE(0); // frame start - WRITE_BYTE(10); // framerate - WRITE_BYTE(3); // life - WRITE_BYTE(20); // width - WRITE_BYTE(20); // noise - WRITE_BYTE(64); // r, g, b - WRITE_BYTE(196); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // brightness - WRITE_BYTE(10); // speed - MESSAGE_END(); - - UTIL_EmitAmbientSound(edict(), tr.vecEndPos, "weapons/electro4.wav", 0.5, ATTN_NORM, 0, RANDOM_LONG(140, 160)); - - SetTouch(NULL); - UTIL_Remove(this); - pev->nextthink = gpGlobals->time + 0.2; - return; - } - - pev->frame = (int)(pev->frame + 1) % 11; - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex()); // entity, attachment - WRITE_COORD(pev->origin.x); // origin - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(128); // radius - WRITE_BYTE(128); // R - WRITE_BYTE(128); // G - WRITE_BYTE(255); // B - WRITE_BYTE(10); // life * 10 - WRITE_COORD(128); // decay - MESSAGE_END(); - - // Crawl( ); -} - -void CNihilanthHVR::ZapTouch(CBaseEntity *pOther) -{ - UTIL_EmitAmbientSound(edict(), pev->origin, "weapons/electro4.wav", 1.0, ATTN_NORM, 0, RANDOM_LONG(90, 95)); - - RadiusDamage(pev, pev, 50, CLASS_NONE, DMG_SHOCK); - pev->velocity = pev->velocity * 0; - - /* - for (int i = 0; i < 10; i++) - { - Crawl( ); - } - */ - - SetTouch(NULL); - UTIL_Remove(this); - pev->nextthink = gpGlobals->time + 0.2; -} - -void CNihilanthHVR ::TeleportInit(CNihilanth *pOwner, CBaseEntity *pEnemy, CBaseEntity *pTarget, CBaseEntity *pTouch) -{ - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - pev->rendercolor.x = 255; - pev->rendercolor.y = 255; - pev->rendercolor.z = 255; - pev->velocity.z *= 0.2; - - SET_MODEL(edict(), "sprites/exit1.spr"); - - m_pNihilanth = pOwner; - m_hEnemy = pEnemy; - m_hTargetEnt = pTarget; - m_hTouch = pTouch; - - SetThink(TeleportThink); - SetTouch(TeleportTouch); - pev->nextthink = gpGlobals->time + 0.1; - - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, "x/x_teleattack1.wav", 1, 0.2, 0, 100); -} - -void CNihilanthHVR ::GreenBallInit() -{ - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - pev->rendercolor.x = 255; - pev->rendercolor.y = 255; - pev->rendercolor.z = 255; - pev->scale = 1.0; - - SET_MODEL(edict(), "sprites/exit1.spr"); - - SetTouch(RemoveTouch); -} - -void CNihilanthHVR ::TeleportThink(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - // check world boundaries - if (m_hEnemy == NULL || !m_hEnemy->IsAlive() || pev->origin.x < -4096 || pev->origin.x > 4096 || pev->origin.y < -4096 || pev->origin.y > 4096 || pev->origin.z < -4096 || pev->origin.z > 4096) - { - STOP_SOUND(edict(), CHAN_WEAPON, "x/x_teleattack1.wav"); - UTIL_Remove(this); - return; - } - - if ((m_hEnemy->Center() - pev->origin).Length() < 128) - { - STOP_SOUND(edict(), CHAN_WEAPON, "x/x_teleattack1.wav"); - UTIL_Remove(this); - - if (m_hTargetEnt != NULL) - m_hTargetEnt->Use(m_hEnemy, m_hEnemy, USE_ON, 1.0); - - if (m_hTouch != NULL && m_hEnemy != NULL) - m_hTouch->Touch(m_hEnemy); - } - else - { - MovetoTarget(m_hEnemy->Center()); - } - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex()); // entity, attachment - WRITE_COORD(pev->origin.x); // origin - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(256); // radius - WRITE_BYTE(0); // R - WRITE_BYTE(255); // G - WRITE_BYTE(0); // B - WRITE_BYTE(10); // life * 10 - WRITE_COORD(256); // decay - MESSAGE_END(); - - pev->frame = (int)(pev->frame + 1) % 20; -} - -void CNihilanthHVR ::AbsorbInit(void) -{ - SetThink(DissipateThink); - pev->renderamt = 255; - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_BEAMENTS); - WRITE_SHORT(this->entindex()); - WRITE_SHORT(m_hTargetEnt->entindex() + 0x1000); - WRITE_SHORT(g_sModelIndexLaser); - WRITE_BYTE(0); // framestart - WRITE_BYTE(0); // framerate - WRITE_BYTE(50); // life - WRITE_BYTE(80); // width - WRITE_BYTE(80); // noise - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(128); // r, g, b - WRITE_BYTE(64); // r, g, b - WRITE_BYTE(255); // brightness - WRITE_BYTE(30); // speed - MESSAGE_END(); -} - -void CNihilanthHVR::TeleportTouch(CBaseEntity *pOther) -{ - CBaseEntity *pEnemy = m_hEnemy; - - if (pOther == pEnemy) - { - if (m_hTargetEnt != NULL) - m_hTargetEnt->Use(pEnemy, pEnemy, USE_ON, 1.0); - - if (m_hTouch != NULL && pEnemy != NULL) - m_hTouch->Touch(pEnemy); - } - else - { - m_pNihilanth->MakeFriend(pev->origin); - } - - SetTouch(NULL); - STOP_SOUND(edict(), CHAN_WEAPON, "x/x_teleattack1.wav"); - UTIL_Remove(this); -} - -void CNihilanthHVR ::DissipateThink(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - if (pev->scale > 5.0) - UTIL_Remove(this); - - pev->renderamt -= 2; - pev->scale += 0.1; - - if (m_hTargetEnt != NULL) - { - CircleTarget(m_hTargetEnt->pev->origin + Vector(0, 0, 4096)); - } - else - { - UTIL_Remove(this); - } - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_ELIGHT); - WRITE_SHORT(entindex()); // entity, attachment - WRITE_COORD(pev->origin.x); // origin - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(pev->renderamt); // radius - WRITE_BYTE(255); // R - WRITE_BYTE(192); // G - WRITE_BYTE(64); // B - WRITE_BYTE(2); // life * 10 - WRITE_COORD(0); // decay - MESSAGE_END(); -} - -BOOL CNihilanthHVR ::CircleTarget(Vector vecTarget) -{ - BOOL fClose = FALSE; - - Vector vecDest = vecTarget; - Vector vecEst = pev->origin + pev->velocity * 0.5; - Vector vecSrc = pev->origin; - vecDest.z = 0; - vecEst.z = 0; - vecSrc.z = 0; - float d1 = (vecDest - vecSrc).Length() - 24 * N_SCALE; - float d2 = (vecDest - vecEst).Length() - 24 * N_SCALE; - - if (m_vecIdeal == Vector(0, 0, 0)) - { - m_vecIdeal = pev->velocity; - } - - if (d1 < 0 && d2 <= d1) - { - // ALERT( at_console, "too close\n"); - m_vecIdeal = m_vecIdeal - (vecDest - vecSrc).Normalize() * 50; - } - else if (d1 > 0 && d2 >= d1) - { - // ALERT( at_console, "too far\n"); - m_vecIdeal = m_vecIdeal + (vecDest - vecSrc).Normalize() * 50; - } - pev->avelocity.z = d1 * 20; - - if (d1 < 32) - { - fClose = TRUE; - } - - m_vecIdeal = m_vecIdeal + Vector(RANDOM_FLOAT(-2, 2), RANDOM_FLOAT(-2, 2), RANDOM_FLOAT(-2, 2)); - m_vecIdeal = Vector(m_vecIdeal.x, m_vecIdeal.y, 0).Normalize() * 200 - /* + Vector( -m_vecIdeal.y, m_vecIdeal.x, 0 ).Normalize( ) * 32 */ - + Vector(0, 0, m_vecIdeal.z); - // m_vecIdeal = m_vecIdeal + Vector( -m_vecIdeal.y, m_vecIdeal.x, 0 ).Normalize( ) * 2; - - // move up/down - d1 = vecTarget.z - pev->origin.z; - if (d1 > 0 && m_vecIdeal.z < 200) - m_vecIdeal.z += 20; - else if (d1 < 0 && m_vecIdeal.z > -200) - m_vecIdeal.z -= 20; - - pev->velocity = m_vecIdeal; - - // ALERT( at_console, "%.0f %.0f %.0f\n", m_vecIdeal.x, m_vecIdeal.y, m_vecIdeal.z ); - return fClose; -} - -void CNihilanthHVR ::MovetoTarget(Vector vecTarget) -{ - if (m_vecIdeal == Vector(0, 0, 0)) - { - m_vecIdeal = pev->velocity; - } - - // accelerate - float flSpeed = m_vecIdeal.Length(); - if (flSpeed > 300) - { - m_vecIdeal = m_vecIdeal.Normalize() * 300; - } - m_vecIdeal = m_vecIdeal + (vecTarget - pev->origin).Normalize() * 300; - pev->velocity = m_vecIdeal; -} - -void CNihilanthHVR ::Crawl(void) -{ - - Vector vecAim = Vector(RANDOM_FLOAT(-1, 1), RANDOM_FLOAT(-1, 1), RANDOM_FLOAT(-1, 1)).Normalize(); - Vector vecPnt = pev->origin + pev->velocity * 0.2 + vecAim * 128; - - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_BEAMENTPOINT); - WRITE_SHORT(entindex()); - WRITE_COORD(vecPnt.x); - WRITE_COORD(vecPnt.y); - WRITE_COORD(vecPnt.z); - WRITE_SHORT(g_sModelIndexLaser); - WRITE_BYTE(0); // frame start - WRITE_BYTE(10); // framerate - WRITE_BYTE(3); // life - WRITE_BYTE(20); // width - WRITE_BYTE(80); // noise - WRITE_BYTE(64); // r, g, b - WRITE_BYTE(128); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // brightness - WRITE_BYTE(10); // speed - MESSAGE_END(); -} - -void CNihilanthHVR::RemoveTouch(CBaseEntity *pOther) -{ - STOP_SOUND(edict(), CHAN_WEAPON, "x/x_teleattack1.wav"); - UTIL_Remove(this); -} - -void CNihilanthHVR::BounceTouch(CBaseEntity *pOther) -{ - Vector vecDir = m_vecIdeal.Normalize(); - - TraceResult tr = UTIL_GetGlobalTrace(); - - float n = -DotProduct(tr.vecPlaneNormal, vecDir); - - vecDir = 2.0 * tr.vecPlaneNormal * n + vecDir; - - m_vecIdeal = vecDir * m_vecIdeal.Length(); -} - -#endif \ No newline at end of file diff --git a/dlls/Half-life/osprey.cpp b/dlls/Half-life/osprey.cpp deleted file mode 100644 index c524f532..00000000 --- a/dlls/Half-life/osprey.cpp +++ /dev/null @@ -1,776 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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" - -typedef struct -{ - int isValid; - EHANDLE hGrunt; - Vector vecOrigin; - Vector vecAngles; -} t_ospreygrunt; - -#define SF_WAITFORTRIGGER 0x40 - -#define MAX_CARRY 24 - -class COsprey : public CBaseMonster -{ -public: - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - int ObjectCaps(void) { return CBaseMonster ::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - void Spawn(void); - void Precache(void); - int Classify(void) { return CLASS_MACHINE; }; - int BloodColor(void) { return DONT_BLEED; } - void Killed(entvars_t *pevAttacker, int iGib); - - void UpdateGoal(void); - BOOL HasDead(void); - void EXPORT FlyThink(void); - void EXPORT DeployThink(void); - void Flight(void); - void EXPORT HitTouch(CBaseEntity *pOther); - void EXPORT FindAllThink(void); - void EXPORT HoverThink(void); - CBaseMonster *MakeGrunt(Vector vecSrc); - void EXPORT CrashTouch(CBaseEntity *pOther); - void EXPORT DyingThink(void); - void EXPORT CommandUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - - // int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType ); - void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - void ShowDamage(void); - - CBaseEntity *m_pGoalEnt; - Vector m_vel1; - Vector m_vel2; - Vector m_pos1; - Vector m_pos2; - Vector m_ang1; - Vector m_ang2; - float m_startTime; - float m_dTime; - - Vector m_velocity; - - float m_flIdealtilt; - float m_flRotortilt; - - float m_flRightHealth; - float m_flLeftHealth; - - int m_iUnits; - EHANDLE m_hGrunt[MAX_CARRY]; - Vector m_vecOrigin[MAX_CARRY]; - EHANDLE m_hRepel[4]; - - int m_iSoundState; - int m_iSpriteTexture; - - int m_iPitch; - - int m_iExplode; - int m_iTailGibs; - int m_iBodyGibs; - int m_iEngineGibs; - - int m_iDoLeftSmokePuff; - int m_iDoRightSmokePuff; -}; - -LINK_ENTITY_TO_CLASS(monster_osprey, COsprey); - -TYPEDESCRIPTION COsprey::m_SaveData[] = - { - DEFINE_FIELD(COsprey, m_pGoalEnt, FIELD_CLASSPTR), - DEFINE_FIELD(COsprey, m_vel1, FIELD_VECTOR), - DEFINE_FIELD(COsprey, m_vel2, FIELD_VECTOR), - DEFINE_FIELD(COsprey, m_pos1, FIELD_POSITION_VECTOR), - DEFINE_FIELD(COsprey, m_pos2, FIELD_POSITION_VECTOR), - DEFINE_FIELD(COsprey, m_ang1, FIELD_VECTOR), - DEFINE_FIELD(COsprey, m_ang2, FIELD_VECTOR), - - DEFINE_FIELD(COsprey, m_startTime, FIELD_TIME), - DEFINE_FIELD(COsprey, m_dTime, FIELD_FLOAT), - DEFINE_FIELD(COsprey, m_velocity, FIELD_VECTOR), - - DEFINE_FIELD(COsprey, m_flIdealtilt, FIELD_FLOAT), - DEFINE_FIELD(COsprey, m_flRotortilt, FIELD_FLOAT), - - DEFINE_FIELD(COsprey, m_flRightHealth, FIELD_FLOAT), - DEFINE_FIELD(COsprey, m_flLeftHealth, FIELD_FLOAT), - - DEFINE_FIELD(COsprey, m_iUnits, FIELD_INTEGER), - DEFINE_ARRAY(COsprey, m_hGrunt, FIELD_EHANDLE, MAX_CARRY), - DEFINE_ARRAY(COsprey, m_vecOrigin, FIELD_POSITION_VECTOR, MAX_CARRY), - DEFINE_ARRAY(COsprey, m_hRepel, FIELD_EHANDLE, 4), - - // DEFINE_FIELD( COsprey, m_iSoundState, FIELD_INTEGER ), - // DEFINE_FIELD( COsprey, m_iSpriteTexture, FIELD_INTEGER ), - // DEFINE_FIELD( COsprey, m_iPitch, FIELD_INTEGER ), - - DEFINE_FIELD(COsprey, m_iDoLeftSmokePuff, FIELD_INTEGER), - DEFINE_FIELD(COsprey, m_iDoRightSmokePuff, FIELD_INTEGER), -}; -IMPLEMENT_SAVERESTORE(COsprey, CBaseMonster); - -void COsprey ::Spawn(void) -{ - Precache(); - // motor - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_BBOX; - - SET_MODEL(ENT(pev), "models/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(FindAllThink); - SetUse(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 COsprey::Precache(void) -{ - UTIL_PrecacheOther("monster_human_grunt"); - - PRECACHE_MODEL("models/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/osprey_tailgibs.mdl"); - m_iBodyGibs = PRECACHE_MODEL("models/osprey_bodygibs.mdl"); - m_iEngineGibs = PRECACHE_MODEL("models/osprey_enginegibs.mdl"); -} - -void COsprey::CommandUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - pev->nextthink = gpGlobals->time + 0.1; -} - -void COsprey ::FindAllThink(void) -{ - CBaseEntity *pEntity = NULL; - - m_iUnits = 0; - while (m_iUnits < MAX_CARRY && (pEntity = UTIL_FindEntityByClassname(pEntity, "monster_human_grunt")) != 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 grunts to resupply\n"); - UTIL_Remove(this); - return; - } - SetThink(FlyThink); - pev->nextthink = gpGlobals->time + 0.1; - m_startTime = gpGlobals->time; -} - -void COsprey ::DeployThink(void) -{ - UTIL_MakeAimVectors(pev->angles); - - Vector vecForward = gpGlobals->v_forward; - Vector vecRight = gpGlobals->v_right; - Vector vecUp = gpGlobals->v_up; - - Vector vecSrc; - - TraceResult tr; - UTIL_TraceLine(pev->origin, pev->origin + Vector(0, 0, -4096.0), ignore_monsters, ENT(pev), &tr); - CSoundEnt::InsertSound(bits_SOUND_DANGER, tr.vecEndPos, 400, 0.3); - - vecSrc = pev->origin + vecForward * 32 + vecRight * 100 + vecUp * -96; - m_hRepel[0] = MakeGrunt(vecSrc); - - vecSrc = pev->origin + vecForward * -64 + vecRight * 100 + vecUp * -96; - m_hRepel[1] = MakeGrunt(vecSrc); - - vecSrc = pev->origin + vecForward * 32 + vecRight * -100 + vecUp * -96; - m_hRepel[2] = MakeGrunt(vecSrc); - - vecSrc = pev->origin + vecForward * -64 + vecRight * -100 + vecUp * -96; - m_hRepel[3] = MakeGrunt(vecSrc); - - SetThink(HoverThink); - pev->nextthink = gpGlobals->time + 0.1; -} - -BOOL COsprey ::HasDead() -{ - for (int i = 0; i < m_iUnits; i++) - { - if (m_hGrunt[i] == NULL || !m_hGrunt[i]->IsAlive()) - { - return TRUE; - } - else - { - m_vecOrigin[i] = m_hGrunt[i]->pev->origin; // send them to where they died - } - } - return FALSE; -} - -CBaseMonster *COsprey ::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_human_grunt", 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(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; -} - -void COsprey ::HoverThink(void) -{ - int i; - for (i = 0; i < 4; i++) - { - if (m_hRepel[i] != NULL && m_hRepel[i]->pev->health > 0 && !(m_hRepel[i]->pev->flags & FL_ONGROUND)) - { - break; - } - } - - if (i == 4) - { - m_startTime = gpGlobals->time; - SetThink(FlyThink); - } - - pev->nextthink = gpGlobals->time + 0.1; - UTIL_MakeAimVectors(pev->angles); - ShowDamage(); -} - -void COsprey::UpdateGoal() -{ - if (m_pGoalEnt) - { - m_pos1 = m_pos2; - m_ang1 = m_ang2; - m_vel1 = m_vel2; - m_pos2 = m_pGoalEnt->pev->origin; - m_ang2 = m_pGoalEnt->pev->angles; - UTIL_MakeAimVectors(Vector(0, m_ang2.y, 0)); - m_vel2 = gpGlobals->v_forward * m_pGoalEnt->pev->speed; - - m_startTime = m_startTime + m_dTime; - m_dTime = 2.0 * (m_pos1 - m_pos2).Length() / (m_vel1.Length() + m_pGoalEnt->pev->speed); - - if (m_ang1.y - m_ang2.y < -180) - { - m_ang1.y += 360; - } - else if (m_ang1.y - m_ang2.y > 180) - { - m_ang1.y -= 360; - } - - if (m_pGoalEnt->pev->speed < 400) - m_flIdealtilt = 0; - else - m_flIdealtilt = -90; - } - else - { - ALERT(at_console, "osprey missing target"); - } -} - -void COsprey::FlyThink(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - if (m_pGoalEnt == NULL && !FStringNull(pev->target)) // this monster has a target - { - m_pGoalEnt = CBaseEntity::Instance(FIND_ENTITY_BY_TARGETNAME(NULL, STRING(pev->target))); - UpdateGoal(); - } - - if (gpGlobals->time > m_startTime + m_dTime) - { - if (m_pGoalEnt->pev->speed == 0) - { - SetThink(DeployThink); - } - do - { - m_pGoalEnt = CBaseEntity::Instance(FIND_ENTITY_BY_TARGETNAME(NULL, STRING(m_pGoalEnt->pev->target))); - } while (m_pGoalEnt->pev->speed < 400 && !HasDead()); - UpdateGoal(); - } - - Flight(); - ShowDamage(); -} - -void COsprey::Flight() -{ - float t = (gpGlobals->time - m_startTime); - float scale = 1.0 / m_dTime; - - float f = UTIL_SplineFraction(t * scale, 1.0); - - Vector pos = (m_pos1 + m_vel1 * t) * (1.0 - f) + (m_pos2 - m_vel2 * (m_dTime - t)) * f; - Vector ang = (m_ang1) * (1.0 - f) + (m_ang2)*f; - m_velocity = m_vel1 * (1.0 - f) + m_vel2 * f; - - UTIL_SetOrigin(pev, pos); - pev->angles = ang; - UTIL_MakeAimVectors(pev->angles); - float flSpeed = DotProduct(gpGlobals->v_forward, m_velocity); - - // float flSpeed = DotProduct( gpGlobals->v_forward, pev->velocity ); - - float m_flIdealtilt = (160 - flSpeed) / 10.0; - - // ALERT( at_console, "%f %f\n", flSpeed, flIdealtilt ); - if (m_flRotortilt < m_flIdealtilt) - { - m_flRotortilt += 0.5; - if (m_flRotortilt > 0) - m_flRotortilt = 0; - } - if (m_flRotortilt > m_flIdealtilt) - { - m_flRotortilt -= 0.5; - if (m_flRotortilt < -90) - m_flRotortilt = -90; - } - SetBoneController(0, m_flRotortilt); - - if (m_iSoundState == 0) - { - EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_rotor4.wav", 1.0, 0.15, 0, 110); - // EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_whine1.wav", 0.5, 0.2, 0, 110 ); - - m_iSoundState = SND_CHANGE_PITCH; // hack for going through level transitions - } - else - { - CBaseEntity *pPlayer = NULL; - - pPlayer = UTIL_FindEntityByClassname(NULL, "player"); - // UNDONE: this needs to send different sounds to every player for multiplayer. - if (pPlayer) - { - float pitch = DotProduct(m_velocity - pPlayer->pev->velocity, (pPlayer->pev->origin - pev->origin).Normalize()); - - pitch = (int)(100 + pitch / 75.0); - - if (pitch > 250) - pitch = 250; - if (pitch < 50) - pitch = 50; - - if (pitch == 100) - pitch = 101; - - if (pitch != m_iPitch) - { - m_iPitch = pitch; - EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_rotor4.wav", 1.0, 0.15, SND_CHANGE_PITCH | SND_CHANGE_VOL, pitch); - // ALERT( at_console, "%.0f\n", pitch ); - } - } - // EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_whine1.wav", flVol, 0.2, SND_CHANGE_PITCH | SND_CHANGE_VOL, pitch); - } -} - -void COsprey::HitTouch(CBaseEntity *pOther) -{ - pev->nextthink = gpGlobals->time + 2.0; -} - -/* -int COsprey::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) -{ - if (m_flRotortilt <= -90) - { - m_flRotortilt = 0; - } - else - { - m_flRotortilt -= 45; - } - SetBoneController( 0, m_flRotortilt ); - return 0; -} -*/ - -void COsprey ::Killed(entvars_t *pevAttacker, int iGib) -{ - pev->movetype = MOVETYPE_TOSS; - pev->gravity = 0.3; - pev->velocity = m_velocity; - pev->avelocity = Vector(RANDOM_FLOAT(-20, 20), 0, RANDOM_FLOAT(-50, 50)); - STOP_SOUND(ENT(pev), CHAN_STATIC, "apache/ap_rotor4.wav"); - - UTIL_SetSize(pev, Vector(-32, -32, -64), Vector(32, 32, 0)); - SetThink(DyingThink); - SetTouch(CrashTouch); - pev->nextthink = gpGlobals->time + 0.1; - pev->health = 0; - pev->takedamage = DAMAGE_NO; - - m_startTime = gpGlobals->time + 4.0; -} - -void COsprey::CrashTouch(CBaseEntity *pOther) -{ - // only crash if we hit something solid - if (pOther->pev->solid == SOLID_BSP) - { - SetTouch(NULL); - m_startTime = gpGlobals->time; - pev->nextthink = gpGlobals->time; - m_velocity = pev->velocity; - } -} - -void COsprey ::DyingThink(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - pev->avelocity = pev->avelocity * 1.02; - - // still falling? - if (m_startTime > gpGlobals->time) - { - UTIL_MakeAimVectors(pev->angles); - ShowDamage(); - - Vector vecSpot = pev->origin + pev->velocity * 0.2; - - // random explosions - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSpot); - WRITE_BYTE(TE_EXPLOSION); // This just makes a dynamic light now - WRITE_COORD(vecSpot.x + RANDOM_FLOAT(-150, 150)); - WRITE_COORD(vecSpot.y + RANDOM_FLOAT(-150, 150)); - WRITE_COORD(vecSpot.z + RANDOM_FLOAT(-150, -50)); - WRITE_SHORT(g_sModelIndexFireball); - WRITE_BYTE(RANDOM_LONG(0, 29) + 30); // scale * 10 - WRITE_BYTE(12); // framerate - WRITE_BYTE(TE_EXPLFLAG_NONE); - MESSAGE_END(); - - // lots of smoke - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSpot); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(vecSpot.x + RANDOM_FLOAT(-150, 150)); - WRITE_COORD(vecSpot.y + RANDOM_FLOAT(-150, 150)); - WRITE_COORD(vecSpot.z + RANDOM_FLOAT(-150, -50)); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(100); // scale * 10 - WRITE_BYTE(10); // framerate - MESSAGE_END(); - - vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5; - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSpot); - WRITE_BYTE(TE_BREAKMODEL); - - // position - WRITE_COORD(vecSpot.x); - WRITE_COORD(vecSpot.y); - WRITE_COORD(vecSpot.z); - - // size - WRITE_COORD(800); - WRITE_COORD(800); - WRITE_COORD(132); - - // velocity - WRITE_COORD(pev->velocity.x); - WRITE_COORD(pev->velocity.y); - WRITE_COORD(pev->velocity.z); - - // randomization - WRITE_BYTE(50); - - // Model - WRITE_SHORT(m_iTailGibs); //model id# - - // # of shards - WRITE_BYTE(8); // let client decide - - // duration - WRITE_BYTE(200); // 10.0 seconds - - // flags - - WRITE_BYTE(BREAK_METAL); - MESSAGE_END(); - - // don't stop it we touch a entity - pev->flags &= ~FL_ONGROUND; - pev->nextthink = gpGlobals->time + 0.2; - return; - } - else - { - Vector vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5; - - /* - MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); - WRITE_BYTE( TE_EXPLOSION); // This just makes a dynamic light now - WRITE_COORD( vecSpot.x ); - WRITE_COORD( vecSpot.y ); - WRITE_COORD( vecSpot.z + 512 ); - WRITE_SHORT( m_iExplode ); - WRITE_BYTE( 250 ); // scale * 10 - WRITE_BYTE( 10 ); // framerate - MESSAGE_END(); - */ - - // gibs - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSpot); - WRITE_BYTE(TE_SPRITE); - WRITE_COORD(vecSpot.x); - WRITE_COORD(vecSpot.y); - WRITE_COORD(vecSpot.z + 512); - WRITE_SHORT(m_iExplode); - WRITE_BYTE(250); // scale * 10 - WRITE_BYTE(255); // brightness - MESSAGE_END(); - - /* - MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); - WRITE_BYTE( TE_SMOKE ); - WRITE_COORD( vecSpot.x ); - WRITE_COORD( vecSpot.y ); - WRITE_COORD( vecSpot.z + 300 ); - WRITE_SHORT( g_sModelIndexSmoke ); - WRITE_BYTE( 250 ); // scale * 10 - WRITE_BYTE( 6 ); // framerate - MESSAGE_END(); - */ - - // blast circle - MESSAGE_BEGIN(MSG_PAS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(TE_BEAMCYLINDER); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z); - WRITE_COORD(pev->origin.x); - WRITE_COORD(pev->origin.y); - WRITE_COORD(pev->origin.z + 2000); // reach damage radius over .2 seconds - WRITE_SHORT(m_iSpriteTexture); - WRITE_BYTE(0); // startframe - WRITE_BYTE(0); // framerate - WRITE_BYTE(4); // life - WRITE_BYTE(32); // width - WRITE_BYTE(0); // noise - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(192); // r, g, b - WRITE_BYTE(128); // brightness - WRITE_BYTE(0); // speed - MESSAGE_END(); - - EMIT_SOUND(ENT(pev), CHAN_STATIC, "weapons/mortarhit.wav", 1.0, 0.3); - - RadiusDamage(pev->origin, pev, pev, 300, CLASS_NONE, DMG_BLAST); - - // gibs - vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5; - MESSAGE_BEGIN(MSG_PAS, SVC_TEMPENTITY, vecSpot); - WRITE_BYTE(TE_BREAKMODEL); - - // position - WRITE_COORD(vecSpot.x); - WRITE_COORD(vecSpot.y); - WRITE_COORD(vecSpot.z + 64); - - // size - WRITE_COORD(800); - WRITE_COORD(800); - WRITE_COORD(128); - - // velocity - WRITE_COORD(m_velocity.x); - WRITE_COORD(m_velocity.y); - WRITE_COORD(fabs(m_velocity.z) * 0.25); - - // randomization - WRITE_BYTE(40); - - // Model - WRITE_SHORT(m_iBodyGibs); //model id# - - // # of shards - WRITE_BYTE(128); - - // duration - WRITE_BYTE(200); // 10.0 seconds - - // flags - - WRITE_BYTE(BREAK_METAL); - MESSAGE_END(); - - UTIL_Remove(this); - } -} - -void COsprey ::ShowDamage(void) -{ - if (m_iDoLeftSmokePuff > 0 || RANDOM_LONG(0, 99) > m_flLeftHealth) - { - Vector vecSrc = pev->origin + gpGlobals->v_right * -340; - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSrc); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(vecSrc.x); - WRITE_COORD(vecSrc.y); - WRITE_COORD(vecSrc.z); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(RANDOM_LONG(0, 9) + 20); // scale * 10 - WRITE_BYTE(12); // framerate - MESSAGE_END(); - if (m_iDoLeftSmokePuff > 0) - m_iDoLeftSmokePuff--; - } - if (m_iDoRightSmokePuff > 0 || RANDOM_LONG(0, 99) > m_flRightHealth) - { - Vector vecSrc = pev->origin + gpGlobals->v_right * 340; - MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSrc); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(vecSrc.x); - WRITE_COORD(vecSrc.y); - WRITE_COORD(vecSrc.z); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(RANDOM_LONG(0, 9) + 20); // scale * 10 - WRITE_BYTE(12); // framerate - MESSAGE_END(); - if (m_iDoRightSmokePuff > 0) - m_iDoRightSmokePuff--; - } -} - -void COsprey::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - // ALERT( at_console, "%d %.0f\n", ptr->iHitgroup, flDamage ); - - // only so much per engine - if (ptr->iHitgroup == 3) - { - if (m_flRightHealth < 0) - return; - else - m_flRightHealth -= flDamage; - m_iDoLeftSmokePuff = 3 + (flDamage / 5.0); - } - - if (ptr->iHitgroup == 2) - { - if (m_flLeftHealth < 0) - return; - else - m_flLeftHealth -= flDamage; - m_iDoRightSmokePuff = 3 + (flDamage / 5.0); - } - - // hit hard, hits cockpit, hits engines - if (flDamage > 50 || ptr->iHitgroup == 1 || ptr->iHitgroup == 2 || ptr->iHitgroup == 3) - { - // ALERT( at_console, "%.0f\n", flDamage ); - AddMultiDamage(pevAttacker, this, flDamage, bitsDamageType); - } - else - { - UTIL_Sparks(ptr->vecEndPos); - } -} diff --git a/dlls/Half-life/python.cpp b/dlls/Half-life/python.cpp deleted file mode 100644 index b75c3503..00000000 --- a/dlls/Half-life/python.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "weapons.h" -#include "monsters.h" -#include "player.h" -#include "gamerules.h" - -enum python_e -{ - PYTHON_IDLE1 = 0, - PYTHON_FIDGET, - PYTHON_FIRE1, - PYTHON_RELOAD, - PYTHON_HOLSTER, - PYTHON_DRAW, - PYTHON_IDLE2, - PYTHON_IDLE3 -}; - -class CPython : public CBasePlayerWeapon -{ -public: - void Spawn(void); - void Precache(void); - int iItemSlot(void) { return 2; } - int GetItemInfo(ItemInfo *p); - int AddToPlayer(CBasePlayer *pPlayer); - void PrimaryAttack(void); - void SecondaryAttack(void); - BOOL Deploy(void); - void Holster(int skiplocal = 0); - void Reload(void); - void WeaponIdle(void); - float m_flSoundDelay; - - BOOL m_fInZoom; // don't save this. -private: - unsigned short m_usFirePython; -}; -LINK_ENTITY_TO_CLASS(weapon_python, CPython); -LINK_ENTITY_TO_CLASS(weapon_357, CPython); - -int CPython::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "357"; - p->iMaxAmmo1 = _357_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = PYTHON_MAX_CLIP; - p->iFlags = 0; - p->iSlot = 1; - p->iPosition = 1; - p->iId = m_iId = WEAPON_PYTHON; - p->iWeight = PYTHON_WEIGHT; - - return 1; -} - -int CPython::AddToPlayer(CBasePlayer *pPlayer) -{ - if (CBasePlayerWeapon::AddToPlayer(pPlayer)) - { - MESSAGE_BEGIN(MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev); - WRITE_BYTE(m_iId); - MESSAGE_END(); - return TRUE; - } - return FALSE; -} - -void CPython::Spawn() -{ - pev->classname = MAKE_STRING("weapon_357"); // hack to allow for old names - Precache(); - m_iId = WEAPON_PYTHON; - SET_MODEL(ENT(pev), "models/w_357.mdl"); - - m_iDefaultAmmo = PYTHON_DEFAULT_GIVE; - - FallInit(); // get ready to fall down. -} - -void CPython::Precache(void) -{ - PRECACHE_MODEL("models/v_357.mdl"); - PRECACHE_MODEL("models/w_357.mdl"); - PRECACHE_MODEL("models/p_357.mdl"); - - PRECACHE_MODEL("models/w_357ammobox.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - - PRECACHE_SOUND("weapons/357_reload1.wav"); - PRECACHE_SOUND("weapons/357_cock1.wav"); - PRECACHE_SOUND("weapons/357_shot1.wav"); - PRECACHE_SOUND("weapons/357_shot2.wav"); - - m_usFirePython = PRECACHE_EVENT(1, "events/python.sc"); -} - -BOOL CPython::Deploy() -{ - if (g_pGameRules->IsMultiplayer()) - { - // enable laser sight geometry. - pev->body = 1; - } - else - { - pev->body = 0; - } - - return DefaultDeploy("models/v_357.mdl", "models/p_357.mdl", PYTHON_DRAW, "python"); -} - -void CPython::Holster(int skiplocal /* = 0 */) -{ - m_fInReload = FALSE; // cancel any reload in progress. - - if (m_fInZoom) - { - SecondaryAttack(); - } - - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0; - m_flTimeWeaponIdle = gpGlobals->time + 10 + RANDOM_FLOAT(0, 5); - SendWeaponAnim(PYTHON_HOLSTER); -} - -void CPython::SecondaryAttack(void) -{ - if (!g_pGameRules->IsMultiplayer()) - { - return; - } - - if (m_fInZoom) - { - m_fInZoom = FALSE; - m_pPlayer->m_iFOV = 0; // 0 means reset to default fov - } - else - { - m_fInZoom = TRUE; - m_pPlayer->m_iFOV = 40; - } - - m_flNextSecondaryAttack = gpGlobals->time + 0.5; -} - -void CPython::PrimaryAttack() -{ - // don't fire underwater - if (m_pPlayer->pev->waterlevel == 3) - { - PlayEmptySound(); - m_flNextPrimaryAttack = gpGlobals->time + 0.15; - return; - } - - if (m_iClip <= 0) - { - if (!m_fFireOnEmpty) - Reload(); - else - { - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/357_cock1.wav", 0.8, ATTN_NORM); - m_flNextPrimaryAttack = gpGlobals->time + 0.15; - } - - return; - } - - PLAYBACK_EVENT(0, m_pPlayer->edict(), m_usFirePython); - - m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; - m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH; - - m_iClip--; - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; - - UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle); - - Vector vecSrc = m_pPlayer->GetGunPosition(); - Vector vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_10DEGREES); - m_pPlayer->FireBullets(1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 8192, BULLET_PLAYER_357, 0); - - if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - // HEV suit - indicate out of ammo condition - m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - - m_flNextPrimaryAttack = gpGlobals->time + 0.75; - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); -} - -void CPython::Reload(void) -{ - if (m_fInZoom) - { - m_fInZoom = FALSE; - m_pPlayer->m_iFOV = 0; // 0 means reset to default fov - } - - if (DefaultReload(6, PYTHON_RELOAD, 2.0)) - { - m_flSoundDelay = gpGlobals->time + 1.5; - } -} - -void CPython::WeaponIdle(void) -{ - ResetEmptySound(); - - m_pPlayer->GetAutoaimVector(AUTOAIM_10DEGREES); - - // ALERT( at_console, "%.2f\n", gpGlobals->time - m_flSoundDelay ); - if (m_flSoundDelay != 0 && m_flSoundDelay <= gpGlobals->time) - { - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/357_reload1.wav", RANDOM_FLOAT(0.8, 0.9), ATTN_NORM); - m_flSoundDelay = 0; - } - - if (m_flTimeWeaponIdle > gpGlobals->time) - return; - - int iAnim; - float flRand = RANDOM_FLOAT(0, 1); - if (flRand <= 0.5) - { - iAnim = PYTHON_IDLE1; - m_flTimeWeaponIdle = gpGlobals->time + (70.0 / 30.0); - } - else if (flRand <= 0.7) - { - iAnim = PYTHON_IDLE2; - m_flTimeWeaponIdle = gpGlobals->time + (60.0 / 30.0); - } - else if (flRand <= 0.9) - { - iAnim = PYTHON_IDLE3; - m_flTimeWeaponIdle = gpGlobals->time + (88.0 / 30.0); - } - else - { - iAnim = PYTHON_FIDGET; - m_flTimeWeaponIdle = gpGlobals->time + (170.0 / 30.0); - } - SendWeaponAnim(iAnim); -} - -class CPythonAmmo : public CBasePlayerAmmo -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_357ammobox.mdl"); - CBasePlayerAmmo::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_357ammobox.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - } - BOOL AddAmmo(CBaseEntity *pOther) - { - if (pOther->GiveAmmo(AMMO_357BOX_GIVE, "357", _357_MAX_CARRY) != -1) - { - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); - return TRUE; - } - return FALSE; - } -}; -LINK_ENTITY_TO_CLASS(ammo_357, CPythonAmmo); - -#endif \ No newline at end of file diff --git a/dlls/Half-life/roach.cpp b/dlls/Half-life/roach.cpp deleted file mode 100644 index d5aa965b..00000000 --- a/dlls/Half-life/roach.cpp +++ /dev/null @@ -1,460 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// cockroach -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" -#include "soundent.h" -#include "decals.h" - -#define ROACH_IDLE 0 -#define ROACH_BORED 1 -#define ROACH_SCARED_BY_ENT 2 -#define ROACH_SCARED_BY_LIGHT 3 -#define ROACH_SMELL_FOOD 4 -#define ROACH_EAT 5 - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -class CRoach : public CBaseMonster -{ -public: - void Spawn( void ); - void Precache( void ); - void SetYawSpeed( void ); - void EXPORT MonsterThink ( void ); - void Move ( float flInterval ); - void PickNewDest ( int iCondition ); - void EXPORT Touch ( CBaseEntity *pOther ); - void Killed( entvars_t *pevAttacker, int iGib ); - - float m_flLastLightLevel; - float m_flNextSmellTime; - int Classify ( void ); - void Look ( int iDistance ); - int ISoundMask ( void ); - - // UNDONE: These don't necessarily need to be save/restored, but if we add more data, it may - BOOL m_fLightHacked; - int m_iMode; - // ----------------------------- -}; -LINK_ENTITY_TO_CLASS( monster_cockroach, CRoach ); - -//========================================================= -// ISoundMask - returns a bit mask indicating which types -// of sounds this monster regards. In the base class implementation, -// monsters care about all sounds, but no scents. -//========================================================= -int CRoach :: ISoundMask ( void ) -{ - return bits_SOUND_CARCASS | bits_SOUND_MEAT; -} - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CRoach :: Classify ( void ) -{ - return CLASS_INSECT; -} - -//========================================================= -// Touch -//========================================================= -void CRoach :: Touch ( CBaseEntity *pOther ) -{ - Vector vecSpot; - TraceResult tr; - - if ( pOther->pev->velocity == g_vecZero || !pOther->IsPlayer() ) - { - return; - } - - vecSpot = pev->origin + Vector ( 0 , 0 , 8 );//move up a bit, and trace down. - UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -24 ), ignore_monsters, ENT(pev), & tr); - - // This isn't really blood. So you don't have to screen it out based on violence levels (UTIL_ShouldShowBlood()) - UTIL_DecalTrace( &tr, DECAL_YBLOOD1 +RANDOM_LONG(0,5) ); - - TakeDamage( pOther->pev, pOther->pev, pev->health, DMG_CRUSH ); -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CRoach :: SetYawSpeed ( void ) -{ - int ys; - - ys = 120; - - pev->yaw_speed = ys; -} - -//========================================================= -// Spawn -//========================================================= -void CRoach :: Spawn() -{ - Precache( ); - - SET_MODEL(ENT(pev), "models/roach.mdl"); - UTIL_SetSize( pev, Vector( -1, -1, 0 ), Vector( 1, 1, 1 ) ); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_YELLOW; - pev->effects = 0; - pev->health = 1; - m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - - MonsterInit(); - SetActivity ( ACT_IDLE ); - - pev->view_ofs = Vector ( 0, 0, 1 );// position of the eyes relative to monster's origin. - pev->takedamage = DAMAGE_YES; - m_fLightHacked = FALSE; - m_flLastLightLevel = -1; - m_iMode = ROACH_IDLE; - m_flNextSmellTime = gpGlobals->time; -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CRoach :: Precache() -{ - PRECACHE_MODEL("models/roach.mdl"); - - PRECACHE_SOUND("roach/rch_die.wav"); - PRECACHE_SOUND("roach/rch_walk.wav"); - PRECACHE_SOUND("roach/rch_smash.wav"); -} - - -//========================================================= -// Killed. -//========================================================= -void CRoach :: Killed( entvars_t *pevAttacker, int iGib ) -{ - pev->solid = SOLID_NOT; - - //random sound - if ( RANDOM_LONG(0,4) == 1 ) - { - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "roach/rch_die.wav", 0.8, ATTN_NORM, 0, 80 + RANDOM_LONG(0,39) ); - } - else - { - EMIT_SOUND_DYN(ENT(pev), CHAN_BODY, "roach/rch_smash.wav", 0.7, ATTN_NORM, 0, 80 + RANDOM_LONG(0,39) ); - } - - CSoundEnt::InsertSound ( bits_SOUND_WORLD, pev->origin, 128, 1 ); - - CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner); - if ( pOwner ) - { - pOwner->DeathNotice( pev ); - } - UTIL_Remove( this ); -} - -//========================================================= -// MonsterThink, overridden for roaches. -//========================================================= -void CRoach :: MonsterThink( void ) -{ - if ( FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) ) - pev->nextthink = gpGlobals->time + RANDOM_FLOAT(1,1.5); - else - pev->nextthink = gpGlobals->time + 0.1;// keep monster thinking - - float flInterval = StudioFrameAdvance( ); // animate - - if ( !m_fLightHacked ) - { - // if light value hasn't been collection for the first time yet, - // suspend the creature for a second so the world finishes spawning, then we'll collect the light level. - pev->nextthink = gpGlobals->time + 1; - m_fLightHacked = TRUE; - return; - } - else if ( m_flLastLightLevel < 0 ) - { - // collect light level for the first time, now that all of the lightmaps in the roach's area have been calculated. - m_flLastLightLevel = GETENTITYILLUM( ENT( pev ) ); - } - - switch ( m_iMode ) - { - case ROACH_IDLE: - case ROACH_EAT: - { - // if not moving, sample environment to see if anything scary is around. Do a radius search 'look' at random. - if ( RANDOM_LONG(0,3) == 1 ) - { - Look( 150 ); - if (HasConditions(bits_COND_SEE_FEAR)) - { - // if see something scary - //ALERT ( at_aiconsole, "Scared\n" ); - Eat( 30 + ( RANDOM_LONG(0,14) ) );// roach will ignore food for 30 to 45 seconds - PickNewDest( ROACH_SCARED_BY_ENT ); - SetActivity ( ACT_WALK ); - } - else if ( RANDOM_LONG(0,149) == 1 ) - { - // if roach doesn't see anything, there's still a chance that it will move. (boredom) - //ALERT ( at_aiconsole, "Bored\n" ); - PickNewDest( ROACH_BORED ); - SetActivity ( ACT_WALK ); - - if ( m_iMode == ROACH_EAT ) - { - // roach will ignore food for 30 to 45 seconds if it got bored while eating. - Eat( 30 + ( RANDOM_LONG(0,14) ) ); - } - } - } - - // don't do this stuff if eating! - if ( m_iMode == ROACH_IDLE ) - { - if ( FShouldEat() ) - { - Listen(); - } - - if ( GETENTITYILLUM( ENT(pev) ) > m_flLastLightLevel ) - { - // someone turned on lights! - //ALERT ( at_console, "Lights!\n" ); - PickNewDest( ROACH_SCARED_BY_LIGHT ); - SetActivity ( ACT_WALK ); - } - else if ( HasConditions(bits_COND_SMELL_FOOD) ) - { - CSound *pSound; - - pSound = CSoundEnt::SoundPointerForIndex( m_iAudibleList ); - - // roach smells food and is just standing around. Go to food unless food isn't on same z-plane. - if ( pSound && abs( pSound->m_vecOrigin.z - pev->origin.z ) <= 3 ) - { - PickNewDest( ROACH_SMELL_FOOD ); - SetActivity ( ACT_WALK ); - } - } - } - - break; - } - case ROACH_SCARED_BY_LIGHT: - { - // if roach was scared by light, then stop if we're over a spot at least as dark as where we started! - if ( GETENTITYILLUM( ENT( pev ) ) <= m_flLastLightLevel ) - { - SetActivity ( ACT_IDLE ); - m_flLastLightLevel = GETENTITYILLUM( ENT ( pev ) );// make this our new light level. - } - break; - } - } - - if ( m_flGroundSpeed != 0 ) - { - Move( flInterval ); - } -} - -//========================================================= -// Picks a new spot for roach to run to.( -//========================================================= -void CRoach :: PickNewDest ( int iCondition ) -{ - Vector vecNewDir; - Vector vecDest; - float flDist; - - m_iMode = iCondition; - - if ( m_iMode == ROACH_SMELL_FOOD ) - { - // find the food and go there. - CSound *pSound; - - pSound = CSoundEnt::SoundPointerForIndex( m_iAudibleList ); - - if ( pSound ) - { - m_Route[ 0 ].vecLocation.x = pSound->m_vecOrigin.x + ( 3 - RANDOM_LONG(0,5) ); - m_Route[ 0 ].vecLocation.y = pSound->m_vecOrigin.y + ( 3 - RANDOM_LONG(0,5) ); - m_Route[ 0 ].vecLocation.z = pSound->m_vecOrigin.z; - m_Route[ 0 ].iType = bits_MF_TO_LOCATION; - m_movementGoal = RouteClassify( m_Route[ 0 ].iType ); - return; - } - } - - do - { - // picks a random spot, requiring that it be at least 128 units away - // else, the roach will pick a spot too close to itself and run in - // circles. this is a hack but buys me time to work on the real monsters. - vecNewDir.x = RANDOM_FLOAT( -1, 1 ); - vecNewDir.y = RANDOM_FLOAT( -1, 1 ); - flDist = 256 + ( RANDOM_LONG(0,255) ); - vecDest = pev->origin + vecNewDir * flDist; - - } while ( ( vecDest - pev->origin ).Length2D() < 128 ); - - m_Route[ 0 ].vecLocation.x = vecDest.x; - m_Route[ 0 ].vecLocation.y = vecDest.y; - m_Route[ 0 ].vecLocation.z = pev->origin.z; - m_Route[ 0 ].iType = bits_MF_TO_LOCATION; - m_movementGoal = RouteClassify( m_Route[ 0 ].iType ); - - if ( RANDOM_LONG(0,9) == 1 ) - { - // every once in a while, a roach will play a skitter sound when they decide to run - EMIT_SOUND_DYN(ENT(pev), CHAN_BODY, "roach/rch_walk.wav", 1, ATTN_NORM, 0, 80 + RANDOM_LONG(0,39) ); - } -} - -//========================================================= -// roach's move function -//========================================================= -void CRoach :: Move ( float flInterval ) -{ - float flWaypointDist; - Vector vecApex; - - // local move to waypoint. - flWaypointDist = ( m_Route[ m_iRouteIndex ].vecLocation - pev->origin ).Length2D(); - MakeIdealYaw ( m_Route[ m_iRouteIndex ].vecLocation ); - - ChangeYaw ( pev->yaw_speed ); - UTIL_MakeVectors( pev->angles ); - - if ( RANDOM_LONG(0,7) == 1 ) - { - // randomly check for blocked path.(more random load balancing) - if ( !WALK_MOVE( ENT(pev), pev->ideal_yaw, 4, WALKMOVE_NORMAL ) ) - { - // stuck, so just pick a new spot to run off to - PickNewDest( m_iMode ); - } - } - - WALK_MOVE( ENT(pev), pev->ideal_yaw, m_flGroundSpeed * flInterval, WALKMOVE_NORMAL ); - - // if the waypoint is closer than step size, then stop after next step (ok for roach to overshoot) - if ( flWaypointDist <= m_flGroundSpeed * flInterval ) - { - // take truncated step and stop - - SetActivity ( ACT_IDLE ); - m_flLastLightLevel = GETENTITYILLUM( ENT ( pev ) );// this is roach's new comfortable light level - - if ( m_iMode == ROACH_SMELL_FOOD ) - { - m_iMode = ROACH_EAT; - } - else - { - m_iMode = ROACH_IDLE; - } - } - - if ( RANDOM_LONG(0,149) == 1 && m_iMode != ROACH_SCARED_BY_LIGHT && m_iMode != ROACH_SMELL_FOOD ) - { - // random skitter while moving as long as not on a b-line to get out of light or going to food - PickNewDest( FALSE ); - } -} - -//========================================================= -// Look - overriden for the roach, which can virtually see -// 360 degrees. -//========================================================= -void CRoach :: Look ( int iDistance ) -{ - CBaseEntity *pSightEnt = NULL;// the current visible entity that we're dealing with - CBaseEntity *pPreviousEnt;// the last entity added to the link list - int iSighted = 0; - - // DON'T let visibility information from last frame sit around! - ClearConditions( bits_COND_SEE_HATE |bits_COND_SEE_DISLIKE | bits_COND_SEE_ENEMY | bits_COND_SEE_FEAR ); - - // don't let monsters outside of the player's PVS act up, or most of the interesting - // things will happen before the player gets there! - if ( FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) ) - { - return; - } - - m_pLink = NULL; - pPreviousEnt = this; - - // Does sphere also limit itself to PVS? - // Examine all entities within a reasonable radius - // !!!PERFORMANCE - let's trivially reject the ent list before radius searching! - while ((pSightEnt = UTIL_FindEntityInSphere( pSightEnt, pev->origin, iDistance )) != NULL) - { - // only consider ents that can be damaged. !!!temporarily only considering other monsters and clients - if ( pSightEnt->IsPlayer() || FBitSet ( pSightEnt->pev->flags, FL_MONSTER ) ) - { - if ( /*FVisible( pSightEnt ) &&*/ !FBitSet( pSightEnt->pev->flags, FL_NOTARGET ) && pSightEnt->pev->health > 0 ) - { - // NULL the Link pointer for each ent added to the link list. If other ents follow, the will overwrite - // this value. If this ent happens to be the last, the list will be properly terminated. - pPreviousEnt->m_pLink = pSightEnt; - pSightEnt->m_pLink = NULL; - pPreviousEnt = pSightEnt; - - // don't add the Enemy's relationship to the conditions. We only want to worry about conditions when - // we see monsters other than the Enemy. - switch ( IRelationship ( pSightEnt ) ) - { - case R_FR: - iSighted |= bits_COND_SEE_FEAR; - break; - case R_NO: - break; - default: - ALERT ( at_console, "%s can't asses %s\n", STRING(pev->classname), STRING(pSightEnt->pev->classname ) ); - break; - } - } - } - } - SetConditions( iSighted ); -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - diff --git a/dlls/Half-life/rpg.cpp b/dlls/Half-life/rpg.cpp deleted file mode 100644 index de5f3905..00000000 --- a/dlls/Half-life/rpg.cpp +++ /dev/null @@ -1,667 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined(OEM_BUILD) - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "gamerules.h" - -enum rpg_e -{ - RPG_IDLE = 0, - RPG_FIDGET, - RPG_RELOAD, // to reload - RPG_FIRE2, // to empty - RPG_HOLSTER1, // loaded - RPG_DRAW1, // loaded - RPG_HOLSTER2, // unloaded - RPG_DRAW_UL, // unloaded - RPG_IDLE_UL, // unloaded idle - RPG_FIDGET_UL, // unloaded fidget -}; - -class CLaserSpot : public CBaseEntity -{ - void Spawn(void); - void Precache(void); - - int ObjectCaps(void) { return FCAP_DONT_SAVE; } - -public: - void Suspend(float flSuspendTime); - void EXPORT Revive(void); - - static CLaserSpot *CreateSpot(void); -}; -LINK_ENTITY_TO_CLASS(laser_spot, CLaserSpot); - -class CRpg : public CBasePlayerWeapon -{ -public: - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void Spawn(void); - void Precache(void); - void Reload(void); - int iItemSlot(void) { return 4; } - int GetItemInfo(ItemInfo *p); - int AddToPlayer(CBasePlayer *pPlayer); - - BOOL Deploy(void); - BOOL CanHolster(void); - void Holster(int skiplocal = 0); - - void PrimaryAttack(void); - void SecondaryAttack(void); - void WeaponIdle(void); - - void UpdateSpot(void); - BOOL ShouldWeaponIdle(void) { return TRUE; }; - - CLaserSpot *m_pSpot; - int m_fSpotActive; - int m_cActiveRockets; // how many missiles in flight from this launcher right now? -}; -LINK_ENTITY_TO_CLASS(weapon_rpg, CRpg); - -TYPEDESCRIPTION CRpg::m_SaveData[] = - { - DEFINE_FIELD(CRpg, m_fSpotActive, FIELD_INTEGER), - DEFINE_FIELD(CRpg, m_cActiveRockets, FIELD_INTEGER), -}; -IMPLEMENT_SAVERESTORE(CRpg, CBasePlayerWeapon); - -//========================================================= -//========================================================= -CLaserSpot *CLaserSpot::CreateSpot(void) -{ - CLaserSpot *pSpot = GetClassPtr((CLaserSpot *)NULL); - pSpot->Spawn(); - - pSpot->pev->classname = MAKE_STRING("laser_spot"); - - return pSpot; -} - -//========================================================= -//========================================================= -void CLaserSpot::Spawn(void) -{ - Precache(); - pev->movetype = MOVETYPE_NONE; - pev->solid = SOLID_NOT; - - pev->rendermode = kRenderGlow; - pev->renderfx = kRenderFxNoDissipation; - pev->renderamt = 255; - - SET_MODEL(ENT(pev), "sprites/laserdot.spr"); - UTIL_SetOrigin(pev, pev->origin); -}; - -//========================================================= -// Suspend- make the laser sight invisible. -//========================================================= -void CLaserSpot::Suspend(float flSuspendTime) -{ - pev->effects |= EF_NODRAW; - - SetThink(Revive); - pev->nextthink = gpGlobals->time + flSuspendTime; -} - -//========================================================= -// Revive - bring a suspended laser sight back. -//========================================================= -void CLaserSpot::Revive(void) -{ - pev->effects &= ~EF_NODRAW; - - SetThink(NULL); -} - -void CLaserSpot::Precache(void) -{ - PRECACHE_MODEL("sprites/laserdot.spr"); -}; - -class CRpgRocket : public CGrenade -{ -public: - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - void Spawn(void); - void Precache(void); - void EXPORT FollowThink(void); - void EXPORT IgniteThink(void); - void EXPORT RocketTouch(CBaseEntity *pOther); - static CRpgRocket *CreateRpgRocket(Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CRpg *pLauncher); - - int m_iTrail; - float m_flIgniteTime; - CRpg *m_pLauncher; // pointer back to the launcher that fired me. -}; -LINK_ENTITY_TO_CLASS(rpg_rocket, CRpgRocket); - -TYPEDESCRIPTION CRpgRocket::m_SaveData[] = - { - DEFINE_FIELD(CRpgRocket, m_flIgniteTime, FIELD_TIME), - DEFINE_FIELD(CRpgRocket, m_pLauncher, FIELD_CLASSPTR), -}; -IMPLEMENT_SAVERESTORE(CRpgRocket, CGrenade); - -//========================================================= -//========================================================= -CRpgRocket *CRpgRocket::CreateRpgRocket(Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CRpg *pLauncher) -{ - CRpgRocket *pRocket = GetClassPtr((CRpgRocket *)NULL); - - UTIL_SetOrigin(pRocket->pev, vecOrigin); - pRocket->pev->angles = vecAngles; - pRocket->Spawn(); - pRocket->SetTouch(CRpgRocket::RocketTouch); - pRocket->m_pLauncher = pLauncher; // remember what RPG fired me. - pRocket->m_pLauncher->m_cActiveRockets++; // register this missile as active for the launcher - pRocket->pev->owner = pOwner->edict(); - - return pRocket; -} - -//========================================================= -//========================================================= -void CRpgRocket ::Spawn(void) -{ - Precache(); - // motor - pev->movetype = MOVETYPE_BOUNCE; - pev->solid = SOLID_BBOX; - - SET_MODEL(ENT(pev), "models/rpgrocket.mdl"); - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); - UTIL_SetOrigin(pev, pev->origin); - - pev->classname = MAKE_STRING("rpg_rocket"); - - SetThink(IgniteThink); - SetTouch(ExplodeTouch); - - pev->angles.x -= 30; - UTIL_MakeVectors(pev->angles); - pev->angles.x = -(pev->angles.x + 30); - - pev->velocity = gpGlobals->v_forward * 250; - pev->gravity = 0.5; - - pev->nextthink = gpGlobals->time + 0.4; - - pev->dmg = gSkillData.plrDmgRPG; -} - -//========================================================= -//========================================================= -void CRpgRocket ::RocketTouch(CBaseEntity *pOther) -{ - if (m_pLauncher) - { - // my launcher is still around, tell it I'm dead. - m_pLauncher->m_cActiveRockets--; - } - - STOP_SOUND(edict(), CHAN_VOICE, "weapons/rocket1.wav"); - ExplodeTouch(pOther); -} - -//========================================================= -//========================================================= -void CRpgRocket ::Precache(void) -{ - PRECACHE_MODEL("models/rpgrocket.mdl"); - m_iTrail = PRECACHE_MODEL("sprites/smoke.spr"); - PRECACHE_SOUND("weapons/rocket1.wav"); -} - -void CRpgRocket ::IgniteThink(void) -{ - // pev->movetype = MOVETYPE_TOSS; - - pev->movetype = MOVETYPE_FLY; - pev->effects |= EF_LIGHT; - - // make rocket sound - EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/rocket1.wav", 1, 0.5); - - // rocket trail - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - - WRITE_BYTE(TE_BEAMFOLLOW); - WRITE_SHORT(entindex()); // entity - WRITE_SHORT(m_iTrail); // model - WRITE_BYTE(40); // life - WRITE_BYTE(5); // width - WRITE_BYTE(224); // r, g, b - WRITE_BYTE(224); // r, g, b - WRITE_BYTE(255); // r, g, b - WRITE_BYTE(255); // brightness - - MESSAGE_END(); // move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS) - - /* - WRITE_BYTE( MSG_BROADCAST, SVC_TEMPENTITY ); - WRITE_BYTE( MSG_BROADCAST, TE_BEAMFOLLOW); - WRITE_SHORT(entindex()); // entity - WRITE_SHORT(MSG_BROADCAST, m_iTrail ); // model - WRITE_BYTE( MSG_BROADCAST, 40 ); // life - WRITE_BYTE( MSG_BROADCAST, 5 ); // width - WRITE_BYTE( MSG_BROADCAST, 224 ); // r, g, b - WRITE_BYTE( MSG_BROADCAST, 224 ); // r, g, b - WRITE_BYTE( MSG_BROADCAST, 255 ); // r, g, b - WRITE_BYTE( MSG_BROADCAST, 255 ); // brightness -*/ - m_flIgniteTime = gpGlobals->time; - - // set to follow laser spot - SetThink(FollowThink); - pev->nextthink = gpGlobals->time + 0.1; -} - -void CRpgRocket ::FollowThink(void) -{ - CBaseEntity *pOther = NULL; - Vector vecTarget; - Vector vecDir; - float flDist, flMax, flDot; - TraceResult tr; - - UTIL_MakeAimVectors(pev->angles); - - vecTarget = gpGlobals->v_forward; - flMax = 4096; - - // Examine all entities within a reasonable radius - while ((pOther = UTIL_FindEntityByClassname(pOther, "laser_spot")) != NULL) - { - UTIL_TraceLine(pev->origin, pOther->pev->origin, dont_ignore_monsters, ENT(pev), &tr); - // ALERT( at_console, "%f\n", tr.flFraction ); - if (tr.flFraction >= 0.90) - { - vecDir = pOther->pev->origin - pev->origin; - flDist = vecDir.Length(); - vecDir = vecDir.Normalize(); - flDot = DotProduct(gpGlobals->v_forward, vecDir); - if ((flDot > 0) && (flDist * (1 - flDot) < flMax)) - { - flMax = flDist * (1 - flDot); - vecTarget = vecDir; - } - } - } - - pev->angles = UTIL_VecToAngles(vecTarget); - - // this acceleration and turning math is totally wrong, but it seems to respond well so don't change it. - float flSpeed = pev->velocity.Length(); - if (gpGlobals->time - m_flIgniteTime < 1.0) - { - pev->velocity = pev->velocity * 0.2 + vecTarget * (flSpeed * 0.8 + 400); - if (pev->waterlevel == 3) - { - // go slow underwater - if (pev->velocity.Length() > 300) - { - pev->velocity = pev->velocity.Normalize() * 300; - } - UTIL_BubbleTrail(pev->origin - pev->velocity * 0.1, pev->origin, 4); - } - else - { - if (pev->velocity.Length() > 2000) - { - pev->velocity = pev->velocity.Normalize() * 2000; - } - } - } - else - { - if (pev->effects & EF_LIGHT) - { - pev->effects = 0; - STOP_SOUND(ENT(pev), CHAN_VOICE, "weapons/rocket1.wav"); - } - pev->velocity = pev->velocity * 0.2 + vecTarget * flSpeed * 0.798; - if (pev->waterlevel == 0 && pev->velocity.Length() < 1500) - { - Detonate(); - } - } - // ALERT( at_console, "%.0f\n", flSpeed ); - - pev->nextthink = gpGlobals->time + 0.1; -} - -void CRpg::Reload(void) -{ - int iResult; - - if (m_iClip == 1) - { - // don't bother with any of this if don't need to reload. - return; - } - - // because the RPG waits to autoreload when no missiles are active while the LTD is on, the - // weapons code is constantly calling into this function, but is often denied because - // a) missiles are in flight, but the LTD is on - // or - // b) player is totally out of ammo and has nothing to switch to, and should be allowed to - // shine the designator around - // - // Set the next attack time into the future so that WeaponIdle will get called more often - // than reload, allowing the RPG LTD to be updated - - m_flNextPrimaryAttack = gpGlobals->time + 0.5; - - if (m_cActiveRockets && m_fSpotActive) - { - // no reloading when there are active missiles tracking the designator. - // ward off future autoreload attempts by setting next attack time into the future for a bit. - return; - } - - if (m_pSpot && m_fSpotActive) - { - m_pSpot->Suspend(2.1); - m_flNextSecondaryAttack = gpGlobals->time + 2.1; - } - - if (m_iClip == 0) - { - iResult = DefaultReload(RPG_MAX_CLIP, RPG_RELOAD, 2); - } - - if (iResult) - { - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); - } -} - -void CRpg::Spawn() -{ - Precache(); - m_iId = WEAPON_RPG; - - SET_MODEL(ENT(pev), "models/w_rpg.mdl"); - m_fSpotActive = 1; - - if (g_pGameRules->IsMultiplayer()) - { - // more default ammo in multiplay. - m_iDefaultAmmo = RPG_DEFAULT_GIVE * 2; - } - else - { - m_iDefaultAmmo = RPG_DEFAULT_GIVE; - } - - FallInit(); // get ready to fall down. -} - -void CRpg::Precache(void) -{ - PRECACHE_MODEL("models/w_rpg.mdl"); - PRECACHE_MODEL("models/v_rpg.mdl"); - PRECACHE_MODEL("models/p_rpg.mdl"); - - PRECACHE_SOUND("items/9mmclip1.wav"); - - UTIL_PrecacheOther("laser_spot"); - UTIL_PrecacheOther("rpg_rocket"); - - PRECACHE_SOUND("weapons/rocketfire1.wav"); - PRECACHE_SOUND("weapons/glauncher.wav"); // alternative fire sound -} - -int CRpg::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "rockets"; - p->iMaxAmmo1 = ROCKET_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = RPG_MAX_CLIP; - p->iSlot = 3; - p->iPosition = 0; - p->iId = m_iId = WEAPON_RPG; - p->iFlags = 0; - p->iWeight = RPG_WEIGHT; - - return 1; -} - -int CRpg::AddToPlayer(CBasePlayer *pPlayer) -{ - if (CBasePlayerWeapon::AddToPlayer(pPlayer)) - { - MESSAGE_BEGIN(MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev); - WRITE_BYTE(m_iId); - MESSAGE_END(); - return TRUE; - } - return FALSE; -} - -BOOL CRpg::Deploy() -{ - if (m_iClip == 0) - { - return DefaultDeploy("models/v_rpg.mdl", "models/p_rpg.mdl", RPG_DRAW_UL, "rpg"); - } - - return DefaultDeploy("models/v_rpg.mdl", "models/p_rpg.mdl", RPG_DRAW1, "rpg"); -} - -BOOL CRpg::CanHolster(void) -{ - if (m_fSpotActive && m_cActiveRockets) - { - // can't put away while guiding a missile. - return FALSE; - } - - return TRUE; -} - -void CRpg::Holster(int skiplocal /* = 0 */) -{ - m_fInReload = FALSE; // cancel any reload in progress. - - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - // m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 ); - SendWeaponAnim(RPG_HOLSTER1); - if (m_pSpot) - { - m_pSpot->Killed(NULL, GIB_NEVER); - m_pSpot = NULL; - } -} - -void CRpg::PrimaryAttack() -{ - if (m_iClip) - { - m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; - m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH; - - SendWeaponAnim(RPG_FIRE2); - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - UTIL_MakeVectors(m_pPlayer->pev->v_angle); - Vector vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -8; - - CRpgRocket *pRocket = CRpgRocket::CreateRpgRocket(vecSrc, m_pPlayer->pev->v_angle, m_pPlayer, this); - - UTIL_MakeVectors(m_pPlayer->pev->v_angle); // RpgRocket::Create stomps on globals, so remake. - pRocket->pev->velocity = pRocket->pev->velocity + gpGlobals->v_forward * DotProduct(m_pPlayer->pev->velocity, gpGlobals->v_forward); - - // firing RPG no longer turns on the designator. ALT fire is a toggle switch for the LTD. - // Ken signed up for this as a global change (sjb) - - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, ATTN_NORM); - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/glauncher.wav", 0.7, ATTN_NORM); - - m_iClip--; - //m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; - - m_flNextPrimaryAttack = gpGlobals->time + 1.5; - m_flTimeWeaponIdle = gpGlobals->time + 1.5; - m_pPlayer->pev->punchangle.x -= 5; - } - else - { - PlayEmptySound(); - } - UpdateSpot(); -} - -void CRpg::SecondaryAttack() -{ - m_fSpotActive = !m_fSpotActive; - - if (!m_fSpotActive && m_pSpot) - { - m_pSpot->Killed(NULL, GIB_NORMAL); - m_pSpot = NULL; - } - - m_flNextSecondaryAttack = gpGlobals->time + 0.2; -} - -void CRpg::WeaponIdle(void) -{ - UpdateSpot(); - - ResetEmptySound(); - - if (m_flTimeWeaponIdle > gpGlobals->time) - return; - - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - int iAnim; - float flRand = RANDOM_FLOAT(0, 1); - if (flRand <= 0.75 || m_fSpotActive) - { - if (m_iClip == 0) - iAnim = RPG_IDLE_UL; - else - iAnim = RPG_IDLE; - - m_flTimeWeaponIdle = gpGlobals->time + 90.0 / 15.0; - } - else - { - if (m_iClip == 0) - iAnim = RPG_FIDGET_UL; - else - iAnim = RPG_FIDGET; - - m_flTimeWeaponIdle = gpGlobals->time + 3.0; - } - - SendWeaponAnim(iAnim); - } - else - { - m_flTimeWeaponIdle = gpGlobals->time + 1; - } -} - -void CRpg::UpdateSpot(void) -{ - if (m_fSpotActive) - { - if (!m_pSpot) - { - m_pSpot = CLaserSpot::CreateSpot(); - } - - UTIL_MakeVectors(m_pPlayer->pev->v_angle); - Vector vecSrc = m_pPlayer->GetGunPosition(); - ; - Vector vecAiming = gpGlobals->v_forward; - - TraceResult tr; - UTIL_TraceLine(vecSrc, vecSrc + vecAiming * 8192, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr); - - // ALERT( "%f %f\n", gpGlobals->v_forward.y, vecAiming.y ); - - /* - float a = gpGlobals->v_forward.y * vecAiming.y + gpGlobals->v_forward.x * vecAiming.x; - m_pPlayer->pev->punchangle.y = acos( a ) * (180 / M_PI); - - ALERT( at_console, "%f\n", a ); - */ - - UTIL_SetOrigin(m_pSpot->pev, tr.vecEndPos); - } -} - -class CRpgAmmo : public CBasePlayerAmmo -{ - void Spawn(void) - { - Precache(); - SET_MODEL(ENT(pev), "models/w_rpgammo.mdl"); - CBasePlayerAmmo::Spawn(); - } - void Precache(void) - { - PRECACHE_MODEL("models/w_rpgammo.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - } - BOOL AddAmmo(CBaseEntity *pOther) - { - int iGive; - - if (g_pGameRules->IsMultiplayer()) - { - // hand out more ammo per rocket in multiplayer. - iGive = AMMO_RPGCLIP_GIVE * 2; - } - else - { - iGive = AMMO_RPGCLIP_GIVE; - } - - if (pOther->GiveAmmo(iGive, "rockets", ROCKET_MAX_CARRY) != -1) - { - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); - return TRUE; - } - return FALSE; - } -}; -LINK_ENTITY_TO_CLASS(ammo_rpgclip, CRpgAmmo); - -#endif \ No newline at end of file diff --git a/dlls/Half-life/satchel.cpp b/dlls/Half-life/satchel.cpp deleted file mode 100644 index 7e680155..00000000 --- a/dlls/Half-life/satchel.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "gamerules.h" - -enum satchel_e -{ - SATCHEL_IDLE1 = 0, - SATCHEL_FIDGET1, - SATCHEL_DRAW, - SATCHEL_DROP -}; - -enum satchel_radio_e -{ - SATCHEL_RADIO_IDLE1 = 0, - SATCHEL_RADIO_FIDGET1, - SATCHEL_RADIO_DRAW, - SATCHEL_RADIO_FIRE, - SATCHEL_RADIO_HOLSTER -}; - -class CSatchelCharge : public CGrenade -{ - void Spawn(void); - void Precache(void); - void BounceSound(void); - - void EXPORT SatchelSlide(CBaseEntity *pOther); - void EXPORT SatchelThink(void); - -public: - void Deactivate(void); -}; -LINK_ENTITY_TO_CLASS(monster_satchel, CSatchelCharge); - -//========================================================= -// Deactivate - do whatever it is we do to an orphaned -// satchel when we don't want it in the world anymore. -//========================================================= -void CSatchelCharge::Deactivate(void) -{ - pev->solid = SOLID_NOT; - UTIL_Remove(this); -} - -void CSatchelCharge ::Spawn(void) -{ - Precache(); - // motor - pev->movetype = MOVETYPE_BOUNCE; - pev->solid = SOLID_BBOX; - - SET_MODEL(ENT(pev), "models/w_satchel.mdl"); - //UTIL_SetSize(pev, Vector( -16, -16, -4), Vector(16, 16, 32)); // Old box -- size of headcrab monsters/players get blocked by this - UTIL_SetSize(pev, Vector(-4, -4, -4), Vector(4, 4, 4)); // Uses point-sized, and can be stepped over - UTIL_SetOrigin(pev, pev->origin); - - SetTouch(SatchelSlide); - SetUse(DetonateUse); - SetThink(SatchelThink); - pev->nextthink = gpGlobals->time + 0.1; - - pev->gravity = 0.5; - pev->friction = 0.8; - - pev->dmg = gSkillData.plrDmgSatchel; - // ResetSequenceInfo( ); - pev->sequence = 1; -} - -void CSatchelCharge::SatchelSlide(CBaseEntity *pOther) -{ - entvars_t *pevOther = pOther->pev; - - // don't hit the guy that launched this grenade - if (pOther->edict() == pev->owner) - return; - - // pev->avelocity = Vector (300, 300, 300); - pev->gravity = 1; // normal gravity now - - // HACKHACK - On ground isn't always set, so look for ground underneath - TraceResult tr; - UTIL_TraceLine(pev->origin, pev->origin - Vector(0, 0, 10), ignore_monsters, edict(), &tr); - - if (tr.flFraction < 1.0) - { - // add a bit of static friction - pev->velocity = pev->velocity * 0.95; - pev->avelocity = pev->avelocity * 0.9; - // play sliding sound, volume based on velocity - } - if (!(pev->flags & FL_ONGROUND) && pev->velocity.Length2D() > 10) - { - BounceSound(); - } - StudioFrameAdvance(); -} - -void CSatchelCharge ::SatchelThink(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - if (!IsInWorld()) - { - UTIL_Remove(this); - return; - } - - if (pev->waterlevel == 3) - { - pev->movetype = MOVETYPE_FLY; - pev->velocity = pev->velocity * 0.8; - pev->avelocity = pev->avelocity * 0.9; - pev->velocity.z += 8; - } - else if (pev->waterlevel == 0) - { - pev->movetype = MOVETYPE_BOUNCE; - } - else - { - pev->velocity.z -= 8; - } -} - -void CSatchelCharge ::Precache(void) -{ - PRECACHE_MODEL("models/grenade.mdl"); - PRECACHE_SOUND("weapons/g_bounce1.wav"); - PRECACHE_SOUND("weapons/g_bounce2.wav"); - PRECACHE_SOUND("weapons/g_bounce3.wav"); -} - -void CSatchelCharge ::BounceSound(void) -{ - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/g_bounce1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/g_bounce2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/g_bounce3.wav", 1, ATTN_NORM); - break; - } -} - -class CSatchel : public CBasePlayerWeapon -{ -public: - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - void Spawn(void); - void Precache(void); - int iItemSlot(void) { return 5; } - int GetItemInfo(ItemInfo *p); - int AddToPlayer(CBasePlayer *pPlayer); - void PrimaryAttack(void); - void SecondaryAttack(void); - int AddDuplicate(CBasePlayerItem *pOriginal); - BOOL CanDeploy(void); - BOOL Deploy(void); - BOOL IsUseable(void); - - void Holster(int skiplocal = 0); - void WeaponIdle(void); - void Throw(void); - int m_chargeReady; -}; -LINK_ENTITY_TO_CLASS(weapon_satchel, CSatchel); - -TYPEDESCRIPTION CSatchel::m_SaveData[] = - { - DEFINE_FIELD(CSatchel, m_chargeReady, FIELD_INTEGER), -}; -IMPLEMENT_SAVERESTORE(CSatchel, CBasePlayerWeapon); - -//========================================================= -// CALLED THROUGH the newly-touched weapon's instance. The existing player weapon is pOriginal -//========================================================= -int CSatchel::AddDuplicate(CBasePlayerItem *pOriginal) -{ - CSatchel *pSatchel; - - if (g_pGameRules->IsMultiplayer()) - { - pSatchel = (CSatchel *)pOriginal; - - if (pSatchel->m_chargeReady != 0) - { - // player has some satchels deployed. Refuse to add more. - return FALSE; - } - } - - return CBasePlayerWeapon::AddDuplicate(pOriginal); -} - -//========================================================= -//========================================================= -int CSatchel::AddToPlayer(CBasePlayer *pPlayer) -{ - int bResult = CBasePlayerItem::AddToPlayer(pPlayer); - - pPlayer->pev->weapons |= (1 << m_iId); - m_chargeReady = 0; // this satchel charge weapon now forgets that any satchels are deployed by it. - - if (bResult) - { - return AddWeapon(); - } - return FALSE; -} - -void CSatchel::Spawn() -{ - Precache(); - m_iId = WEAPON_SATCHEL; - SET_MODEL(ENT(pev), "models/w_satchel.mdl"); - - m_iDefaultAmmo = SATCHEL_DEFAULT_GIVE; - - FallInit(); // get ready to fall down. -} - -void CSatchel::Precache(void) -{ - PRECACHE_MODEL("models/v_satchel.mdl"); - PRECACHE_MODEL("models/v_satchel_radio.mdl"); - PRECACHE_MODEL("models/w_satchel.mdl"); - PRECACHE_MODEL("models/p_satchel.mdl"); - PRECACHE_MODEL("models/p_satchel_radio.mdl"); - - UTIL_PrecacheOther("monster_satchel"); -} - -int CSatchel::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "Satchel Charge"; - p->iMaxAmmo1 = SATCHEL_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = WEAPON_NOCLIP; - p->iSlot = 4; - p->iPosition = 1; - p->iFlags = ITEM_FLAG_SELECTONEMPTY | ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE; - p->iId = m_iId = WEAPON_SATCHEL; - p->iWeight = SATCHEL_WEIGHT; - - return 1; -} - -//========================================================= -//========================================================= -BOOL CSatchel::IsUseable(void) -{ - if (m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] > 0) - { - // player is carrying some satchels - return TRUE; - } - - if (m_chargeReady != 0) - { - // player isn't carrying any satchels, but has some out - return TRUE; - } - - return FALSE; -} - -BOOL CSatchel::CanDeploy(void) -{ - if (m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] > 0) - { - // player is carrying some satchels - return TRUE; - } - - if (m_chargeReady != 0) - { - // player isn't carrying any satchels, but has some out - return TRUE; - } - - return FALSE; -} - -BOOL CSatchel::Deploy() -{ - if (m_chargeReady) - { - m_pPlayer->pev->viewmodel = MAKE_STRING("models/v_satchel_radio.mdl"); - m_pPlayer->pev->weaponmodel = MAKE_STRING("models/p_satchel_radio.mdl"); - SendWeaponAnim(SATCHEL_RADIO_DRAW); - // use hivehand animations - strncpy(m_pPlayer->m_szAnimExtention, "hive", sizeof(m_pPlayer->m_szAnimExtention) ); - } - else - { - m_pPlayer->pev->viewmodel = MAKE_STRING("models/v_satchel.mdl"); - m_pPlayer->pev->weaponmodel = MAKE_STRING("models/p_satchel.mdl"); - SendWeaponAnim(SATCHEL_DRAW); - // use tripmine animations - strncpy(m_pPlayer->m_szAnimExtention, "trip", sizeof(m_pPlayer->m_szAnimExtention) ); - } - - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0; - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); - return TRUE; -} - -void CSatchel::Holster(int skiplocal /* = 0 */) -{ - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - - if (m_chargeReady) - { - SendWeaponAnim(SATCHEL_RADIO_HOLSTER); - } - else - { - SendWeaponAnim(SATCHEL_DROP); - } - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM); - - if (!m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] && !m_chargeReady) - { - m_pPlayer->pev->weapons &= ~(1 << WEAPON_SATCHEL); - SetThink(DestroyItem); - pev->nextthink = gpGlobals->time + 0.1; - } -} - -void CSatchel::PrimaryAttack() -{ - switch (m_chargeReady) - { - case 0: - { - Throw(); - } - break; - case 1: - { - SendWeaponAnim(SATCHEL_RADIO_FIRE); - - edict_t *pPlayer = m_pPlayer->edict(); - - CBaseEntity *pSatchel = NULL; - - while ((pSatchel = UTIL_FindEntityInSphere(pSatchel, m_pPlayer->pev->origin, 4096)) != NULL) - { - if (FClassnameIs(pSatchel->pev, "monster_satchel")) - { - if (pSatchel->pev->owner == pPlayer) - { - pSatchel->Use(m_pPlayer, m_pPlayer, USE_ON, 0); - m_chargeReady = 2; - } - } - } - - if (m_chargeReady == 1) - { - // play buzzer sound - } - else - { - // play click sound - } - - m_chargeReady = 2; - m_flNextPrimaryAttack = gpGlobals->time + 0.5; - m_flNextSecondaryAttack = gpGlobals->time + 0.5; - m_flTimeWeaponIdle = gpGlobals->time + 0.5; - break; - } - - case 2: - // we're reloading, don't allow fire - { - } - break; - } -} - -void CSatchel::SecondaryAttack(void) -{ - if (m_chargeReady != 2) - { - Throw(); - } -} - -void CSatchel::Throw(void) -{ - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - Vector vecSrc = m_pPlayer->pev->origin; - - Vector vecThrow = gpGlobals->v_forward * 274 + m_pPlayer->pev->velocity; - - CBaseEntity *pSatchel = Create("monster_satchel", vecSrc, Vector(0, 0, 0), m_pPlayer->edict()); - pSatchel->pev->velocity = vecThrow; - pSatchel->pev->avelocity.y = 400; - - m_pPlayer->pev->viewmodel = MAKE_STRING("models/v_satchel_radio.mdl"); - m_pPlayer->pev->weaponmodel = MAKE_STRING("models/p_satchel_radio.mdl"); - SendWeaponAnim(SATCHEL_RADIO_DRAW); - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - m_chargeReady = 1; - - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; - - m_flNextPrimaryAttack = gpGlobals->time + 1.0; - m_flNextSecondaryAttack = gpGlobals->time + 0.5; - } -} - -void CSatchel::WeaponIdle(void) -{ - if (m_flTimeWeaponIdle > gpGlobals->time) - return; - - switch (m_chargeReady) - { - case 0: - SendWeaponAnim(SATCHEL_FIDGET1); - // use tripmine animations - strncpy(m_pPlayer->m_szAnimExtention, "trip", sizeof(m_pPlayer->m_szAnimExtention) ); - break; - case 1: - SendWeaponAnim(SATCHEL_RADIO_FIDGET1); - // use hivehand animations - strncpy(m_pPlayer->m_szAnimExtention, "hive", sizeof(m_pPlayer->m_szAnimExtention) ); - break; - case 2: - if (!m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - m_chargeReady = 0; - RetireWeapon(); - return; - } - - m_pPlayer->pev->viewmodel = MAKE_STRING("models/v_satchel.mdl"); - m_pPlayer->pev->weaponmodel = MAKE_STRING("models/p_satchel.mdl"); - SendWeaponAnim(SATCHEL_DRAW); - - // use tripmine animations - strncpy(m_pPlayer->m_szAnimExtention, "trip", sizeof(m_pPlayer->m_szAnimExtention) ); - - m_flNextPrimaryAttack = gpGlobals->time + 0.5; - m_flNextSecondaryAttack = gpGlobals->time + 0.5; - m_chargeReady = 0; - break; - } - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); // how long till we do this again. -} - -//========================================================= -// DeactivateSatchels - removes all satchels owned by -// the provided player. Should only be used upon death. -// -// Made this global on purpose. -//========================================================= -void DeactivateSatchels(CBasePlayer *pOwner) -{ - edict_t *pFind; - - pFind = FIND_ENTITY_BY_CLASSNAME(NULL, "monster_satchel"); - - while (!FNullEnt(pFind)) - { - CBaseEntity *pEnt = CBaseEntity::Instance(pFind); - CSatchelCharge *pSatchel = (CSatchelCharge *)pEnt; - - if (pSatchel) - { - if (pSatchel->pev->owner == pOwner->edict()) - { - pSatchel->Deactivate(); - } - } - - pFind = FIND_ENTITY_BY_CLASSNAME(pFind, "monster_satchel"); - } -} - -#endif \ No newline at end of file diff --git a/dlls/Half-life/scientist.cpp b/dlls/Half-life/scientist.cpp deleted file mode 100644 index 417444a0..00000000 --- a/dlls/Half-life/scientist.cpp +++ /dev/null @@ -1,1401 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// human scientist (passive lab worker) -//========================================================= - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "talkmonster.h" -#include "schedule.h" -#include "defaultai.h" -#include "scripted.h" -#include "animation.h" -#include "soundent.h" - -#define NUM_SCIENTIST_HEADS 4 // four heads available for scientist model -enum -{ - HEAD_GLASSES = 0, - HEAD_EINSTEIN = 1, - HEAD_LUTHER = 2, - HEAD_SLICK = 3 -}; - -enum -{ - SCHED_HIDE = LAST_TALKMONSTER_SCHEDULE + 1, - SCHED_FEAR, - SCHED_PANIC, - SCHED_STARTLE, - SCHED_TARGET_CHASE_SCARED, - SCHED_TARGET_FACE_SCARED, -}; - -enum -{ - TASK_SAY_HEAL = LAST_TALKMONSTER_TASK + 1, - TASK_HEAL, - TASK_SAY_FEAR, - TASK_RUN_PATH_SCARED, - TASK_SCREAM, - TASK_RANDOM_SCREAM, - TASK_MOVE_TO_TARGET_RANGE_SCARED, -}; - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define SCIENTIST_AE_HEAL (1) -#define SCIENTIST_AE_NEEDLEON (2) -#define SCIENTIST_AE_NEEDLEOFF (3) - -//======================================================= -// Scientist -//======================================================= - -class CScientist : public CTalkMonster -{ -public: - void Spawn(void); - void Precache(void); - - void SetYawSpeed(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - void RunTask(Task_t *pTask); - void StartTask(Task_t *pTask); - int ObjectCaps(void) { return CTalkMonster ::ObjectCaps() | FCAP_IMPULSE_USE; } - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - virtual int FriendNumber(int arrayNumber); - void SetActivity(Activity newActivity); - Activity GetStoppedActivity(void); - int ISoundMask(void); - void DeclineFollowing(void); - - float CoverRadius(void) { return 1200; } // Need more room for cover because scientists want to get far away! - BOOL DisregardEnemy(CBaseEntity *pEnemy) { return !pEnemy->IsAlive() || (gpGlobals->time - m_fearTime) > 15; } - - BOOL CanHeal(void); - void Heal(void); - void Scream(void); - - // Override these to set behavior - Schedule_t *GetScheduleOfType(int Type); - Schedule_t *GetSchedule(void); - MONSTERSTATE GetIdealState(void); - - void DeathSound(void); - void PainSound(void); - - void TalkInit(void); - - void Killed(entvars_t *pevAttacker, int iGib); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - CUSTOM_SCHEDULES; - -private: - float m_painTime; - float m_healTime; - float m_fearTime; -}; - -LINK_ENTITY_TO_CLASS(monster_scientist, CScientist); - -TYPEDESCRIPTION CScientist::m_SaveData[] = - { - DEFINE_FIELD(CScientist, m_painTime, FIELD_TIME), - DEFINE_FIELD(CScientist, m_healTime, FIELD_TIME), - DEFINE_FIELD(CScientist, m_fearTime, FIELD_TIME), -}; - -IMPLEMENT_SAVERESTORE(CScientist, CTalkMonster); - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= -Task_t tlFollow[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_CANT_FOLLOW}, // If you fail, bail out of follow - {TASK_MOVE_TO_TARGET_RANGE, (float)128}, // Move within 128 of target ent (client) - // { TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE }, -}; - -Schedule_t slFollow[] = - { - {tlFollow, - ARRAYSIZE(tlFollow), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND, - bits_SOUND_COMBAT | - bits_SOUND_DANGER, - "Follow"}, -}; - -Task_t tlFollowScared[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_TARGET_CHASE}, // If you fail, follow normally - {TASK_MOVE_TO_TARGET_RANGE_SCARED, (float)128}, // Move within 128 of target ent (client) - // { TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE_SCARED }, -}; - -Schedule_t slFollowScared[] = - { - {tlFollowScared, - ARRAYSIZE(tlFollowScared), - bits_COND_NEW_ENEMY | - bits_COND_HEAR_SOUND | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - bits_SOUND_DANGER, - "FollowScared"}, -}; - -Task_t tlFaceTargetScared[] = - { - {TASK_FACE_TARGET, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_CROUCHIDLE}, - {TASK_SET_SCHEDULE, (float)SCHED_TARGET_CHASE_SCARED}, -}; - -Schedule_t slFaceTargetScared[] = - { - {tlFaceTargetScared, - ARRAYSIZE(tlFaceTargetScared), - bits_COND_HEAR_SOUND | - bits_COND_NEW_ENEMY, - bits_SOUND_DANGER, - "FaceTargetScared"}, -}; - -Task_t tlStopFollowing[] = - { - {TASK_CANT_FOLLOW, (float)0}, -}; - -Schedule_t slStopFollowing[] = - { - {tlStopFollowing, - ARRAYSIZE(tlStopFollowing), - 0, - 0, - "StopFollowing"}, -}; - -Task_t tlHeal[] = - { - {TASK_MOVE_TO_TARGET_RANGE, (float)50}, // Move within 60 of target ent (client) - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_TARGET_CHASE}, // If you fail, catch up with that guy! (change this to put syringe away and then chase) - {TASK_FACE_IDEAL, (float)0}, - {TASK_SAY_HEAL, (float)0}, - {TASK_PLAY_SEQUENCE_FACE_TARGET, (float)ACT_ARM}, // Whip out the needle - {TASK_HEAL, (float)0}, // Put it in the player - {TASK_PLAY_SEQUENCE_FACE_TARGET, (float)ACT_DISARM}, // Put away the needle -}; - -Schedule_t slHeal[] = - { - {tlHeal, - ARRAYSIZE(tlHeal), - 0, // Don't interrupt or he'll end up running around with a needle all the time - 0, - "Heal"}, -}; - -Task_t tlFaceTarget[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_TARGET, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_SET_SCHEDULE, (float)SCHED_TARGET_CHASE}, -}; - -Schedule_t slFaceTarget[] = - { - {tlFaceTarget, - ARRAYSIZE(tlFaceTarget), - bits_COND_CLIENT_PUSH | - bits_COND_NEW_ENEMY | - bits_COND_HEAR_SOUND, - bits_SOUND_COMBAT | - bits_SOUND_DANGER, - "FaceTarget"}, -}; - -Task_t tlSciPanic[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_SCREAM, (float)0}, - {TASK_PLAY_SEQUENCE_FACE_ENEMY, (float)ACT_EXCITED}, // This is really fear-stricken excitement - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, -}; - -Schedule_t slSciPanic[] = - { - {tlSciPanic, - ARRAYSIZE(tlSciPanic), - 0, - 0, - "SciPanic"}, -}; - -Task_t tlIdleSciStand[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_WAIT, (float)2}, // repick IDLESTAND every two seconds. - {TASK_TLK_HEADRESET, (float)0}, // reset head position -}; - -Schedule_t slIdleSciStand[] = - { - {tlIdleSciStand, - ARRAYSIZE(tlIdleSciStand), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND | - bits_COND_SMELL | - bits_COND_CLIENT_PUSH | - bits_COND_PROVOKED, - - bits_SOUND_COMBAT | // sound flags - //bits_SOUND_PLAYER | - //bits_SOUND_WORLD | - bits_SOUND_DANGER | - bits_SOUND_MEAT | // scents - bits_SOUND_CARCASS | - bits_SOUND_GARBAGE, - "IdleSciStand" - - }, -}; - -Task_t tlScientistCover[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_PANIC}, // If you fail, just panic! - {TASK_STOP_MOVING, (float)0}, - {TASK_FIND_COVER_FROM_ENEMY, (float)0}, - {TASK_RUN_PATH_SCARED, (float)0}, - {TASK_TURN_LEFT, (float)179}, - {TASK_SET_SCHEDULE, (float)SCHED_HIDE}, -}; - -Schedule_t slScientistCover[] = - { - {tlScientistCover, - ARRAYSIZE(tlScientistCover), - bits_COND_NEW_ENEMY, - 0, - "ScientistCover"}, -}; - -Task_t tlScientistHide[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_PANIC}, // If you fail, just panic! - {TASK_STOP_MOVING, (float)0}, - {TASK_PLAY_SEQUENCE, (float)ACT_CROUCH}, - {TASK_SET_ACTIVITY, (float)ACT_CROUCHIDLE}, // FIXME: This looks lame - {TASK_WAIT_RANDOM, (float)10.0}, -}; - -Schedule_t slScientistHide[] = - { - {tlScientistHide, - ARRAYSIZE(tlScientistHide), - bits_COND_NEW_ENEMY | - bits_COND_HEAR_SOUND | - bits_COND_SEE_ENEMY | - bits_COND_SEE_HATE | - bits_COND_SEE_FEAR | - bits_COND_SEE_DISLIKE, - bits_SOUND_DANGER, - "ScientistHide"}, -}; - -Task_t tlScientistStartle[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_PANIC}, // If you fail, just panic! - {TASK_RANDOM_SCREAM, (float)0.3}, // Scream 30% of the time - {TASK_STOP_MOVING, (float)0}, - {TASK_PLAY_SEQUENCE_FACE_ENEMY, (float)ACT_CROUCH}, - {TASK_RANDOM_SCREAM, (float)0.1}, // Scream again 10% of the time - {TASK_PLAY_SEQUENCE_FACE_ENEMY, (float)ACT_CROUCHIDLE}, - {TASK_WAIT_RANDOM, (float)1.0}, -}; - -Schedule_t slScientistStartle[] = - { - {tlScientistStartle, - ARRAYSIZE(tlScientistStartle), - bits_COND_NEW_ENEMY | - bits_COND_SEE_ENEMY | - bits_COND_SEE_HATE | - bits_COND_SEE_FEAR | - bits_COND_SEE_DISLIKE, - 0, - "ScientistStartle"}, -}; - -Task_t tlFear[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_ENEMY, (float)0}, - {TASK_SAY_FEAR, (float)0}, - // { TASK_PLAY_SEQUENCE, (float)ACT_FEAR_DISPLAY }, -}; - -Schedule_t slFear[] = - { - {tlFear, - ARRAYSIZE(tlFear), - bits_COND_NEW_ENEMY, - 0, - "Fear"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CScientist){ - slFollow, - slFaceTarget, - slIdleSciStand, - slFear, - slScientistCover, - slScientistHide, - slScientistStartle, - slHeal, - slStopFollowing, - slSciPanic, - slFollowScared, - slFaceTargetScared, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CScientist, CTalkMonster); - -void CScientist::DeclineFollowing(void) -{ - Talk(10); - m_hTalkTarget = m_hEnemy; - PlaySentence("SC_POK", 2, VOL_NORM, ATTN_NORM); -} - -void CScientist ::Scream(void) -{ - if (FOkToSpeak()) - { - Talk(10); - m_hTalkTarget = m_hEnemy; - PlaySentence("SC_SCREAM", RANDOM_FLOAT(3, 6), VOL_NORM, ATTN_NORM); - } -} - -Activity CScientist::GetStoppedActivity(void) -{ - if (m_hEnemy != NULL) - return ACT_EXCITED; - return CTalkMonster::GetStoppedActivity(); -} - -void CScientist ::StartTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_SAY_HEAL: - // if ( FOkToSpeak() ) - Talk(2); - m_hTalkTarget = m_hTargetEnt; - PlaySentence("SC_HEAL", 2, VOL_NORM, ATTN_IDLE); - - TaskComplete(); - break; - - case TASK_SCREAM: - Scream(); - TaskComplete(); - break; - - case TASK_RANDOM_SCREAM: - if (RANDOM_FLOAT(0, 1) < pTask->flData) - Scream(); - TaskComplete(); - break; - - case TASK_SAY_FEAR: - if (FOkToSpeak()) - { - Talk(2); - m_hTalkTarget = m_hEnemy; - if (m_hEnemy->IsPlayer()) - PlaySentence("SC_PLFEAR", 5, VOL_NORM, ATTN_NORM); - else - PlaySentence("SC_FEAR", 5, VOL_NORM, ATTN_NORM); - } - TaskComplete(); - break; - - case TASK_HEAL: - m_IdealActivity = ACT_MELEE_ATTACK1; - break; - - case TASK_RUN_PATH_SCARED: - m_movementActivity = ACT_RUN_SCARED; - break; - - case TASK_MOVE_TO_TARGET_RANGE_SCARED: - { - if ((m_hTargetEnt->pev->origin - pev->origin).Length() < 1) - TaskComplete(); - else - { - m_vecMoveGoal = m_hTargetEnt->pev->origin; - if (!MoveToTarget(ACT_WALK_SCARED, 0.5)) - TaskFail(); - } - } - break; - - default: - CTalkMonster::StartTask(pTask); - break; - } -} - -void CScientist ::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_RUN_PATH_SCARED: - if (MovementIsComplete()) - TaskComplete(); - if (RANDOM_LONG(0, 31) < 8) - Scream(); - break; - - case TASK_MOVE_TO_TARGET_RANGE_SCARED: - { - if (RANDOM_LONG(0, 63) < 8) - Scream(); - - if (m_hEnemy == NULL) - { - TaskFail(); - } - else - { - float distance; - - distance = (m_vecMoveGoal - pev->origin).Length2D(); - // Re-evaluate when you think your finished, or the target has moved too far - if ((distance < pTask->flData) || (m_vecMoveGoal - m_hTargetEnt->pev->origin).Length() > pTask->flData * 0.5) - { - m_vecMoveGoal = m_hTargetEnt->pev->origin; - distance = (m_vecMoveGoal - pev->origin).Length2D(); - FRefreshRoute(); - } - - // Set the appropriate activity based on an overlapping range - // overlap the range to prevent oscillation - if (distance < pTask->flData) - { - TaskComplete(); - RouteClear(); // Stop moving - } - else if (distance < 190 && m_movementActivity != ACT_WALK_SCARED) - m_movementActivity = ACT_WALK_SCARED; - else if (distance >= 270 && m_movementActivity != ACT_RUN_SCARED) - m_movementActivity = ACT_RUN_SCARED; - } - } - break; - - case TASK_HEAL: - if (m_fSequenceFinished) - { - TaskComplete(); - } - else - { - if (TargetDistance() > 90) - TaskComplete(); - pev->ideal_yaw = UTIL_VecToYaw(m_hTargetEnt->pev->origin - pev->origin); - ChangeYaw(pev->yaw_speed); - } - break; - default: - CTalkMonster::RunTask(pTask); - break; - } -} - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CScientist ::Classify(void) -{ - return CLASS_HUMAN_PASSIVE; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CScientist ::SetYawSpeed(void) -{ - int ys; - - ys = 90; - - switch (m_Activity) - { - case ACT_IDLE: - ys = 120; - break; - case ACT_WALK: - ys = 180; - break; - case ACT_RUN: - ys = 150; - break; - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - ys = 120; - break; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CScientist ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case SCIENTIST_AE_HEAL: // Heal my target (if within range) - Heal(); - break; - case SCIENTIST_AE_NEEDLEON: - { - int oldBody = pev->body; - pev->body = (oldBody % NUM_SCIENTIST_HEADS) + NUM_SCIENTIST_HEADS * 1; - } - break; - case SCIENTIST_AE_NEEDLEOFF: - { - int oldBody = pev->body; - pev->body = (oldBody % NUM_SCIENTIST_HEADS) + NUM_SCIENTIST_HEADS * 0; - } - break; - - default: - CTalkMonster::HandleAnimEvent(pEvent); - } -} - -//========================================================= -// Spawn -//========================================================= -void CScientist ::Spawn(void) -{ - Precache(); - - SET_MODEL(ENT(pev), "models/scientist.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->health = gSkillData.scientistHealth; - pev->view_ofs = Vector(0, 0, 50); // position of the eyes relative to monster's origin. - m_flFieldOfView = VIEW_FIELD_WIDE; // NOTE: we need a wide field of view so scientists will notice player and say hello - m_MonsterState = MONSTERSTATE_NONE; - - // m_flDistTooFar = 256.0; - - m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_OPEN_DOORS | bits_CAP_AUTO_DOORS | bits_CAP_USE; - - // White hands - pev->skin = 0; - - if (pev->body == -1) - { // -1 chooses a random head - pev->body = RANDOM_LONG(0, NUM_SCIENTIST_HEADS - 1); // pick a head, any head - } - - // Luther is black, make his hands black - if (pev->body == HEAD_LUTHER) - pev->skin = 1; - - MonsterInit(); - SetUse(FollowerUse); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CScientist ::Precache(void) -{ - PRECACHE_MODEL("models/scientist.mdl"); - PRECACHE_SOUND("scientist/sci_pain1.wav"); - PRECACHE_SOUND("scientist/sci_pain2.wav"); - PRECACHE_SOUND("scientist/sci_pain3.wav"); - PRECACHE_SOUND("scientist/sci_pain4.wav"); - PRECACHE_SOUND("scientist/sci_pain5.wav"); - - // every new scientist must call this, otherwise - // when a level is loaded, nobody will talk (time is reset to 0) - TalkInit(); - - CTalkMonster::Precache(); -} - -// Init talk data -void CScientist ::TalkInit() -{ - - CTalkMonster::TalkInit(); - - // scientist will try to talk to friends in this order: - - m_szFriends[0] = "monster_scientist"; - m_szFriends[1] = "monster_sitting_scientist"; - m_szFriends[2] = "monster_barney"; - - // scientists speach group names (group names are in sentences.txt) - - m_szGrp[TLK_ANSWER] = "SC_ANSWER"; - m_szGrp[TLK_QUESTION] = "SC_QUESTION"; - m_szGrp[TLK_IDLE] = "SC_IDLE"; - m_szGrp[TLK_STARE] = "SC_STARE"; - m_szGrp[TLK_USE] = "SC_OK"; - m_szGrp[TLK_UNUSE] = "SC_WAIT"; - m_szGrp[TLK_STOP] = "SC_STOP"; - m_szGrp[TLK_NOSHOOT] = "SC_SCARED"; - m_szGrp[TLK_HELLO] = "SC_HELLO"; - - m_szGrp[TLK_PLHURT1] = "!SC_CUREA"; - m_szGrp[TLK_PLHURT2] = "!SC_CUREB"; - m_szGrp[TLK_PLHURT3] = "!SC_CUREC"; - - m_szGrp[TLK_PHELLO] = "SC_PHELLO"; - m_szGrp[TLK_PIDLE] = "SC_PIDLE"; - m_szGrp[TLK_PQUESTION] = "SC_PQUEST"; - m_szGrp[TLK_SMELL] = "SC_SMELL"; - - m_szGrp[TLK_WOUND] = "SC_WOUND"; - m_szGrp[TLK_MORTAL] = "SC_MORTAL"; - - // get voice for head - switch (pev->body % 3) - { - default: - case HEAD_GLASSES: - m_voicePitch = 105; - break; //glasses - case HEAD_EINSTEIN: - m_voicePitch = 100; - break; //einstein - case HEAD_LUTHER: - m_voicePitch = 95; - break; //luther - case HEAD_SLICK: - m_voicePitch = 100; - break; //slick - } -} - -int CScientist ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - - if (pevInflictor && pevInflictor->flags & FL_CLIENT) - { - Remember(bits_MEMORY_PROVOKED); - StopFollowing(TRUE); - } - - // make sure friends talk about it if player hurts scientist... - return CTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -//========================================================= -// ISoundMask - returns a bit mask indicating which types -// of sounds this monster regards. In the base class implementation, -// monsters care about all sounds, but no scents. -//========================================================= -int CScientist ::ISoundMask(void) -{ - return bits_SOUND_WORLD | - bits_SOUND_COMBAT | - bits_SOUND_DANGER | - bits_SOUND_PLAYER; -} - -//========================================================= -// PainSound -//========================================================= -void CScientist ::PainSound(void) -{ - if (gpGlobals->time < m_painTime) - return; - - m_painTime = gpGlobals->time + RANDOM_FLOAT(0.5, 0.75); - - switch (RANDOM_LONG(0, 4)) - { - case 0: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "scientist/sci_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - case 1: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "scientist/sci_pain2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - case 2: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "scientist/sci_pain3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - case 3: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "scientist/sci_pain4.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - case 4: - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "scientist/sci_pain5.wav", 1, ATTN_NORM, 0, GetVoicePitch()); - break; - } -} - -//========================================================= -// DeathSound -//========================================================= -void CScientist ::DeathSound(void) -{ - PainSound(); -} - -void CScientist::Killed(entvars_t *pevAttacker, int iGib) -{ - SetUse(NULL); - CTalkMonster::Killed(pevAttacker, iGib); -} - -void CScientist ::SetActivity(Activity newActivity) -{ - int iSequence; - - iSequence = LookupActivity(newActivity); - - // Set to the desired anim, or default anim if the desired is not present - if (iSequence == ACTIVITY_NOT_AVAILABLE) - newActivity = ACT_IDLE; - CTalkMonster::SetActivity(newActivity); -} - -Schedule_t *CScientist ::GetScheduleOfType(int Type) -{ - Schedule_t *psched; - - switch (Type) - { - // Hook these to make a looping schedule - case SCHED_TARGET_FACE: - // call base class default so that scientist will talk - // when 'used' - psched = CTalkMonster::GetScheduleOfType(Type); - - if (psched == slIdleStand) - return slFaceTarget; // override this for different target face behavior - else - return psched; - - case SCHED_TARGET_CHASE: - return slFollow; - - case SCHED_CANT_FOLLOW: - return slStopFollowing; - - case SCHED_PANIC: - return slSciPanic; - - case SCHED_TARGET_CHASE_SCARED: - return slFollowScared; - - case SCHED_TARGET_FACE_SCARED: - return slFaceTargetScared; - - case SCHED_IDLE_STAND: - // call base class default so that scientist will talk - // when standing during idle - psched = CTalkMonster::GetScheduleOfType(Type); - - if (psched == slIdleStand) - return slIdleSciStand; - else - return psched; - - case SCHED_HIDE: - return slScientistHide; - - case SCHED_STARTLE: - return slScientistStartle; - - case SCHED_FEAR: - return slFear; - } - - return CTalkMonster::GetScheduleOfType(Type); -} - -Schedule_t *CScientist ::GetSchedule(void) -{ - // so we don't keep calling through the EHANDLE stuff - CBaseEntity *pEnemy = m_hEnemy; - - if (HasConditions(bits_COND_HEAR_SOUND)) - { - CSound *pSound; - pSound = PBestSound(); - - ASSERT(pSound != NULL); - if (pSound && (pSound->m_iType & bits_SOUND_DANGER)) - return GetScheduleOfType(SCHED_TAKE_COVER_FROM_BEST_SOUND); - } - - switch (m_MonsterState) - { - case MONSTERSTATE_ALERT: - case MONSTERSTATE_IDLE: - if (pEnemy) - { - if (HasConditions(bits_COND_SEE_ENEMY)) - m_fearTime = gpGlobals->time; - else if (DisregardEnemy(pEnemy)) // After 15 seconds of being hidden, return to alert - { - m_hEnemy = NULL; - pEnemy = NULL; - } - } - - if (HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE)) - { - // flinch if hurt - return GetScheduleOfType(SCHED_SMALL_FLINCH); - } - - // Cower when you hear something scary - if (HasConditions(bits_COND_HEAR_SOUND)) - { - CSound *pSound; - pSound = PBestSound(); - - ASSERT(pSound != NULL); - if (pSound) - { - if (pSound->m_iType & (bits_SOUND_DANGER | bits_SOUND_COMBAT)) - { - if (gpGlobals->time - m_fearTime > 3) // Only cower every 3 seconds or so - { - m_fearTime = gpGlobals->time; // Update last fear - return GetScheduleOfType(SCHED_STARTLE); // This will just duck for a second - } - } - } - } - - // Behavior for following the player - if (IsFollowing()) - { - if (!m_hTargetEnt->IsAlive()) - { - // UNDONE: Comment about the recently dead player here? - StopFollowing(FALSE); - break; - } - - int relationship = R_NO; - - // Nothing scary, just me and the player - if (pEnemy != NULL) - relationship = IRelationship(pEnemy); - - // UNDONE: Model fear properly, fix R_FR and add multiple levels of fear - if (relationship != R_DL && relationship != R_HT) - { - // If I'm already close enough to my target - if (TargetDistance() <= 128) - { - if (CanHeal()) // Heal opportunistically - return slHeal; - if (HasConditions(bits_COND_CLIENT_PUSH)) // Player wants me to move - return GetScheduleOfType(SCHED_MOVE_AWAY_FOLLOW); - } - return GetScheduleOfType(SCHED_TARGET_FACE); // Just face and follow. - } - else // UNDONE: When afraid, scientist won't move out of your way. Keep This? If not, write move away scared - { - if (HasConditions(bits_COND_NEW_ENEMY)) // I just saw something new and scary, react - return GetScheduleOfType(SCHED_FEAR); // React to something scary - return GetScheduleOfType(SCHED_TARGET_FACE_SCARED); // face and follow, but I'm scared! - } - } - - if (HasConditions(bits_COND_CLIENT_PUSH)) // Player wants me to move - return GetScheduleOfType(SCHED_MOVE_AWAY); - - // try to say something about smells - TrySmellTalk(); - break; - case MONSTERSTATE_COMBAT: - if (HasConditions(bits_COND_NEW_ENEMY)) - return slFear; // Point and scream! - if (HasConditions(bits_COND_SEE_ENEMY)) - return slScientistCover; // Take Cover - - if (HasConditions(bits_COND_HEAR_SOUND)) - return slTakeCoverFromBestSound; // Cower and panic from the scary sound! - - return slScientistCover; // Run & Cower - break; - } - - return CTalkMonster::GetSchedule(); -} - -MONSTERSTATE CScientist ::GetIdealState(void) -{ - switch (m_MonsterState) - { - case MONSTERSTATE_ALERT: - case MONSTERSTATE_IDLE: - if (HasConditions(bits_COND_NEW_ENEMY)) - { - if (IsFollowing()) - { - int relationship = IRelationship(m_hEnemy); - if (relationship != R_FR || relationship != R_HT && !HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE)) - { - // Don't go to combat if you're following the player - m_IdealMonsterState = MONSTERSTATE_ALERT; - return m_IdealMonsterState; - } - StopFollowing(TRUE); - } - } - else if (HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE)) - { - // Stop following if you take damage - if (IsFollowing()) - StopFollowing(TRUE); - } - break; - - case MONSTERSTATE_COMBAT: - { - CBaseEntity *pEnemy = m_hEnemy; - if (pEnemy != NULL) - { - if (DisregardEnemy(pEnemy)) // After 15 seconds of being hidden, return to alert - { - // Strip enemy when going to alert - m_IdealMonsterState = MONSTERSTATE_ALERT; - m_hEnemy = NULL; - return m_IdealMonsterState; - } - // Follow if only scared a little - if (m_hTargetEnt != NULL) - { - m_IdealMonsterState = MONSTERSTATE_ALERT; - return m_IdealMonsterState; - } - - if (HasConditions(bits_COND_SEE_ENEMY)) - { - m_fearTime = gpGlobals->time; - m_IdealMonsterState = MONSTERSTATE_COMBAT; - return m_IdealMonsterState; - } - } - } - break; - } - - return CTalkMonster::GetIdealState(); -} - -BOOL CScientist::CanHeal(void) -{ - if ((m_healTime > gpGlobals->time) || (m_hTargetEnt == NULL) || (m_hTargetEnt->pev->health > (m_hTargetEnt->pev->max_health * 0.5))) - return FALSE; - - return TRUE; -} - -void CScientist::Heal(void) -{ - if (!CanHeal()) - return; - - Vector target = m_hTargetEnt->pev->origin - pev->origin; - if (target.Length() > 100) - return; - - m_hTargetEnt->TakeHealth(gSkillData.scientistHeal, DMG_GENERIC); - // Don't heal again for 1 minute - m_healTime = gpGlobals->time + 60; -} - -int CScientist::FriendNumber(int arrayNumber) -{ - static int array[3] = {1, 2, 0}; - if (arrayNumber < 3) - return array[arrayNumber]; - return arrayNumber; -} - -//========================================================= -// Dead Scientist PROP -//========================================================= -class CDeadScientist : public CBaseMonster -{ -public: - void Spawn(void); - int Classify(void) { return CLASS_HUMAN_PASSIVE; } - - void KeyValue(KeyValueData *pkvd); - int m_iPose; // which sequence to display - static char *m_szPoses[7]; -}; -char *CDeadScientist::m_szPoses[] = {"lying_on_back", "lying_on_stomach", "dead_sitting", "dead_hang", "dead_table1", "dead_table2", "dead_table3"}; - -void CDeadScientist::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "pose")) - { - m_iPose = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else - CBaseMonster::KeyValue(pkvd); -} -LINK_ENTITY_TO_CLASS(monster_scientist_dead, CDeadScientist); - -// -// ********** DeadScientist SPAWN ********** -// -void CDeadScientist ::Spawn() -{ - PRECACHE_MODEL("models/scientist.mdl"); - SET_MODEL(ENT(pev), "models/scientist.mdl"); - - pev->effects = 0; - pev->sequence = 0; - // Corpses have less health - pev->health = 8; //gSkillData.scientistHealth; - - m_bloodColor = BLOOD_COLOR_RED; - - if (pev->body == -1) - { // -1 chooses a random head - pev->body = RANDOM_LONG(0, NUM_SCIENTIST_HEADS - 1); // pick a head, any head - } - // Luther is black, make his hands black - if (pev->body == HEAD_LUTHER) - pev->skin = 1; - else - pev->skin = 0; - - pev->sequence = LookupSequence(m_szPoses[m_iPose]); - if (pev->sequence == -1) - { - ALERT(at_console, "Dead scientist with bad pose\n"); - } - - // pev->skin += 2; // use bloody skin -- UNDONE: Turn this back on when we have a bloody skin again! - MonsterInitDead(); -} - -//========================================================= -// Sitting Scientist PROP -//========================================================= - -class CSittingScientist : public CScientist // kdb: changed from public CBaseMonster so he can speak -{ -public: - void Spawn(void); - void Precache(void); - - void EXPORT SittingThink(void); - int Classify(void); - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - virtual void SetAnswerQuestion(CTalkMonster *pSpeaker); - int FriendNumber(int arrayNumber); - - int FIdleSpeak(void); - int m_baseSequence; - int m_headTurn; - float m_flResponseDelay; -}; - -LINK_ENTITY_TO_CLASS(monster_sitting_scientist, CSittingScientist); -TYPEDESCRIPTION CSittingScientist::m_SaveData[] = - { - // Don't need to save/restore m_baseSequence (recalced) - DEFINE_FIELD(CSittingScientist, m_headTurn, FIELD_INTEGER), - DEFINE_FIELD(CSittingScientist, m_flResponseDelay, FIELD_FLOAT), -}; - -IMPLEMENT_SAVERESTORE(CSittingScientist, CScientist); - -// animation sequence aliases -typedef enum -{ - SITTING_ANIM_sitlookleft, - SITTING_ANIM_sitlookright, - SITTING_ANIM_sitscared, - SITTING_ANIM_sitting2, - SITTING_ANIM_sitting3 -} SITTING_ANIM; - -// -// ********** Scientist SPAWN ********** -// -void CSittingScientist ::Spawn() -{ - PRECACHE_MODEL("models/scientist.mdl"); - SET_MODEL(ENT(pev), "models/scientist.mdl"); - Precache(); - InitBoneControllers(); - - UTIL_SetSize(pev, Vector(-14, -14, 0), Vector(14, 14, 36)); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - pev->effects = 0; - pev->health = 50; - - m_bloodColor = BLOOD_COLOR_RED; - m_flFieldOfView = VIEW_FIELD_WIDE; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - - m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD; - - SetBits(pev->spawnflags, SF_MONSTER_PREDISASTER); // predisaster only! - - if (pev->body == -1) - { // -1 chooses a random head - pev->body = RANDOM_LONG(0, NUM_SCIENTIST_HEADS - 1); // pick a head, any head - } - // Luther is black, make his hands black - if (pev->body == HEAD_LUTHER) - pev->skin = 1; - - m_baseSequence = LookupSequence("sitlookleft"); - pev->sequence = m_baseSequence + RANDOM_LONG(0, 4); - ResetSequenceInfo(); - - SetThink(SittingThink); - pev->nextthink = gpGlobals->time + 0.1; - - DROP_TO_FLOOR(ENT(pev)); -} - -void CSittingScientist ::Precache(void) -{ - m_baseSequence = LookupSequence("sitlookleft"); - TalkInit(); -} - -//========================================================= -// ID as a passive human -//========================================================= -int CSittingScientist ::Classify(void) -{ - return CLASS_HUMAN_PASSIVE; -} - -int CSittingScientist::FriendNumber(int arrayNumber) -{ - static int array[3] = {2, 1, 0}; - if (arrayNumber < 3) - return array[arrayNumber]; - return arrayNumber; -} - -//========================================================= -// sit, do stuff -//========================================================= -void CSittingScientist ::SittingThink(void) -{ - CBaseEntity *pent; - - StudioFrameAdvance(); - - // try to greet player - if (FIdleHello()) - { - pent = FindNearestFriend(TRUE); - if (pent) - { - float yaw = VecToYaw(pent->pev->origin - pev->origin) - pev->angles.y; - - if (yaw > 180) - yaw -= 360; - if (yaw < -180) - yaw += 360; - - if (yaw > 0) - pev->sequence = m_baseSequence + SITTING_ANIM_sitlookleft; - else - pev->sequence = m_baseSequence + SITTING_ANIM_sitlookright; - - ResetSequenceInfo(); - pev->frame = 0; - SetBoneController(0, 0); - } - } - else if (m_fSequenceFinished) - { - int i = RANDOM_LONG(0, 99); - m_headTurn = 0; - - if (m_flResponseDelay && gpGlobals->time > m_flResponseDelay) - { - // respond to question - IdleRespond(); - pev->sequence = m_baseSequence + SITTING_ANIM_sitscared; - m_flResponseDelay = 0; - } - else if (i < 30) - { - pev->sequence = m_baseSequence + SITTING_ANIM_sitting3; - - // turn towards player or nearest friend and speak - - if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer)) - pent = FindNearestFriend(TRUE); - else - pent = FindNearestFriend(FALSE); - - if (!FIdleSpeak() || !pent) - { - m_headTurn = RANDOM_LONG(0, 8) * 10 - 40; - pev->sequence = m_baseSequence + SITTING_ANIM_sitting3; - } - else - { - // only turn head if we spoke - float yaw = VecToYaw(pent->pev->origin - pev->origin) - pev->angles.y; - - if (yaw > 180) - yaw -= 360; - if (yaw < -180) - yaw += 360; - - if (yaw > 0) - pev->sequence = m_baseSequence + SITTING_ANIM_sitlookleft; - else - pev->sequence = m_baseSequence + SITTING_ANIM_sitlookright; - - //ALERT(at_console, "sitting speak\n"); - } - } - else if (i < 60) - { - pev->sequence = m_baseSequence + SITTING_ANIM_sitting3; - m_headTurn = RANDOM_LONG(0, 8) * 10 - 40; - if (RANDOM_LONG(0, 99) < 5) - { - //ALERT(at_console, "sitting speak2\n"); - FIdleSpeak(); - } - } - else if (i < 80) - { - pev->sequence = m_baseSequence + SITTING_ANIM_sitting2; - } - else if (i < 100) - { - pev->sequence = m_baseSequence + SITTING_ANIM_sitscared; - } - - ResetSequenceInfo(); - pev->frame = 0; - SetBoneController(0, m_headTurn); - } - pev->nextthink = gpGlobals->time + 0.1; -} - -// prepare sitting scientist to answer a question -void CSittingScientist ::SetAnswerQuestion(CTalkMonster *pSpeaker) -{ - m_flResponseDelay = gpGlobals->time + RANDOM_FLOAT(3, 4); - m_hTalkTarget = (CBaseMonster *)pSpeaker; -} - -//========================================================= -// FIdleSpeak -// ask question of nearby friend, or make statement -//========================================================= -int CSittingScientist ::FIdleSpeak(void) -{ - // try to start a conversation, or make statement - int pitch; - - if (!FOkToSpeak()) - return FALSE; - - // set global min delay for next conversation - CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(4.8, 5.2); - - pitch = GetVoicePitch(); - - // if there is a friend nearby to speak to, play sentence, set friend's response time, return - - // try to talk to any standing or sitting scientists nearby - CBaseEntity *pentFriend = FindNearestFriend(FALSE); - - if (pentFriend && RANDOM_LONG(0, 1)) - { - CTalkMonster *pTalkMonster = GetClassPtr((CTalkMonster *)pentFriend->pev); - pTalkMonster->SetAnswerQuestion(this); - - IdleHeadTurn(pentFriend->pev->origin); - SENTENCEG_PlayRndSz(ENT(pev), m_szGrp[TLK_PQUESTION], 1.0, ATTN_IDLE, 0, pitch); - // set global min delay for next conversation - CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(4.8, 5.2); - return TRUE; - } - - // otherwise, play an idle statement - if (RANDOM_LONG(0, 1)) - { - SENTENCEG_PlayRndSz(ENT(pev), m_szGrp[TLK_PIDLE], 1.0, ATTN_IDLE, 0, pitch); - // set global min delay for next conversation - CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(4.8, 5.2); - return TRUE; - } - - // never spoke - CTalkMonster::g_talkWaitTime = 0; - return FALSE; -} diff --git a/dlls/Half-life/shotgun.cpp b/dlls/Half-life/shotgun.cpp deleted file mode 100644 index 6f38f374..00000000 --- a/dlls/Half-life/shotgun.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "gamerules.h" - -// special deathmatch shotgun spreads -#define VECTOR_CONE_DM_SHOTGUN Vector( 0.08716, 0.04362, 0.00 )// 10 degrees by 5 degrees -#define VECTOR_CONE_DM_DOUBLESHOTGUN Vector( 0.17365, 0.04362, 0.00 ) // 20 degrees by 5 degrees - -enum shotgun_e { - SHOTGUN_IDLE = 0, - SHOTGUN_FIRE, - SHOTGUN_FIRE2, - SHOTGUN_RELOAD, - SHOTGUN_PUMP, - SHOTGUN_START_RELOAD, - SHOTGUN_DRAW, - SHOTGUN_HOLSTER, - SHOTGUN_IDLE4, - SHOTGUN_IDLE_DEEP -}; - -class CShotgun : public CBasePlayerWeapon -{ -public: - int Save( CSave &save ); - int Restore( CRestore &restore ); - static TYPEDESCRIPTION m_SaveData[]; - - void Spawn( void ); - void Precache( void ); - int iItemSlot( ) { return 3; } - int GetItemInfo(ItemInfo *p); - int AddToPlayer( CBasePlayer *pPlayer ); - - void PrimaryAttack( void ); - void SecondaryAttack( void ); - BOOL Deploy( ); - void Reload( void ); - void WeaponIdle( void ); - int m_fInReload; - float m_flNextReload; - int m_iShell; - float m_flPumpTime; -private: - unsigned short m_usDoubleFire; - unsigned short m_usSingleFire; -}; -LINK_ENTITY_TO_CLASS( weapon_shotgun, CShotgun ); - - -TYPEDESCRIPTION CShotgun::m_SaveData[] = -{ - DEFINE_FIELD( CShotgun, m_flNextReload, FIELD_TIME ), - DEFINE_FIELD( CShotgun, m_fInReload, FIELD_INTEGER ), - DEFINE_FIELD( CShotgun, m_flNextReload, FIELD_TIME ), - // DEFINE_FIELD( CShotgun, m_iShell, FIELD_INTEGER ), - DEFINE_FIELD( CShotgun, m_flPumpTime, FIELD_TIME ), -}; -IMPLEMENT_SAVERESTORE( CShotgun, CBasePlayerWeapon ); - - - -void CShotgun::Spawn( ) -{ - Precache( ); - m_iId = WEAPON_SHOTGUN; - SET_MODEL(ENT(pev), "models/w_shotgun.mdl"); - - m_iDefaultAmmo = SHOTGUN_DEFAULT_GIVE; - - FallInit();// get ready to fall -} - - -void CShotgun::Precache( void ) -{ - PRECACHE_MODEL("models/v_shotgun.mdl"); - PRECACHE_MODEL("models/w_shotgun.mdl"); - PRECACHE_MODEL("models/p_shotgun.mdl"); - - m_iShell = PRECACHE_MODEL ("models/shotgunshell.mdl");// shotgun shell - - PRECACHE_SOUND("items/9mmclip1.wav"); - - PRECACHE_SOUND ("weapons/dbarrel1.wav");//shotgun - PRECACHE_SOUND ("weapons/sbarrel1.wav");//shotgun - - PRECACHE_SOUND ("weapons/reload1.wav"); // shotgun reload - PRECACHE_SOUND ("weapons/reload3.wav"); // shotgun reload - -// PRECACHE_SOUND ("weapons/sshell1.wav"); // shotgun reload - played on client -// PRECACHE_SOUND ("weapons/sshell3.wav"); // shotgun reload - played on client - - PRECACHE_SOUND ("weapons/357_cock1.wav"); // gun empty sound - PRECACHE_SOUND ("weapons/scock1.wav"); // cock gun - - m_usSingleFire = PRECACHE_EVENT( 1, "events/shotgun1.sc" ); - m_usDoubleFire = PRECACHE_EVENT( 1, "events/shotgun2.sc" ); -} - -int CShotgun::AddToPlayer( CBasePlayer *pPlayer ) -{ - if ( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) - { - MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); - WRITE_BYTE( m_iId ); - MESSAGE_END(); - return TRUE; - } - return FALSE; -} - - -int CShotgun::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "buckshot"; - p->iMaxAmmo1 = BUCKSHOT_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = SHOTGUN_MAX_CLIP; - p->iSlot = 2; - p->iPosition = 1; - p->iFlags = 0; - p->iId = m_iId = WEAPON_SHOTGUN; - p->iWeight = SHOTGUN_WEIGHT; - - return 1; -} - - - -BOOL CShotgun::Deploy( ) -{ - return DefaultDeploy( "models/v_shotgun.mdl", "models/p_shotgun.mdl", SHOTGUN_DRAW, "shotgun" ); -} - - -void CShotgun::PrimaryAttack() -{ - // don't fire underwater - if (m_pPlayer->pev->waterlevel == 3) - { - PlayEmptySound( ); - m_flNextPrimaryAttack = gpGlobals->time + 0.15; - return; - } - - if (m_iClip <= 0) - { - Reload( ); - if (m_iClip == 0) - PlayEmptySound( ); - return; - } - - PLAYBACK_EVENT( 0, m_pPlayer->edict(), m_usSingleFire ); - - m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; - m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; - - m_iClip--; - - // player "shoot" animation - m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - Vector vecSrc = m_pPlayer->GetGunPosition( ); - Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); - - if ( g_pGameRules->IsDeathmatch() ) - { - // altered deathmatch spread - m_pPlayer->FireBullets( 4, vecSrc, vecAiming, VECTOR_CONE_DM_SHOTGUN, 2048, BULLET_PLAYER_BUCKSHOT, 0 ); - } - else - { - // regular old, untouched spread. - m_pPlayer->FireBullets( 6, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 0 ); - } - - if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - // HEV suit - indicate out of ammo condition - m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - - if (m_iClip != 0) - m_flPumpTime = gpGlobals->time + 0.5; - - m_flNextPrimaryAttack = gpGlobals->time + 0.75; - m_flNextSecondaryAttack = gpGlobals->time + 0.75; - if (m_iClip != 0) - m_flTimeWeaponIdle = gpGlobals->time + 5.0; - else - m_flTimeWeaponIdle = 0.75; - m_fInReload = 0; -} - - -void CShotgun::SecondaryAttack( void ) -{ - // don't fire underwater - if (m_pPlayer->pev->waterlevel == 3) - { - PlayEmptySound( ); - m_flNextPrimaryAttack = gpGlobals->time + 0.15; - return; - } - - if (m_iClip <= 1) - { - Reload( ); - PlayEmptySound( ); - return; - } - - PLAYBACK_EVENT( 0, m_pPlayer->edict(), m_usDoubleFire ); - - m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; - m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; - - m_iClip -= 2; - - // player "shoot" animation - m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - Vector vecSrc = m_pPlayer->GetGunPosition( ); - Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); - - if ( g_pGameRules->IsDeathmatch() ) - { - // tuned for deathmatch - m_pPlayer->FireBullets( 8, vecSrc, vecAiming, VECTOR_CONE_DM_DOUBLESHOTGUN, 2048, BULLET_PLAYER_BUCKSHOT, 0 ); - } - else - { - // untouched default single player - m_pPlayer->FireBullets( 12, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 0 ); - } - - if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - // HEV suit - indicate out of ammo condition - m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - - if (m_iClip != 0) - m_flPumpTime = gpGlobals->time + 0.95; - - m_flNextPrimaryAttack = gpGlobals->time + 1.5; - m_flNextSecondaryAttack = gpGlobals->time + 1.5; - if (m_iClip != 0) - m_flTimeWeaponIdle = gpGlobals->time + 6.0; - else - m_flTimeWeaponIdle = 1.5; - - m_fInReload = 0; -} - - -void CShotgun::Reload( void ) -{ - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == SHOTGUN_MAX_CLIP) - return; - - if (m_flNextReload > gpGlobals->time) - return; - - // don't reload until recoil is done - if (m_flNextPrimaryAttack > gpGlobals->time) - return; - - // check to see if we're ready to reload - if (m_fInReload == 0) - { - SendWeaponAnim( SHOTGUN_START_RELOAD ); - m_fInReload = 1; - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.6; - m_flTimeWeaponIdle = gpGlobals->time + 0.6; - m_flNextPrimaryAttack = gpGlobals->time + 1.0; - m_flNextSecondaryAttack = gpGlobals->time + 1.0; - return; - } - else if (m_fInReload == 1) - { - if (m_flTimeWeaponIdle > gpGlobals->time) - return; - // was waiting for gun to move to side - m_fInReload = 2; - - if (RANDOM_LONG(0,1)) - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/reload1.wav", 1, ATTN_NORM, 0, 85 + RANDOM_LONG(0,0x1f)); - else - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/reload3.wav", 1, ATTN_NORM, 0, 85 + RANDOM_LONG(0,0x1f)); - - SendWeaponAnim( SHOTGUN_RELOAD ); - - m_flNextReload = gpGlobals->time + 0.5; - m_flTimeWeaponIdle = gpGlobals->time + 0.5; - } - else - { - // Add them to the clip - m_iClip += 1; - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 1; - m_fInReload = 1; - } -} - - -void CShotgun::WeaponIdle( void ) -{ - ResetEmptySound( ); - - m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); - - if (m_flPumpTime && m_flPumpTime < gpGlobals->time) - { - // play pumping sound - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); - m_flPumpTime = 0; - } - - if (m_flTimeWeaponIdle < gpGlobals->time) - { - if (m_iClip == 0 && m_fInReload == 0 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - Reload( ); - } - else if (m_fInReload != 0) - { - if (m_iClip != 8 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - Reload( ); - } - else - { - // reload debounce has timed out - SendWeaponAnim( SHOTGUN_PUMP ); - - // play cocking sound - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); - m_fInReload = 0; - m_flTimeWeaponIdle = gpGlobals->time + 1.5; - } - } - else - { - int iAnim; - float flRand = RANDOM_FLOAT(0, 1); - if (flRand <= 0.8) - { - iAnim = SHOTGUN_IDLE_DEEP; - m_flTimeWeaponIdle = gpGlobals->time + (60.0/12.0);// * RANDOM_LONG(2, 5); - } - else if (flRand <= 0.95) - { - iAnim = SHOTGUN_IDLE; - m_flTimeWeaponIdle = gpGlobals->time + (20.0/9.0); - } - else - { - iAnim = SHOTGUN_IDLE4; - m_flTimeWeaponIdle = gpGlobals->time + (20.0/9.0); - } - SendWeaponAnim( iAnim ); - } - } -} - - - -class CShotgunAmmo : public CBasePlayerAmmo -{ - void Spawn( void ) - { - Precache( ); - SET_MODEL(ENT(pev), "models/w_shotbox.mdl"); - CBasePlayerAmmo::Spawn( ); - } - void Precache( void ) - { - PRECACHE_MODEL ("models/w_shotbox.mdl"); - PRECACHE_SOUND("items/9mmclip1.wav"); - } - BOOL AddAmmo( CBaseEntity *pOther ) - { - if (pOther->GiveAmmo( AMMO_BUCKSHOTBOX_GIVE, "buckshot", BUCKSHOT_MAX_CARRY ) != -1) - { - EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); - return TRUE; - } - return FALSE; - } -}; -LINK_ENTITY_TO_CLASS( ammo_buckshot, CShotgunAmmo ); - - diff --git a/dlls/Half-life/singleplay_gamerules.cpp b/dlls/Half-life/singleplay_gamerules.cpp deleted file mode 100644 index c49a71ed..00000000 --- a/dlls/Half-life/singleplay_gamerules.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// teamplay_gamerules.cpp -// -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "player.h" -#include "Weapons.h" -#include "gamerules.h" -#include "skill.h" -#include "items.h" - -extern DLL_GLOBAL CGameRules *g_pGameRules; -extern DLL_GLOBAL BOOL g_fGameOver; -extern int gmsgDeathMsg; // client dll messages -extern int gmsgScoreInfo; -extern int gmsgMOTD; - -//========================================================= -//========================================================= -CHalfLifeRules::CHalfLifeRules(void) -{ - RefreshSkillData(); -} - -//========================================================= -//========================================================= -void CHalfLifeRules::Think(void) -{ -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules::IsMultiplayer(void) -{ - return FALSE; -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules::IsDeathmatch(void) -{ - return FALSE; -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules::IsCoOp(void) -{ - return FALSE; -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules::FShouldSwitchWeapon(CBasePlayer *pPlayer, CBasePlayerItem *pWeapon) -{ - if (!pPlayer->m_pActiveItem) - { - // player doesn't have an active item! - return TRUE; - } - - if (!pPlayer->m_pActiveItem->CanHolster()) - { - return FALSE; - } - - return TRUE; -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules ::GetNextBestWeapon(CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon) -{ - return FALSE; -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules ::ClientConnected(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) -{ - return TRUE; -} - -void CHalfLifeRules ::InitHUD(CBasePlayer *pl) -{ -} - -//========================================================= -//========================================================= -void CHalfLifeRules ::ClientDisconnected(edict_t *pClient) -{ -} - -//========================================================= -//========================================================= -float CHalfLifeRules::FlPlayerFallDamage(CBasePlayer *pPlayer) -{ - // subtract off the speed at which a player is allowed to fall without being hurt, - // so damage will be based on speed beyond that, not the entire fall - pPlayer->m_flFallVelocity -= PLAYER_MAX_SAFE_FALL_SPEED; - return pPlayer->m_flFallVelocity * DAMAGE_FOR_FALL_SPEED; -} - -//========================================================= -//========================================================= -void CHalfLifeRules ::PlayerSpawn(CBasePlayer *pPlayer) -{ -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules ::AllowAutoTargetCrosshair(void) -{ - return (g_iSkillLevel == SKILL_EASY); -} - -//========================================================= -//========================================================= -void CHalfLifeRules ::PlayerThink(CBasePlayer *pPlayer) -{ -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules ::FPlayerCanRespawn(CBasePlayer *pPlayer) -{ - return TRUE; -} - -//========================================================= -//========================================================= -float CHalfLifeRules ::FlPlayerSpawnTime(CBasePlayer *pPlayer) -{ - return gpGlobals->time; //now! -} - -//========================================================= -// IPointsForKill - how many points awarded to anyone -// that kills this player? -//========================================================= -int CHalfLifeRules ::IPointsForKill(CBasePlayer *pAttacker, CBasePlayer *pKilled) -{ - return 1; -} - -//========================================================= -// PlayerKilled - someone/something killed this player -//========================================================= -void CHalfLifeRules ::PlayerKilled(CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor) -{ -} - -//========================================================= -// Deathnotice -//========================================================= -void CHalfLifeRules::DeathNotice(CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor) -{ -} - -//========================================================= -// PlayerGotWeapon - player has grabbed a weapon that was -// sitting in the world -//========================================================= -void CHalfLifeRules ::PlayerGotWeapon(CBasePlayer *pPlayer, CBasePlayerItem *pWeapon) -{ -} - -//========================================================= -// FlWeaponRespawnTime - what is the time in the future -// at which this weapon may spawn? -//========================================================= -float CHalfLifeRules ::FlWeaponRespawnTime(CBasePlayerItem *pWeapon) -{ - return -1; -} - -//========================================================= -// FlWeaponRespawnTime - Returns 0 if the weapon can respawn -// now, otherwise it returns the time at which it can try -// to spawn again. -//========================================================= -float CHalfLifeRules ::FlWeaponTryRespawn(CBasePlayerItem *pWeapon) -{ - return 0; -} - -//========================================================= -// VecWeaponRespawnSpot - where should this weapon spawn? -// Some game variations may choose to randomize spawn locations -//========================================================= -Vector CHalfLifeRules ::VecWeaponRespawnSpot(CBasePlayerItem *pWeapon) -{ - return pWeapon->pev->origin; -} - -//========================================================= -// WeaponShouldRespawn - any conditions inhibiting the -// respawning of this weapon? -//========================================================= -int CHalfLifeRules ::WeaponShouldRespawn(CBasePlayerItem *pWeapon) -{ - return GR_WEAPON_RESPAWN_NO; -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules::CanHaveItem(CBasePlayer *pPlayer, CItem *pItem) -{ - return TRUE; -} - -//========================================================= -//========================================================= -void CHalfLifeRules::PlayerGotItem(CBasePlayer *pPlayer, CItem *pItem) -{ -} - -//========================================================= -//========================================================= -int CHalfLifeRules::ItemShouldRespawn(CItem *pItem) -{ - return GR_ITEM_RESPAWN_NO; -} - -//========================================================= -// At what time in the future may this Item respawn? -//========================================================= -float CHalfLifeRules::FlItemRespawnTime(CItem *pItem) -{ - return -1; -} - -//========================================================= -// Where should this item respawn? -// Some game variations may choose to randomize spawn locations -//========================================================= -Vector CHalfLifeRules::VecItemRespawnSpot(CItem *pItem) -{ - return pItem->pev->origin; -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules::IsAllowedToSpawn(CBaseEntity *pEntity) -{ - return TRUE; -} - -//========================================================= -//========================================================= -void CHalfLifeRules::PlayerGotAmmo(CBasePlayer *pPlayer, char *szName, int iCount) -{ -} - -//========================================================= -//========================================================= -int CHalfLifeRules::AmmoShouldRespawn(CBasePlayerAmmo *pAmmo) -{ - return GR_AMMO_RESPAWN_NO; -} - -//========================================================= -//========================================================= -float CHalfLifeRules::FlAmmoRespawnTime(CBasePlayerAmmo *pAmmo) -{ - return -1; -} - -//========================================================= -//========================================================= -Vector CHalfLifeRules::VecAmmoRespawnSpot(CBasePlayerAmmo *pAmmo) -{ - return pAmmo->pev->origin; -} - -//========================================================= -//========================================================= -float CHalfLifeRules::FlHealthChargerRechargeTime(void) -{ - return 0; // don't recharge -} - -//========================================================= -//========================================================= -int CHalfLifeRules::DeadPlayerWeapons(CBasePlayer *pPlayer) -{ - return GR_PLR_DROP_GUN_NO; -} - -//========================================================= -//========================================================= -int CHalfLifeRules::DeadPlayerAmmo(CBasePlayer *pPlayer) -{ - return GR_PLR_DROP_AMMO_NO; -} - -//========================================================= -//========================================================= -int CHalfLifeRules::PlayerRelationship(CBaseEntity *pPlayer, CBaseEntity *pTarget) -{ - // why would a single player in half life need this? - return GR_NOTTEAMMATE; -} - -//========================================================= -//========================================================= -BOOL CHalfLifeRules ::FAllowMonsters(void) -{ - return TRUE; -} diff --git a/dlls/Half-life/sound.cpp b/dlls/Half-life/sound.cpp index 6368f74c..aa6a2b0c 100644 --- a/dlls/Half-life/sound.cpp +++ b/dlls/Half-life/sound.cpp @@ -22,7 +22,6 @@ #include "MSDLLHeaders.h" #include "Weapons.h" #include "player.h" -#include "talkmonster.h" #include "gamerules.h" static char *memfgets(byte *pMemFile, int fileSize, int &filePos, char *pBuffer, int bufferSize); @@ -1931,6 +1930,7 @@ void CSpeaker ::Spawn(void) #define ANNOUNCE_MINUTES_MIN 0.25 #define ANNOUNCE_MINUTES_MAX 2.25 +static float g_talkWaitTime = 0.0f; // time delay until it's ok to speak: used so that two NPCs don't talk at once void CSpeaker ::Precache(void) { @@ -1947,9 +1947,9 @@ void CSpeaker ::SpeakerThink(void) int pitch = 100; // Wait for the talkmonster to finish first. - if (gpGlobals->time <= CTalkMonster::g_talkWaitTime) + if (gpGlobals->time <= g_talkWaitTime) { - pev->nextthink = CTalkMonster::g_talkWaitTime + RANDOM_FLOAT(5, 10); + pev->nextthink = g_talkWaitTime + RANDOM_FLOAT(5, 10); return; } @@ -2019,7 +2019,7 @@ void CSpeaker ::SpeakerThink(void) pev->nextthink = gpGlobals->time + RANDOM_FLOAT(ANNOUNCE_MINUTES_MIN * 60.0, ANNOUNCE_MINUTES_MAX * 60.0); - CTalkMonster::g_talkWaitTime = gpGlobals->time + 5; // time delay until it's ok to speak: used so that two NPCs don't talk at once + g_talkWaitTime = gpGlobals->time + 5; // time delay until it's ok to speak: used so that two NPCs don't talk at once } return; diff --git a/dlls/Half-life/squadmonster.cpp b/dlls/Half-life/squadmonster.cpp deleted file mode 100644 index a3e81bc1..00000000 --- a/dlls/Half-life/squadmonster.cpp +++ /dev/null @@ -1,613 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// Squadmonster functions -//========================================================= -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "nodes.h" -#include "monsters.h" -#include "animation.h" -#include "saverestore.h" -#include "squadmonster.h" -#include "plane.h" - -//========================================================= -// Save/Restore -//========================================================= -TYPEDESCRIPTION CSquadMonster::m_SaveData[] = - { - DEFINE_FIELD(CSquadMonster, m_hSquadLeader, FIELD_EHANDLE), - DEFINE_ARRAY(CSquadMonster, m_hSquadMember, FIELD_EHANDLE, MAX_SQUAD_MEMBERS - 1), - - // DEFINE_FIELD( CSquadMonster, m_afSquadSlots, FIELD_INTEGER ), // these need to be reset after transitions! - DEFINE_FIELD(CSquadMonster, m_fEnemyEluded, FIELD_BOOLEAN), - DEFINE_FIELD(CSquadMonster, m_flLastEnemySightTime, FIELD_TIME), - - DEFINE_FIELD(CSquadMonster, m_iMySlot, FIELD_INTEGER), - -}; - -IMPLEMENT_SAVERESTORE(CSquadMonster, CBaseMonster); - -//========================================================= -// OccupySlot - if any slots of the passed slots are -// available, the monster will be assigned to one. -//========================================================= -BOOL CSquadMonster ::OccupySlot(int iDesiredSlots) -{ - int i; - int iMask; - int iSquadSlots; - - if (!InSquad()) - { - return TRUE; - } - - if (SquadEnemySplit()) - { - // if the squad members aren't all fighting the same enemy, slots are disabled - // so that a squad member doesn't get stranded unable to engage his enemy because - // all of the attack slots are taken by squad members fighting other enemies. - m_iMySlot = bits_SLOT_SQUAD_SPLIT; - return TRUE; - } - - CSquadMonster *pSquadLeader = MySquadLeader(); - - if (!(iDesiredSlots ^ pSquadLeader->m_afSquadSlots)) - { - // none of the desired slots are available. - return FALSE; - } - - iSquadSlots = pSquadLeader->m_afSquadSlots; - - for (i = 0; i < NUM_SLOTS; i++) - { - iMask = 1 << i; - if (iDesiredSlots & iMask) // am I looking for this bit? - { - if (!(iSquadSlots & iMask)) // Is it already taken? - { - // No, use this bit - pSquadLeader->m_afSquadSlots |= iMask; - m_iMySlot = iMask; - // ALERT ( at_aiconsole, "Took slot %d - %d\n", i, m_hSquadLeader->m_afSquadSlots ); - return TRUE; - } - } - } - - return FALSE; -} - -//========================================================= -// VacateSlot -//========================================================= -void CSquadMonster ::VacateSlot() -{ - if (m_iMySlot != bits_NO_SLOT && InSquad()) - { - // ALERT ( at_aiconsole, "Vacated Slot %d - %d\n", m_iMySlot, m_hSquadLeader->m_afSquadSlots ); - MySquadLeader()->m_afSquadSlots &= ~m_iMySlot; - m_iMySlot = bits_NO_SLOT; - } -} - -//========================================================= -// ScheduleChange -//========================================================= -void CSquadMonster ::ScheduleChange(void) -{ - VacateSlot(); -} - -//========================================================= -// Killed -//========================================================= -void CSquadMonster ::Killed(entvars_t *pevAttacker, int iGib) -{ - VacateSlot(); - - if (InSquad()) - { - MySquadLeader()->SquadRemove(this); - } - - CBaseMonster ::Killed(pevAttacker, iGib); -} - -// These functions are still awaiting conversion to CSquadMonster - -//========================================================= -// -// SquadRemove(), remove pRemove from my squad. -// If I am pRemove, promote m_pSquadNext to leader -// -//========================================================= -void CSquadMonster ::SquadRemove(CSquadMonster *pRemove) -{ - ASSERT(pRemove != NULL); - ASSERT(this->IsLeader()); - ASSERT(pRemove->m_hSquadLeader == this); - - // If I'm the leader, get rid of my squad - if (pRemove == MySquadLeader()) - { - for (int i = 0; i < MAX_SQUAD_MEMBERS - 1; i++) - { - CSquadMonster *pMember = MySquadMember(i); - if (pMember) - { - pMember->m_hSquadLeader = NULL; - m_hSquadMember[i] = NULL; - } - } - } - else - { - CSquadMonster *pSquadLeader = MySquadLeader(); - if (pSquadLeader) - { - for (int i = 0; i < MAX_SQUAD_MEMBERS - 1; i++) - { - if (pSquadLeader->m_hSquadMember[i] == this) - { - pSquadLeader->m_hSquadMember[i] = NULL; - break; - } - } - } - } - - pRemove->m_hSquadLeader = NULL; -} - -//========================================================= -// -// SquadAdd(), add pAdd to my squad -// -//========================================================= -BOOL CSquadMonster ::SquadAdd(CSquadMonster *pAdd) -{ - ASSERT(pAdd != NULL); - ASSERT(!pAdd->InSquad()); - ASSERT(this->IsLeader()); - - for (int i = 0; i < MAX_SQUAD_MEMBERS - 1; i++) - { - if (m_hSquadMember[i] == NULL) - { - m_hSquadMember[i] = pAdd; - pAdd->m_hSquadLeader = this; - return TRUE; - } - } - return FALSE; - // should complain here -} - -//========================================================= -// -// SquadPasteEnemyInfo - called by squad members that have -// current info on the enemy so that it can be stored for -// members who don't have current info. -// -//========================================================= -void CSquadMonster ::SquadPasteEnemyInfo(void) -{ - CSquadMonster *pSquadLeader = MySquadLeader(); - if (pSquadLeader) - pSquadLeader->m_vecEnemyLKP = m_vecEnemyLKP; -} - -//========================================================= -// -// SquadCopyEnemyInfo - called by squad members who don't -// have current info on the enemy. Reads from the same fields -// in the leader's data that other squad members write to, -// so the most recent data is always available here. -// -//========================================================= -void CSquadMonster ::SquadCopyEnemyInfo(void) -{ - CSquadMonster *pSquadLeader = MySquadLeader(); - if (pSquadLeader) - m_vecEnemyLKP = pSquadLeader->m_vecEnemyLKP; -} - -//========================================================= -// -// SquadMakeEnemy - makes everyone in the squad angry at -// the same entity. -// -//========================================================= -void CSquadMonster ::SquadMakeEnemy(CBaseEntity *pEnemy) -{ - if (!InSquad()) - return; - - if (!pEnemy) - { - ALERT(at_console, "ERROR: SquadMakeEnemy() - pEnemy is NULL!\n"); - return; - } - - CSquadMonster *pSquadLeader = MySquadLeader(); - for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) - { - CSquadMonster *pMember = pSquadLeader->MySquadMember(i); - if (pMember) - { - // reset members who aren't activly engaged in fighting - if (pMember->m_hEnemy != pEnemy && !pMember->HasConditions(bits_COND_SEE_ENEMY)) - { - if (pMember->m_hEnemy != NULL) - { - // remember their current enemy - pMember->PushEnemy(pMember->m_hEnemy, pMember->m_vecEnemyLKP); - } - // give them a new enemy - pMember->m_hEnemy = pEnemy; - pMember->m_vecEnemyLKP = pEnemy->pev->origin; - pMember->SetConditions(bits_COND_NEW_ENEMY); - } - } - } -} - -//========================================================= -// -// SquadCount(), return the number of members of this squad -// callable from leaders & followers -// -//========================================================= -int CSquadMonster ::SquadCount(void) -{ - if (!InSquad()) - return 0; - - CSquadMonster *pSquadLeader = MySquadLeader(); - int squadCount = 0; - for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) - { - if (pSquadLeader->MySquadMember(i) != NULL) - squadCount++; - } - - return squadCount; -} - -//========================================================= -// -// SquadRecruit(), get some monsters of my classification and -// link them as a group. returns the group size -// -//========================================================= -int CSquadMonster ::SquadRecruit(int searchRadius, int maxMembers) -{ - int squadCount; - int iMyClass = Classify(); // cache this monster's class - - // Don't recruit if I'm already in a group - if (InSquad()) - return 0; - - if (maxMembers < 2) - return 0; - - // I am my own leader - m_hSquadLeader = this; - squadCount = 1; - - CBaseEntity *pEntity = NULL; - - if (!FStringNull(pev->netname)) - { - // I have a netname, so unconditionally recruit everyone else with that name. - pEntity = UTIL_FindEntityByString(pEntity, "netname", STRING(pev->netname)); - while (pEntity) - { - CSquadMonster *pRecruit = pEntity->MySquadMonsterPointer(); - - if (pRecruit) - { - if (!pRecruit->InSquad() && pRecruit->Classify() == iMyClass && pRecruit != this) - { - // minimum protection here against user error.in worldcraft. - if (!SquadAdd(pRecruit)) - break; - squadCount++; - } - } - - pEntity = UTIL_FindEntityByString(pEntity, "netname", STRING(pev->netname)); - } - } - else - { - while ((pEntity = UTIL_FindEntityInSphere(pEntity, pev->origin, searchRadius)) != NULL) - { - CSquadMonster *pRecruit = pEntity->MySquadMonsterPointer(); - - if (pRecruit && pRecruit != this && pRecruit->IsAlive() && !pRecruit->m_pCine) - { - // Can we recruit this guy? - if (!pRecruit->InSquad() && pRecruit->Classify() == iMyClass && - ((iMyClass != CLASS_ALIEN_MONSTER) || FStrEq(STRING(pev->classname), STRING(pRecruit->pev->classname))) && - FStringNull(pRecruit->pev->netname)) - { - TraceResult tr; - UTIL_TraceLine(pev->origin + pev->view_ofs, pRecruit->pev->origin + pev->view_ofs, ignore_monsters, pRecruit->edict(), &tr); // try to hit recruit with a traceline. - if (tr.flFraction == 1.0) - { - if (!SquadAdd(pRecruit)) - break; - - squadCount++; - } - } - } - } - } - - // no single member squads - if (squadCount == 1) - { - m_hSquadLeader = NULL; - } - - return squadCount; -} - -//========================================================= -// CheckEnemy -//========================================================= -int CSquadMonster ::CheckEnemy(CBaseEntity *pEnemy) -{ - int iUpdatedLKP; - - iUpdatedLKP = CBaseMonster ::CheckEnemy(m_hEnemy); - - // communicate with squad members about the enemy IF this individual has the same enemy as the squad leader. - if (InSquad() && (CBaseEntity *)m_hEnemy == MySquadLeader()->m_hEnemy) - { - if (iUpdatedLKP) - { - // have new enemy information, so paste to the squad. - SquadPasteEnemyInfo(); - } - else - { - // enemy unseen, copy from the squad knowledge. - SquadCopyEnemyInfo(); - } - } - - return iUpdatedLKP; -} - -//========================================================= -// StartMonster -//========================================================= -void CSquadMonster ::StartMonster(void) -{ - CBaseMonster ::StartMonster(); - - if ((m_afCapability & bits_CAP_SQUAD) && !InSquad()) - { - if (!FStringNull(pev->netname)) - { - // if I have a groupname, I can only recruit if I'm flagged as leader - if (!(pev->spawnflags & SF_SQUADMONSTER_LEADER)) - { - return; - } - } - - // try to form squads now. - int iSquadSize = SquadRecruit(1024, 4); - - if (iSquadSize) - { - ALERT(at_aiconsole, "Squad of %d %s formed\n", iSquadSize, STRING(pev->classname)); - } - - if (IsLeader() && FClassnameIs(pev, "monster_human_grunt")) - { - SetBodygroup(1, 1); // UNDONE: truly ugly hack - pev->skin = 0; - } - } -} - -//========================================================= -// NoFriendlyFire - checks for possibility of friendly fire -// -// Builds a large box in front of the grunt and checks to see -// if any squad members are in that box. -//========================================================= -BOOL CSquadMonster ::NoFriendlyFire(void) -{ - if (!InSquad()) - { - return TRUE; - } - - CPlane backPlane; - CPlane leftPlane; - CPlane rightPlane; - - Vector vecLeftSide; - Vector vecRightSide; - Vector v_left; - - //!!!BUGBUG - to fix this, the planes must be aligned to where the monster will be firing its gun, not the direction it is facing!!! - - if (m_hEnemy != NULL) - { - UTIL_MakeVectors(UTIL_VecToAngles(m_hEnemy->Center() - pev->origin)); - } - else - { - // if there's no enemy, pretend there's a friendly in the way, so the grunt won't shoot. - return FALSE; - } - - //UTIL_MakeVectors ( pev->angles ); - - vecLeftSide = pev->origin - (gpGlobals->v_right * (pev->size.x * 1.5)); - vecRightSide = pev->origin + (gpGlobals->v_right * (pev->size.x * 1.5)); - v_left = gpGlobals->v_right * -1; - - leftPlane.InitializePlane(gpGlobals->v_right, vecLeftSide); - rightPlane.InitializePlane(v_left, vecRightSide); - backPlane.InitializePlane(gpGlobals->v_forward, pev->origin); - - /* - ALERT ( at_console, "LeftPlane: %f %f %f : %f\n", leftPlane.m_vecNormal.x, leftPlane.m_vecNormal.y, leftPlane.m_vecNormal.z, leftPlane.m_flDist ); - ALERT ( at_console, "RightPlane: %f %f %f : %f\n", rightPlane.m_vecNormal.x, rightPlane.m_vecNormal.y, rightPlane.m_vecNormal.z, rightPlane.m_flDist ); - ALERT ( at_console, "BackPlane: %f %f %f : %f\n", backPlane.m_vecNormal.x, backPlane.m_vecNormal.y, backPlane.m_vecNormal.z, backPlane.m_flDist ); -*/ - - CSquadMonster *pSquadLeader = MySquadLeader(); - for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) - { - CSquadMonster *pMember = pSquadLeader->MySquadMember(i); - if (pMember && pMember != this) - { - - if (backPlane.PointInFront(pMember->pev->origin) && - leftPlane.PointInFront(pMember->pev->origin) && - rightPlane.PointInFront(pMember->pev->origin)) - { - // this guy is in the check volume! Don't shoot! - return FALSE; - } - } - } - - return TRUE; -} - -//========================================================= -// GetIdealState - surveys the Conditions information available -// and finds the best new state for a monster. -//========================================================= -MONSTERSTATE CSquadMonster ::GetIdealState(void) -{ - int iConditions; - - iConditions = IScheduleFlags(); - - // If no schedule conditions, the new ideal state is probably the reason we're in here. - switch (m_MonsterState) - { - case MONSTERSTATE_IDLE: - case MONSTERSTATE_ALERT: - if (HasConditions(bits_COND_NEW_ENEMY) && InSquad()) - { - SquadMakeEnemy(m_hEnemy); - } - break; - } - - return CBaseMonster ::GetIdealState(); -} - -//========================================================= -// FValidateCover - determines whether or not the chosen -// cover location is a good one to move to. (currently based -// on proximity to others in the squad) -//========================================================= -BOOL CSquadMonster ::FValidateCover(const Vector &vecCoverLocation) -{ - if (!InSquad()) - { - return TRUE; - } - - if (SquadMemberInRange(vecCoverLocation, 128)) - { - // another squad member is too close to this piece of cover. - return FALSE; - } - - return TRUE; -} - -//========================================================= -// SquadEnemySplit- returns TRUE if not all squad members -// are fighting the same enemy. -//========================================================= -BOOL CSquadMonster ::SquadEnemySplit(void) -{ - if (!InSquad()) - return FALSE; - - CSquadMonster *pSquadLeader = MySquadLeader(); - CBaseEntity *pEnemy = pSquadLeader->m_hEnemy; - - for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) - { - CSquadMonster *pMember = pSquadLeader->MySquadMember(i); - if (pMember != NULL && pMember->m_hEnemy != NULL && pMember->m_hEnemy != pEnemy) - { - return TRUE; - } - } - return FALSE; -} - -//========================================================= -// FValidateCover - determines whether or not the chosen -// cover location is a good one to move to. (currently based -// on proximity to others in the squad) -//========================================================= -BOOL CSquadMonster ::SquadMemberInRange(const Vector &vecLocation, float flDist) -{ - if (!InSquad()) - return FALSE; - - CSquadMonster *pSquadLeader = MySquadLeader(); - - for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) - { - CSquadMonster *pSquadMember = pSquadLeader->MySquadMember(i); - if (pSquadMember && (vecLocation - pSquadMember->pev->origin).Length2D() <= flDist) - return TRUE; - } - return FALSE; -} - -extern Schedule_t slChaseEnemyFailed[]; - -Schedule_t *CSquadMonster::GetScheduleOfType(int iType) -{ - switch (iType) - { - - case SCHED_CHASE_ENEMY_FAILED: - { - return &slChaseEnemyFailed[0]; - } - - default: - return CBaseMonster::GetScheduleOfType(iType); - } -} diff --git a/dlls/Half-life/squadmonster.h b/dlls/Half-life/squadmonster.h deleted file mode 100644 index 99e0e507..00000000 --- a/dlls/Half-life/squadmonster.h +++ /dev/null @@ -1,119 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// CSquadMonster - all the extra data for monsters that -// form squads. -//========================================================= - -#define SF_SQUADMONSTER_LEADER 32 - -#define bits_NO_SLOT 0 - -// HUMAN GRUNT SLOTS -#define bits_SLOT_HGRUNT_ENGAGE1 (1 << 0) -#define bits_SLOT_HGRUNT_ENGAGE2 (1 << 1) -#define bits_SLOTS_HGRUNT_ENGAGE (bits_SLOT_HGRUNT_ENGAGE1 | bits_SLOT_HGRUNT_ENGAGE2) - -#define bits_SLOT_HGRUNT_GRENADE1 (1 << 2) -#define bits_SLOT_HGRUNT_GRENADE2 (1 << 3) -#define bits_SLOTS_HGRUNT_GRENADE (bits_SLOT_HGRUNT_GRENADE1 | bits_SLOT_HGRUNT_GRENADE2) - -// ALIEN GRUNT SLOTS -#define bits_SLOT_AGRUNT_HORNET1 (1 << 4) -#define bits_SLOT_AGRUNT_HORNET2 (1 << 5) -#define bits_SLOT_AGRUNT_CHASE (1 << 6) -#define bits_SLOTS_AGRUNT_HORNET (bits_SLOT_AGRUNT_HORNET1 | bits_SLOT_AGRUNT_HORNET2) - -// HOUNDEYE SLOTS -#define bits_SLOT_HOUND_ATTACK1 (1 << 7) -#define bits_SLOT_HOUND_ATTACK2 (1 << 8) -#define bits_SLOT_HOUND_ATTACK3 (1 << 9) -#define bits_SLOTS_HOUND_ATTACK (bits_SLOT_HOUND_ATTACK1 | bits_SLOT_HOUND_ATTACK2 | bits_SLOT_HOUND_ATTACK3) - -// global slots -#define bits_SLOT_SQUAD_SPLIT (1 << 10) // squad members don't all have the same enemy - -#define NUM_SLOTS 11 // update this every time you add/remove a slot. - -#define MAX_SQUAD_MEMBERS 5 - -#pragma message("SquadMonster.h Inlcuded!") -//========================================================= -// CSquadMonster - for any monster that forms squads. -//========================================================= -class CSquadMonster : public CBaseMonster -{ -public: - // squad leader info - EHANDLE m_hSquadLeader; // who is my leader - EHANDLE m_hSquadMember[MAX_SQUAD_MEMBERS - 1]; // valid only for leader - int m_afSquadSlots; - float m_flLastEnemySightTime; // last time anyone in the squad saw the enemy - BOOL m_fEnemyEluded; - - // squad member info - int m_iMySlot; // this is the behaviour slot that the monster currently holds in the squad. - - int CheckEnemy(CBaseEntity *pEnemy); - void StartMonster(void); - void VacateSlot(void); - void ScheduleChange(void); - void Killed(entvars_t *pevAttacker, int iGib); - BOOL OccupySlot(int iDesiredSlot); - BOOL NoFriendlyFire(void); - - // squad functions still left in base class - CSquadMonster *MySquadLeader() - { - CSquadMonster *pSquadLeader = (CSquadMonster *)((CBaseEntity *)m_hSquadLeader); - if (pSquadLeader != NULL) - return pSquadLeader; - return this; - } - CSquadMonster *MySquadMember(int i) - { - if (i >= MAX_SQUAD_MEMBERS - 1) - return this; - else - return (CSquadMonster *)((CBaseEntity *)m_hSquadMember[i]); - } - int InSquad(void) { return m_hSquadLeader != NULL; } - int IsLeader(void) { return m_hSquadLeader == this; } - int SquadJoin(int searchRadius); - int SquadRecruit(int searchRadius, int maxMembers); - int SquadCount(void); - void SquadRemove(CSquadMonster *pRemove); - void SquadUnlink(void); - BOOL SquadAdd(CSquadMonster *pAdd); - void SquadDisband(void); - void SquadAddConditions(int iConditions); - void SquadMakeEnemy(CBaseEntity *pEnemy); - void SquadPasteEnemyInfo(void); - void SquadCopyEnemyInfo(void); - BOOL SquadEnemySplit(void); - BOOL SquadMemberInRange(const Vector &vecLocation, float flDist); - - virtual CSquadMonster *MySquadMonsterPointer(void) { return this; } - - static TYPEDESCRIPTION m_SaveData[]; - - int Save(CSave &save); - int Restore(CRestore &restore); - - BOOL FValidateCover(const Vector &vecCoverLocation); - - MONSTERSTATE GetIdealState(void); - Schedule_t *GetScheduleOfType(int iType); -}; diff --git a/dlls/Half-life/squeakgrenade.cpp b/dlls/Half-life/squeakgrenade.cpp deleted file mode 100644 index 6da95267..00000000 --- a/dlls/Half-life/squeakgrenade.cpp +++ /dev/null @@ -1,590 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "soundent.h" -#include "gamerules.h" - -enum w_squeak_e -{ - WSQUEAK_IDLE1 = 0, - WSQUEAK_FIDGET, - WSQUEAK_JUMP, - WSQUEAK_RUN, -}; - -enum squeak_e -{ - SQUEAK_IDLE1 = 0, - SQUEAK_FIDGETFIT, - SQUEAK_FIDGETNIP, - SQUEAK_DOWN, - SQUEAK_UP, - SQUEAK_THROW -}; - -class CSqueakGrenade : public CGrenade -{ - void Spawn(void); - void Precache(void); - int Classify(void); - void EXPORT SuperBounceTouch(CBaseEntity *pOther); - void EXPORT HuntThink(void); - int BloodColor(void) { return BLOOD_COLOR_YELLOW; } - void Killed(entvars_t *pevAttacker, int iGib); - void GibMonster(void); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - - static TYPEDESCRIPTION m_SaveData[]; - - static float m_flNextBounceSoundTime; - - // CBaseEntity *m_pTarget; - float m_flDie; - Vector m_vecTarget; - float m_flNextHunt; - float m_flNextHit; - Vector m_posPrev; - EHANDLE m_hOwner; - int m_iMyClass; -}; - -float CSqueakGrenade::m_flNextBounceSoundTime = 0; - -LINK_ENTITY_TO_CLASS(monster_snark, CSqueakGrenade); -TYPEDESCRIPTION CSqueakGrenade::m_SaveData[] = - { - DEFINE_FIELD(CSqueakGrenade, m_flDie, FIELD_TIME), - DEFINE_FIELD(CSqueakGrenade, m_vecTarget, FIELD_VECTOR), - DEFINE_FIELD(CSqueakGrenade, m_flNextHunt, FIELD_TIME), - DEFINE_FIELD(CSqueakGrenade, m_flNextHit, FIELD_TIME), - DEFINE_FIELD(CSqueakGrenade, m_posPrev, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CSqueakGrenade, m_hOwner, FIELD_EHANDLE), -}; - -IMPLEMENT_SAVERESTORE(CSqueakGrenade, CGrenade); - -#define SQUEEK_DETONATE_DELAY 15.0 - -int CSqueakGrenade ::Classify(void) -{ - if (m_iMyClass != 0) - return m_iMyClass; // protect against recursion - - if (m_hEnemy != NULL) - { - m_iMyClass = CLASS_INSECT; // no one cares about it - switch (m_hEnemy->Classify()) - { - case CLASS_PLAYER: - case CLASS_HUMAN_PASSIVE: - case CLASS_HUMAN_MILITARY: - m_iMyClass = 0; - return CLASS_ALIEN_MILITARY; // barney's get mad, grunts get mad at it - } - m_iMyClass = 0; - } - - return CLASS_ALIEN_BIOWEAPON; -} - -void CSqueakGrenade ::Spawn(void) -{ - Precache(); - // motor - pev->movetype = MOVETYPE_BOUNCE; - pev->solid = SOLID_BBOX; - - SET_MODEL(ENT(pev), "models/w_squeak.mdl"); - UTIL_SetSize(pev, Vector(-4, -4, 0), Vector(4, 4, 8)); - UTIL_SetOrigin(pev, pev->origin); - - SetTouch(SuperBounceTouch); - SetThink(HuntThink); - pev->nextthink = gpGlobals->time + 0.1; - m_flNextHunt = gpGlobals->time + 1E6; - - pev->flags |= FL_MONSTER; - pev->takedamage = DAMAGE_AIM; - pev->health = gSkillData.snarkHealth; - pev->gravity = 0.5; - pev->friction = 0.5; - - pev->dmg = gSkillData.snarkDmgPop; - - m_flDie = gpGlobals->time + SQUEEK_DETONATE_DELAY; - - m_flFieldOfView = 0; // 180 degrees - - if (pev->owner) - m_hOwner = Instance(pev->owner); - - m_flNextBounceSoundTime = gpGlobals->time; // reset each time a snark is spawned. - - pev->sequence = WSQUEAK_RUN; - ResetSequenceInfo(); -} - -void CSqueakGrenade::Precache(void) -{ - PRECACHE_MODEL("models/w_squeak.mdl"); - PRECACHE_SOUND("squeek/sqk_blast1.wav"); - PRECACHE_SOUND("common/bodysplat.wav"); - PRECACHE_SOUND("squeek/sqk_die1.wav"); - PRECACHE_SOUND("squeek/sqk_hunt1.wav"); - PRECACHE_SOUND("squeek/sqk_hunt2.wav"); - PRECACHE_SOUND("squeek/sqk_hunt3.wav"); - PRECACHE_SOUND("squeek/sqk_deploy1.wav"); -} - -void CSqueakGrenade ::Killed(entvars_t *pevAttacker, int iGib) -{ - pev->model = iStringNull; // make invisible - SetThink(SUB_Remove); - SetTouch(NULL); - pev->nextthink = gpGlobals->time + 0.1; - - // since squeak grenades never leave a body behind, clear out their takedamage now. - // Squeaks do a bit of radius damage when they pop, and that radius damage will - // continue to call this function unless we acknowledge the Squeak's death now. (sjb) - pev->takedamage = DAMAGE_NO; - - // play squeek blast - EMIT_SOUND_DYN(ENT(pev), CHAN_ITEM, "squeek/sqk_blast1.wav", 1, 0.5, 0, PITCH_NORM); - - CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, SMALL_EXPLOSION_VOLUME, 3.0); - - UTIL_BloodDrips(pev->origin, g_vecZero, BloodColor(), 80); - - if (m_hOwner != NULL) - RadiusDamage(pev, m_hOwner->pev, pev->dmg, CLASS_NONE, DMG_BLAST); - else - RadiusDamage(pev, pev, pev->dmg, CLASS_NONE, DMG_BLAST); - - // reset owner so death message happens - if (m_hOwner != NULL) - pev->owner = m_hOwner->edict(); - - CBaseMonster ::Killed(pevAttacker, GIB_ALWAYS); -} - -void CSqueakGrenade ::GibMonster(void) -{ - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "common/bodysplat.wav", 0.75, ATTN_NORM, 0, 200); -} - -void CSqueakGrenade::HuntThink(void) -{ - // ALERT( at_console, "think\n" ); - - if (!IsInWorld()) - { - SetTouch(NULL); - UTIL_Remove(this); - return; - } - - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - // explode when ready - if (gpGlobals->time >= m_flDie) - { - g_vecAttackDir = pev->velocity.Normalize(); - pev->health = -1; - Killed(pev, 0); - return; - } - - // float - if (pev->waterlevel != 0) - { - if (pev->movetype == MOVETYPE_BOUNCE) - { - pev->movetype = MOVETYPE_FLY; - } - pev->velocity = pev->velocity * 0.9; - pev->velocity.z += 8.0; - } - else if (pev->movetype = MOVETYPE_FLY) - { - pev->movetype = MOVETYPE_BOUNCE; - } - - // return if not time to hunt - if (m_flNextHunt > gpGlobals->time) - return; - - m_flNextHunt = gpGlobals->time + 2.0; - - CBaseEntity *pOther = NULL; - Vector vecDir; - TraceResult tr; - - Vector vecFlat = pev->velocity; - vecFlat.z = 0; - vecFlat = vecFlat.Normalize(); - - UTIL_MakeVectors(pev->angles); - - if (m_hEnemy == NULL || !m_hEnemy->IsAlive()) - { - // find target, bounce a bit towards it. - Look(512); - m_hEnemy = BestVisibleEnemy(); - } - - // squeek if it's about time blow up - if ((m_flDie - gpGlobals->time <= 0.5) && (m_flDie - gpGlobals->time >= 0.3)) - { - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_die1.wav", 1, ATTN_NORM, 0, 100 + RANDOM_LONG(0, 0x3F)); - CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, 256, 0.25); - } - - // higher pitch as squeeker gets closer to detonation time - float flpitch = 155.0 - 60.0 * ((m_flDie - gpGlobals->time) / SQUEEK_DETONATE_DELAY); - if (flpitch < 80) - flpitch = 80; - - if (m_hEnemy != NULL) - { - if (FVisible(m_hEnemy)) - { - vecDir = m_hEnemy->EyePosition() - pev->origin; - m_vecTarget = vecDir.Normalize(); - } - - float flVel = pev->velocity.Length(); - float flAdj = 50.0 / (flVel + 10.0); - - if (flAdj > 1.2) - flAdj = 1.2; - - // ALERT( at_console, "think : enemy\n"); - - // ALERT( at_console, "%.0f %.2f %.2f %.2f\n", flVel, m_vecTarget.x, m_vecTarget.y, m_vecTarget.z ); - - pev->velocity = pev->velocity * flAdj + m_vecTarget * 300; - } - - if (pev->flags & FL_ONGROUND) - { - pev->avelocity = Vector(0, 0, 0); - } - else - { - if (pev->avelocity == Vector(0, 0, 0)) - { - pev->avelocity.x = RANDOM_FLOAT(-100, 100); - pev->avelocity.z = RANDOM_FLOAT(-100, 100); - } - } - - if ((pev->origin - m_posPrev).Length() < 1.0) - { - pev->velocity.x = RANDOM_FLOAT(-100, 100); - pev->velocity.y = RANDOM_FLOAT(-100, 100); - } - m_posPrev = pev->origin; - - pev->angles = UTIL_VecToAngles(pev->velocity); - pev->angles.z = 0; - pev->angles.x = 0; -} - -void CSqueakGrenade::SuperBounceTouch(CBaseEntity *pOther) -{ - float flpitch; - - TraceResult tr = UTIL_GetGlobalTrace(); - - // don't hit the guy that launched this grenade - if (pev->owner && pOther->edict() == pev->owner) - return; - - // at least until we've bounced once - pev->owner = NULL; - - pev->angles.x = 0; - pev->angles.z = 0; - - // avoid bouncing too much - if (m_flNextHit > gpGlobals->time) - return; - - // higher pitch as squeeker gets closer to detonation time - flpitch = 155.0 - 60.0 * ((m_flDie - gpGlobals->time) / SQUEEK_DETONATE_DELAY); - - if (pOther->pev->takedamage && m_flNextAttack < gpGlobals->time) - { - // attack! - - // make sure it's me who has touched them - if (tr.pHit == pOther->edict()) - { - // and it's not another squeakgrenade - if (tr.pHit->v.modelindex != pev->modelindex) - { - // ALERT( at_console, "hit enemy\n"); - ClearMultiDamage(); - pOther->TraceAttack(pev, gSkillData.snarkDmgBite, gpGlobals->v_forward, &tr, DMG_SLASH); - if (m_hOwner != NULL) - ApplyMultiDamage(pev, m_hOwner->pev); - else - ApplyMultiDamage(pev, pev); - - pev->dmg += gSkillData.snarkDmgPop; // add more explosion damage - // m_flDie += 2.0; // add more life - - // make bite sound - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "squeek/sqk_deploy1.wav", 1.0, ATTN_NORM, 0, (int)flpitch); - m_flNextAttack = gpGlobals->time + 0.5; - } - } - else - { - // ALERT( at_console, "been hit\n"); - } - } - - m_flNextHit = gpGlobals->time + 0.1; - m_flNextHunt = gpGlobals->time; - - if (g_pGameRules->IsMultiplayer()) - { - // in multiplayer, we limit how often snarks can make their bounce sounds to prevent overflows. - if (gpGlobals->time < m_flNextBounceSoundTime) - { - // too soon! - return; - } - } - - if (!(pev->flags & FL_ONGROUND)) - { - // play bounce sound - float flRndSound = RANDOM_FLOAT(0, 1); - - if (flRndSound <= 0.33) - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt1.wav", 1, ATTN_NORM, 0, (int)flpitch); - else if (flRndSound <= 0.66) - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt2.wav", 1, ATTN_NORM, 0, (int)flpitch); - else - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt3.wav", 1, ATTN_NORM, 0, (int)flpitch); - CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, 256, 0.25); - } - else - { - // skittering sound - CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, 100, 0.1); - } - - m_flNextBounceSoundTime = gpGlobals->time + 0.5; // half second. -} - -class CSqueak : public CBasePlayerWeapon -{ -public: - void Spawn(void); - void Precache(void); - int iItemSlot(void) { return 5; } - int GetItemInfo(ItemInfo *p); - - void PrimaryAttack(void); - void SecondaryAttack(void); - BOOL Deploy(void); - void Holster(int skiplocal = 0); - void WeaponIdle(void); - int m_fJustThrown; -}; -LINK_ENTITY_TO_CLASS(weapon_snark, CSqueak); - -void CSqueak::Spawn() -{ - Precache(); - m_iId = WEAPON_SNARK; - SET_MODEL(ENT(pev), "models/w_sqknest.mdl"); - - FallInit(); //get ready to fall down. - - m_iDefaultAmmo = SNARK_DEFAULT_GIVE; - - pev->sequence = 1; - pev->animtime = gpGlobals->time; - pev->framerate = 1.0; -} - -void CSqueak::Precache(void) -{ - PRECACHE_MODEL("models/w_sqknest.mdl"); - PRECACHE_MODEL("models/v_squeak.mdl"); - PRECACHE_MODEL("models/p_squeak.mdl"); - PRECACHE_SOUND("squeek/sqk_hunt2.wav"); - PRECACHE_SOUND("squeek/sqk_hunt3.wav"); - UTIL_PrecacheOther("monster_snark"); -} - -int CSqueak::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "Snarks"; - p->iMaxAmmo1 = SNARK_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = WEAPON_NOCLIP; - p->iSlot = 4; - p->iPosition = 3; - p->iId = m_iId = WEAPON_SNARK; - p->iWeight = SNARK_WEIGHT; - p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE; - - return 1; -} - -BOOL CSqueak::Deploy() -{ - // play hunt sound - float flRndSound = RANDOM_FLOAT(0, 1); - - if (flRndSound <= 0.5) - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt2.wav", 1, ATTN_NORM, 0, 100); - else - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt3.wav", 1, ATTN_NORM, 0, 100); - - m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; - - return DefaultDeploy("models/v_squeak.mdl", "models/p_squeak.mdl", SQUEAK_UP, "squeak"); -} - -void CSqueak::Holster(int skiplocal /* = 0 */) -{ - m_pPlayer->m_flNextAttack = gpGlobals->time + 0.5; - - if (!m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - m_pPlayer->pev->weapons &= ~(1 << WEAPON_SNARK); - SetThink(DestroyItem); - pev->nextthink = gpGlobals->time + 0.1; - return; - } - - SendWeaponAnim(SQUEAK_DOWN); - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM); -} - -void CSqueak::PrimaryAttack() -{ - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - UTIL_MakeVectors(m_pPlayer->pev->v_angle); - TraceResult tr; - Vector trace_origin; - - // HACK HACK: Ugly hacks to handle change in origin based on new physics code for players - // Move origin up if crouched and start trace a bit outside of body ( 20 units instead of 16 ) - trace_origin = m_pPlayer->pev->origin; - if (m_pPlayer->pev->flags & FL_DUCKING) - { - trace_origin = trace_origin - (VEC_HULL_MIN - VEC_DUCK_HULL_MIN); - } - - // find place to toss monster - UTIL_TraceLine(trace_origin + gpGlobals->v_forward * 20, trace_origin + gpGlobals->v_forward * 64, dont_ignore_monsters, NULL, &tr); - - if (tr.fAllSolid == 0 && tr.fStartSolid == 0 && tr.flFraction > 0.25) - { - SendWeaponAnim(SQUEAK_THROW); - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - CBaseEntity *pSqueak = CBaseEntity::Create("monster_snark", tr.vecEndPos, m_pPlayer->pev->v_angle, m_pPlayer->edict()); - - pSqueak->pev->velocity = gpGlobals->v_forward * 200 + m_pPlayer->pev->velocity; - - // play hunt sound - float flRndSound = RANDOM_FLOAT(0, 1); - - if (flRndSound <= 0.5) - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt2.wav", 1, ATTN_NORM, 0, 105); - else - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt3.wav", 1, ATTN_NORM, 0, 105); - - m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; - - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; - - m_fJustThrown = 1; - - m_flNextPrimaryAttack = gpGlobals->time + 0.3; - m_flTimeWeaponIdle = gpGlobals->time + 1.0; - } - } -} - -void CSqueak::SecondaryAttack(void) -{ -} - -void CSqueak::WeaponIdle(void) -{ - if (m_flTimeWeaponIdle > gpGlobals->time) - return; - - if (m_fJustThrown) - { - m_fJustThrown = 0; - - if (!m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()]) - { - RetireWeapon(); - return; - } - - SendWeaponAnim(SQUEAK_UP); - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); - return; - } - - int iAnim; - float flRand = RANDOM_FLOAT(0, 1); - if (flRand <= 0.75) - { - iAnim = SQUEAK_IDLE1; - m_flTimeWeaponIdle = gpGlobals->time + 30.0 / 16 * (2); - } - else if (flRand <= 0.875) - { - iAnim = SQUEAK_FIDGETFIT; - m_flTimeWeaponIdle = gpGlobals->time + 70.0 / 16.0; - } - else - { - iAnim = SQUEAK_FIDGETNIP; - m_flTimeWeaponIdle = gpGlobals->time + 80.0 / 16.0; - } - SendWeaponAnim(iAnim); -} - -#endif \ No newline at end of file diff --git a/dlls/Half-life/talkmonster.cpp b/dlls/Half-life/talkmonster.cpp deleted file mode 100644 index 7071418c..00000000 --- a/dlls/Half-life/talkmonster.cpp +++ /dev/null @@ -1,1419 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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 "schedule.h" -#include "talkmonster.h" -#include "defaultai.h" -#include "scripted.h" -#include "soundent.h" -#include "animation.h" - -//========================================================= -// Talking monster base class -// Used for scientists and barneys -//========================================================= -float CTalkMonster::g_talkWaitTime = 0; // time delay until it's ok to speak: used so that two NPCs don't talk at once - -// NOTE: m_voicePitch & m_szGrp should be fixed up by precache each save/restore - -TYPEDESCRIPTION CTalkMonster::m_SaveData[] = - { - DEFINE_FIELD(CTalkMonster, m_bitsSaid, FIELD_INTEGER), - DEFINE_FIELD(CTalkMonster, m_nSpeak, FIELD_INTEGER), - - // Recalc'ed in Precache() - // DEFINE_FIELD( CTalkMonster, m_voicePitch, FIELD_INTEGER ), - // DEFINE_FIELD( CTalkMonster, m_szGrp, FIELD_??? ), - DEFINE_FIELD(CTalkMonster, m_useTime, FIELD_TIME), - DEFINE_FIELD(CTalkMonster, m_iszUse, FIELD_STRING), - DEFINE_FIELD(CTalkMonster, m_iszUnUse, FIELD_STRING), - DEFINE_FIELD(CTalkMonster, m_flLastSaidSmelled, FIELD_TIME), - DEFINE_FIELD(CTalkMonster, m_flStopTalkTime, FIELD_TIME), - DEFINE_FIELD(CTalkMonster, m_hTalkTarget, FIELD_EHANDLE), -}; - -IMPLEMENT_SAVERESTORE(CTalkMonster, CBaseMonster); - -// array of friend names -char *CTalkMonster::m_szFriends[TLK_CFRIENDS] = - { - "monster_barney", - "monster_scientist", - "monster_sitting_scientist", -}; - -//========================================================= -// AI Schedules Specific to talking monsters -//========================================================= - -Task_t tlIdleResponse[] = - { - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, // Stop and listen - {TASK_WAIT, (float)0.5}, // Wait until sure it's me they are talking to - {TASK_TLK_EYECONTACT, (float)0}, // Wait until speaker is done - {TASK_TLK_RESPOND, (float)0}, // Wait and then say my response - {TASK_TLK_IDEALYAW, (float)0}, // look at who I'm talking to - {TASK_FACE_IDEAL, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_SIGNAL3}, - {TASK_TLK_EYECONTACT, (float)0}, // Wait until speaker is done -}; - -Schedule_t slIdleResponse[] = - { - {tlIdleResponse, - ARRAYSIZE(tlIdleResponse), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "Idle Response" - - }, -}; - -Task_t tlIdleSpeak[] = - { - {TASK_TLK_SPEAK, (float)0}, // question or remark - {TASK_TLK_IDEALYAW, (float)0}, // look at who I'm talking to - {TASK_FACE_IDEAL, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_SIGNAL3}, - {TASK_TLK_EYECONTACT, (float)0}, - {TASK_WAIT_RANDOM, (float)0.5}, -}; - -Schedule_t slIdleSpeak[] = - { - {tlIdleSpeak, - ARRAYSIZE(tlIdleSpeak), - bits_COND_NEW_ENEMY | - bits_COND_CLIENT_PUSH | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "Idle Speak"}, -}; - -Task_t tlIdleSpeakWait[] = - { - {TASK_SET_ACTIVITY, (float)ACT_SIGNAL3}, // Stop and talk - {TASK_TLK_SPEAK, (float)0}, // question or remark - {TASK_TLK_EYECONTACT, (float)0}, // - {TASK_WAIT, (float)2}, // wait - used when sci is in 'use' mode to keep head turned -}; - -Schedule_t slIdleSpeakWait[] = - { - {tlIdleSpeakWait, - ARRAYSIZE(tlIdleSpeakWait), - bits_COND_NEW_ENEMY | - bits_COND_CLIENT_PUSH | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "Idle Speak Wait"}, -}; - -Task_t tlIdleHello[] = - { - {TASK_SET_ACTIVITY, (float)ACT_SIGNAL3}, // Stop and talk - {TASK_TLK_HELLO, (float)0}, // Try to say hello to player - {TASK_TLK_EYECONTACT, (float)0}, - {TASK_WAIT, (float)0.5}, // wait a bit - {TASK_TLK_HELLO, (float)0}, // Try to say hello to player - {TASK_TLK_EYECONTACT, (float)0}, - {TASK_WAIT, (float)0.5}, // wait a bit - {TASK_TLK_HELLO, (float)0}, // Try to say hello to player - {TASK_TLK_EYECONTACT, (float)0}, - {TASK_WAIT, (float)0.5}, // wait a bit - {TASK_TLK_HELLO, (float)0}, // Try to say hello to player - {TASK_TLK_EYECONTACT, (float)0}, - {TASK_WAIT, (float)0.5}, // wait a bit - -}; - -Schedule_t slIdleHello[] = - { - {tlIdleHello, - ARRAYSIZE(tlIdleHello), - bits_COND_NEW_ENEMY | - bits_COND_CLIENT_PUSH | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND | - bits_COND_PROVOKED, - - bits_SOUND_COMBAT, - "Idle Hello"}, -}; - -Task_t tlIdleStopShooting[] = - { - {TASK_TLK_STOPSHOOTING, (float)0}, // tell player to stop shooting friend - // { TASK_TLK_EYECONTACT, (float)0 },// look at the player -}; - -Schedule_t slIdleStopShooting[] = - { - {tlIdleStopShooting, - ARRAYSIZE(tlIdleStopShooting), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND, - 0, - "Idle Stop Shooting"}, -}; - -Task_t tlMoveAway[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_MOVE_AWAY_FAIL}, - {TASK_STORE_LASTPOSITION, (float)0}, - {TASK_MOVE_AWAY_PATH, (float)100}, - {TASK_WALK_PATH_FOR_UNITS, (float)100}, - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_PLAYER, (float)0.5}, -}; - -Schedule_t slMoveAway[] = - { - {tlMoveAway, - ARRAYSIZE(tlMoveAway), - 0, - 0, - "MoveAway"}, -}; - -Task_t tlMoveAwayFail[] = - { - {TASK_STOP_MOVING, (float)0}, - {TASK_FACE_PLAYER, (float)0.5}, -}; - -Schedule_t slMoveAwayFail[] = - { - {tlMoveAwayFail, - ARRAYSIZE(tlMoveAwayFail), - 0, - 0, - "MoveAwayFail"}, -}; - -Task_t tlMoveAwayFollow[] = - { - {TASK_SET_FAIL_SCHEDULE, (float)SCHED_TARGET_FACE}, - {TASK_STORE_LASTPOSITION, (float)0}, - {TASK_MOVE_AWAY_PATH, (float)100}, - {TASK_WALK_PATH_FOR_UNITS, (float)100}, - {TASK_STOP_MOVING, (float)0}, - {TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE}, -}; - -Schedule_t slMoveAwayFollow[] = - { - {tlMoveAwayFollow, - ARRAYSIZE(tlMoveAwayFollow), - 0, - 0, - "MoveAwayFollow"}, -}; - -Task_t tlTlkIdleWatchClient[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_TLK_LOOK_AT_CLIENT, (float)6}, -}; - -Task_t tlTlkIdleWatchClientStare[] = - { - {TASK_STOP_MOVING, 0}, - {TASK_SET_ACTIVITY, (float)ACT_IDLE}, - {TASK_TLK_CLIENT_STARE, (float)6}, - {TASK_TLK_STARE, (float)0}, - {TASK_TLK_IDEALYAW, (float)0}, // look at who I'm talking to - {TASK_FACE_IDEAL, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_SIGNAL3}, - {TASK_TLK_EYECONTACT, (float)0}, -}; - -Schedule_t slTlkIdleWatchClient[] = - { - {tlTlkIdleWatchClient, - ARRAYSIZE(tlTlkIdleWatchClient), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND | - bits_COND_SMELL | - bits_COND_CLIENT_PUSH | - bits_COND_CLIENT_UNSEEN | - bits_COND_PROVOKED, - - bits_SOUND_COMBAT | // sound flags - change these, and you'll break the talking code. - //bits_SOUND_PLAYER | - //bits_SOUND_WORLD | - - bits_SOUND_DANGER | - bits_SOUND_MEAT | // scents - bits_SOUND_CARCASS | - bits_SOUND_GARBAGE, - "TlkIdleWatchClient"}, - - {tlTlkIdleWatchClientStare, - ARRAYSIZE(tlTlkIdleWatchClientStare), - bits_COND_NEW_ENEMY | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE | - bits_COND_HEAR_SOUND | - bits_COND_SMELL | - bits_COND_CLIENT_PUSH | - bits_COND_CLIENT_UNSEEN | - bits_COND_PROVOKED, - - bits_SOUND_COMBAT | // sound flags - change these, and you'll break the talking code. - //bits_SOUND_PLAYER | - //bits_SOUND_WORLD | - - bits_SOUND_DANGER | - bits_SOUND_MEAT | // scents - bits_SOUND_CARCASS | - bits_SOUND_GARBAGE, - "TlkIdleWatchClientStare"}, -}; - -Task_t tlTlkIdleEyecontact[] = - { - {TASK_TLK_IDEALYAW, (float)0}, // look at who I'm talking to - {TASK_FACE_IDEAL, (float)0}, - {TASK_SET_ACTIVITY, (float)ACT_SIGNAL3}, - {TASK_TLK_EYECONTACT, (float)0}, // Wait until speaker is done -}; - -Schedule_t slTlkIdleEyecontact[] = - { - {tlTlkIdleEyecontact, - ARRAYSIZE(tlTlkIdleEyecontact), - bits_COND_NEW_ENEMY | - bits_COND_CLIENT_PUSH | - bits_COND_LIGHT_DAMAGE | - bits_COND_HEAVY_DAMAGE, - 0, - "TlkIdleEyecontact"}, -}; - -DEFINE_CUSTOM_SCHEDULES(CTalkMonster){ - slIdleResponse, - slIdleSpeak, - slIdleHello, - slIdleSpeakWait, - slIdleStopShooting, - slMoveAway, - slMoveAwayFollow, - slMoveAwayFail, - slTlkIdleWatchClient, - &slTlkIdleWatchClient[1], - slTlkIdleEyecontact, -}; - -IMPLEMENT_CUSTOM_SCHEDULES(CTalkMonster, CBaseMonster); - -void CTalkMonster ::SetActivity(Activity newActivity) -{ - if (newActivity == ACT_IDLE && IsTalking()) - newActivity = ACT_SIGNAL3; - - if (newActivity == ACT_SIGNAL3 && (LookupActivity(ACT_SIGNAL3) == ACTIVITY_NOT_AVAILABLE)) - newActivity = ACT_IDLE; - - CBaseMonster::SetActivity(newActivity); -} - -void CTalkMonster ::StartTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_TLK_SPEAK: - // ask question or make statement - FIdleSpeak(); - TaskComplete(); - break; - - case TASK_TLK_RESPOND: - // respond to question - IdleRespond(); - TaskComplete(); - break; - - case TASK_TLK_HELLO: - // greet player - FIdleHello(); - TaskComplete(); - break; - - case TASK_TLK_STARE: - // let the player know I know he's staring at me. - FIdleStare(); - TaskComplete(); - break; - - case TASK_FACE_PLAYER: - case TASK_TLK_LOOK_AT_CLIENT: - case TASK_TLK_CLIENT_STARE: - // track head to the client for a while. - m_flWaitFinished = gpGlobals->time + pTask->flData; - break; - - case TASK_TLK_EYECONTACT: - break; - - case TASK_TLK_IDEALYAW: - if (m_hTalkTarget != NULL) - { - pev->yaw_speed = 60; - float yaw = VecToYaw(m_hTalkTarget->pev->origin - pev->origin) - pev->angles.y; - - if (yaw > 180) - yaw -= 360; - if (yaw < -180) - yaw += 360; - - if (yaw < 0) - { - pev->ideal_yaw = min(yaw + 45, 0) + pev->angles.y; - } - else - { - pev->ideal_yaw = max(yaw - 45, 0) + pev->angles.y; - } - } - TaskComplete(); - break; - - case TASK_TLK_HEADRESET: - // reset head position after looking at something - m_hTalkTarget = NULL; - TaskComplete(); - break; - - case TASK_TLK_STOPSHOOTING: - // tell player to stop shooting - PlaySentence(m_szGrp[TLK_NOSHOOT], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_NORM); - TaskComplete(); - break; - - case TASK_CANT_FOLLOW: - StopFollowing(FALSE); - PlaySentence(m_szGrp[TLK_STOP], RANDOM_FLOAT(2, 2.5), VOL_NORM, ATTN_NORM); - TaskComplete(); - break; - - case TASK_WALK_PATH_FOR_UNITS: - m_movementActivity = ACT_WALK; - break; - - case TASK_MOVE_AWAY_PATH: - { - Vector dir = pev->angles; - dir.y = pev->ideal_yaw + 180; - Vector move; - - UTIL_MakeVectorsPrivate(dir, move, NULL, NULL); - dir = pev->origin + move * pTask->flData; - if (MoveToLocation(ACT_WALK, 2, dir)) - { - TaskComplete(); - } - else if (FindCover(pev->origin, pev->view_ofs, 0, CoverRadius())) - { - // then try for plain ole cover - m_flMoveWaitFinished = gpGlobals->time + 2; - TaskComplete(); - } - else - { - // nowhere to go? - TaskFail(); - } - } - break; - - case TASK_PLAY_SCRIPT: - m_hTalkTarget = NULL; - CBaseMonster::StartTask(pTask); - break; - - default: - CBaseMonster::StartTask(pTask); - } -} - -void CTalkMonster ::RunTask(Task_t *pTask) -{ - switch (pTask->iTask) - { - case TASK_TLK_CLIENT_STARE: - case TASK_TLK_LOOK_AT_CLIENT: - - edict_t *pPlayer; - - // track head to the client for a while. - if (m_MonsterState == MONSTERSTATE_IDLE && - !IsMoving() && - !IsTalking()) - { - // Get edict for one player - pPlayer = g_engfuncs.pfnPEntityOfEntIndex(1); - - if (pPlayer) - { - IdleHeadTurn(pPlayer->v.origin); - } - } - else - { - // started moving or talking - TaskFail(); - return; - } - - if (pTask->iTask == TASK_TLK_CLIENT_STARE) - { - // fail out if the player looks away or moves away. - if ((pPlayer->v.origin - pev->origin).Length2D() > TLK_STARE_DIST) - { - // player moved away. - TaskFail(); - } - - UTIL_MakeVectors(pPlayer->v.angles); - if (UTIL_DotPoints(pPlayer->v.origin, pev->origin, gpGlobals->v_forward) < m_flFieldOfView) - { - // player looked away - TaskFail(); - } - } - - if (gpGlobals->time > m_flWaitFinished) - { - TaskComplete(); - } - break; - - case TASK_FACE_PLAYER: - { - // Get edict for one player - edict_t *pPlayer = g_engfuncs.pfnPEntityOfEntIndex(1); - - if (pPlayer) - { - MakeIdealYaw(pPlayer->v.origin); - ChangeYaw(pev->yaw_speed); - IdleHeadTurn(pPlayer->v.origin); - if (gpGlobals->time > m_flWaitFinished && FlYawDiff() < 10) - { - TaskComplete(); - } - } - else - { - TaskFail(); - } - } - break; - - case TASK_TLK_EYECONTACT: - if (!IsMoving() && IsTalking() && m_hTalkTarget != NULL) - { - // ALERT( at_console, "waiting %f\n", m_flStopTalkTime - gpGlobals->time ); - IdleHeadTurn(m_hTalkTarget->pev->origin); - } - else - { - TaskComplete(); - } - break; - - case TASK_WALK_PATH_FOR_UNITS: - { - float distance; - - distance = (m_vecLastPosition - pev->origin).Length2D(); - - // Walk path until far enough away - if (distance > pTask->flData || MovementIsComplete()) - { - TaskComplete(); - RouteClear(); // Stop moving - } - } - break; - case TASK_WAIT_FOR_MOVEMENT: - if (IsTalking() && m_hTalkTarget != NULL) - { - // ALERT(at_console, "walking, talking\n"); - IdleHeadTurn(m_hTalkTarget->pev->origin); - } - else - { - IdleHeadTurn(pev->origin); - // override so that during walk, a scientist may talk and greet player - FIdleHello(); - if (RANDOM_LONG(0, m_nSpeak * 20) == 0) - { - FIdleSpeak(); - } - } - - CBaseMonster::RunTask(pTask); - if (TaskIsComplete()) - IdleHeadTurn(pev->origin); - break; - - default: - if (IsTalking() && m_hTalkTarget != NULL) - { - IdleHeadTurn(m_hTalkTarget->pev->origin); - } - else - { - SetBoneController(0, 0); - } - CBaseMonster::RunTask(pTask); - } -} - -void CTalkMonster ::Killed(entvars_t *pevAttacker, int iGib) -{ - // If a client killed me (unless I was already Barnacle'd), make everyone else mad/afraid of him - if ((pevAttacker->flags & FL_CLIENT) && m_MonsterState != MONSTERSTATE_PRONE) - { - AlertFriends(); - LimitFollowers(CBaseEntity::Instance(pevAttacker), 0); - } - - m_hTargetEnt = NULL; - // Don't finish that sentence - StopTalking(); - SetUse(NULL); - CBaseMonster::Killed(pevAttacker, iGib); -} - -CBaseEntity *CTalkMonster::EnumFriends(CBaseEntity *pPrevious, int listNumber, BOOL bTrace) -{ - CBaseEntity *pFriend = pPrevious; - char *pszFriend; - TraceResult tr; - Vector vecCheck; - - pszFriend = m_szFriends[FriendNumber(listNumber)]; - while (pFriend = UTIL_FindEntityByClassname(pFriend, pszFriend)) - { - if (pFriend == this || !pFriend->IsAlive()) - // don't talk to self or dead people - continue; - if (bTrace) - { - vecCheck = pFriend->pev->origin; - vecCheck.z = pFriend->pev->absmax.z; - - UTIL_TraceLine(pev->origin, vecCheck, ignore_monsters, ENT(pev), &tr); - } - else - tr.flFraction = 1.0; - - if (tr.flFraction == 1.0) - { - return pFriend; - } - } - - return NULL; -} - -void CTalkMonster::AlertFriends(void) -{ - CBaseEntity *pFriend = NULL; - int i; - - // for each friend in this bsp... - for (i = 0; i < TLK_CFRIENDS; i++) - { - while (pFriend = EnumFriends(pFriend, i, TRUE)) - { - CBaseMonster *pMonster = pFriend->MyMonsterPointer(); - if (pMonster->IsAlive()) - { - // don't provoke a friend that's playing a death animation. They're a goner - pMonster->m_afMemory |= bits_MEMORY_PROVOKED; - } - } - } -} - -void CTalkMonster::ShutUpFriends(void) -{ - CBaseEntity *pFriend = NULL; - int i; - - // for each friend in this bsp... - for (i = 0; i < TLK_CFRIENDS; i++) - { - while (pFriend = EnumFriends(pFriend, i, TRUE)) - { - CBaseMonster *pMonster = pFriend->MyMonsterPointer(); - if (pMonster) - { - pMonster->SentenceStop(); - } - } - } -} - -// UNDONE: Keep a follow time in each follower, make a list of followers in this function and do LRU -// UNDONE: Check this in Restore to keep restored monsters from joining a full list of followers -void CTalkMonster::LimitFollowers(CBaseEntity *pPlayer, int maxFollowers) -{ - CBaseEntity *pFriend = NULL; - int i, count; - - count = 0; - // for each friend in this bsp... - for (i = 0; i < TLK_CFRIENDS; i++) - { - while (pFriend = EnumFriends(pFriend, i, FALSE)) - { - CBaseMonster *pMonster = pFriend->MyMonsterPointer(); - if (pMonster) - { - if (pMonster->m_hTargetEnt == pPlayer) - { - count++; - if (count > maxFollowers) - pMonster->StopFollowing(TRUE); - } - } - } - } -} - -float CTalkMonster::TargetDistance(void) -{ - // If we lose the player, or he dies, return a really large distance - if (m_hTargetEnt == NULL || !m_hTargetEnt->IsAlive()) - return 1e6; - - return (m_hTargetEnt->pev->origin - pev->origin).Length(); -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CTalkMonster ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case SCRIPT_EVENT_SENTENCE_RND1: // Play a named sentence group 25% of the time - if (RANDOM_LONG(0, 99) < 75) - break; - // fall through... - case SCRIPT_EVENT_SENTENCE: // Play a named sentence group - ShutUpFriends(); - PlaySentence(pEvent->options, RANDOM_FLOAT(2.8, 3.4), VOL_NORM, ATTN_IDLE); - //ALERT(at_console, "script event speak\n"); - break; - - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -// monsters derived from ctalkmonster should call this in precache() - -void CTalkMonster ::TalkInit(void) -{ - // every new talking monster must reset this global, otherwise - // when a level is loaded, nobody will talk (time is reset to 0) - - CTalkMonster::g_talkWaitTime = 0; - - m_voicePitch = 100; -} -//========================================================= -// FindNearestFriend -// Scan for nearest, visible friend. If fPlayer is true, look for -// nearest player -//========================================================= -CBaseEntity *CTalkMonster ::FindNearestFriend(BOOL fPlayer) -{ - CBaseEntity *pFriend = NULL; - CBaseEntity *pNearest = NULL; - float range = 10000000.0; - TraceResult tr; - Vector vecStart = pev->origin; - Vector vecCheck; - int i; - char *pszFriend; - int cfriends; - - vecStart.z = pev->absmax.z; - - if (fPlayer) - cfriends = 1; - else - cfriends = TLK_CFRIENDS; - - // for each type of friend... - - for (i = cfriends - 1; i > -1; i--) - { - if (fPlayer) - pszFriend = "player"; - else - pszFriend = m_szFriends[FriendNumber(i)]; - - if (!pszFriend) - continue; - - // for each friend in this bsp... - while (pFriend = UTIL_FindEntityByClassname(pFriend, pszFriend)) - { - if (pFriend == this || !pFriend->IsAlive()) - // don't talk to self or dead people - continue; - - CBaseMonster *pMonster = pFriend->MyMonsterPointer(); - - // If not a monster for some reason, or in a script, or prone - if (!pMonster || pMonster->m_MonsterState == MONSTERSTATE_SCRIPT || pMonster->m_MonsterState == MONSTERSTATE_PRONE) - continue; - - vecCheck = pFriend->pev->origin; - vecCheck.z = pFriend->pev->absmax.z; - - // if closer than previous friend, and in range, see if he's visible - - if (range > (vecStart - vecCheck).Length()) - { - UTIL_TraceLine(vecStart, vecCheck, ignore_monsters, ENT(pev), &tr); - - if (tr.flFraction == 1.0) - { - // visible and in range, this is the new nearest scientist - if ((vecStart - vecCheck).Length() < TALKRANGE_MIN) - { - pNearest = pFriend; - range = (vecStart - vecCheck).Length(); - } - } - } - } - } - return pNearest; -} - -int CTalkMonster ::GetVoicePitch(void) -{ - return m_voicePitch + RANDOM_LONG(0, 3); -} - -void CTalkMonster ::Touch(CBaseEntity *pOther) -{ - // Did the player touch me? - if (pOther->IsPlayer()) - { - // Ignore if pissed at player - if (m_afMemory & bits_MEMORY_PROVOKED) - return; - - // Stay put during speech - if (IsTalking()) - return; - - // Heuristic for determining if the player is pushing me away - float speed = fabs(pOther->pev->velocity.x) + fabs(pOther->pev->velocity.y); - if (speed > 50) - { - SetConditions(bits_COND_CLIENT_PUSH); - MakeIdealYaw(pOther->pev->origin); - } - } -} - -//========================================================= -// IdleRespond -// Respond to a previous question -//========================================================= -void CTalkMonster ::IdleRespond(void) -{ - int pitch = GetVoicePitch(); - - // play response - PlaySentence(m_szGrp[TLK_ANSWER], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE); -} - -int CTalkMonster ::FOkToSpeak(void) -{ - // if in the grip of a barnacle, don't speak - if (m_MonsterState == MONSTERSTATE_PRONE || m_IdealMonsterState == MONSTERSTATE_PRONE) - { - return FALSE; - } - - // if not alive, certainly don't speak - if (pev->deadflag != DEAD_NO) - { - return FALSE; - } - - // if someone else is talking, don't speak - if (gpGlobals->time <= CTalkMonster::g_talkWaitTime) - return FALSE; - - if (pev->spawnflags & SF_MONSTER_GAG) - return FALSE; - - if (m_MonsterState == MONSTERSTATE_PRONE) - return FALSE; - - // if player is not in pvs, don't speak - if (!IsAlive() || FNullEnt(FIND_CLIENT_IN_PVS(edict()))) - return FALSE; - - // don't talk if you're in combat - if (m_hEnemy != NULL && FVisible(m_hEnemy)) - return FALSE; - - return TRUE; -} - -int CTalkMonster::CanPlaySentence(BOOL fDisregardState) -{ - if (fDisregardState) - return CBaseMonster::CanPlaySentence(fDisregardState); - return FOkToSpeak(); -} - -//========================================================= -// FIdleStare -//========================================================= -int CTalkMonster ::FIdleStare(void) -{ - if (!FOkToSpeak()) - return FALSE; - - PlaySentence(m_szGrp[TLK_STARE], RANDOM_FLOAT(5, 7.5), VOL_NORM, ATTN_IDLE); - - m_hTalkTarget = FindNearestFriend(TRUE); - return TRUE; -} - -//========================================================= -// IdleHello -// Try to greet player first time he's seen -//========================================================= -int CTalkMonster ::FIdleHello(void) -{ - if (!FOkToSpeak()) - return FALSE; - - // if this is first time scientist has seen player, greet him - if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer)) - { - // get a player - CBaseEntity *pPlayer = FindNearestFriend(TRUE); - - if (pPlayer) - { - if (FInViewCone(pPlayer) && FVisible(pPlayer)) - { - m_hTalkTarget = pPlayer; - - if (FBitSet(pev->spawnflags, SF_MONSTER_PREDISASTER)) - PlaySentence(m_szGrp[TLK_PHELLO], RANDOM_FLOAT(3, 3.5), VOL_NORM, ATTN_IDLE); - else - PlaySentence(m_szGrp[TLK_HELLO], RANDOM_FLOAT(3, 3.5), VOL_NORM, ATTN_IDLE); - - SetBits(m_bitsSaid, bit_saidHelloPlayer); - - return TRUE; - } - } - } - return FALSE; -} - -// turn head towards supplied origin -void CTalkMonster ::IdleHeadTurn(Vector &vecFriend) -{ - // turn head in desired direction only if ent has a turnable head - if (m_afCapability & bits_CAP_TURN_HEAD) - { - float yaw = VecToYaw(vecFriend - pev->origin) - pev->angles.y; - - if (yaw > 180) - yaw -= 360; - if (yaw < -180) - yaw += 360; - - // turn towards vector - SetBoneController(0, yaw); - } -} - -//========================================================= -// FIdleSpeak -// ask question of nearby friend, or make statement -//========================================================= -int CTalkMonster ::FIdleSpeak(void) -{ - // try to start a conversation, or make statement - int pitch; - const char *szIdleGroup; - const char *szQuestionGroup; - float duration; - - if (!FOkToSpeak()) - return FALSE; - - // set idle groups based on pre/post disaster - if (FBitSet(pev->spawnflags, SF_MONSTER_PREDISASTER)) - { - szIdleGroup = m_szGrp[TLK_PIDLE]; - szQuestionGroup = m_szGrp[TLK_PQUESTION]; - // set global min delay for next conversation - duration = RANDOM_FLOAT(4.8, 5.2); - } - else - { - szIdleGroup = m_szGrp[TLK_IDLE]; - szQuestionGroup = m_szGrp[TLK_QUESTION]; - // set global min delay for next conversation - duration = RANDOM_FLOAT(2.8, 3.2); - } - - pitch = GetVoicePitch(); - - // player using this entity is alive and wounded? - CBaseEntity *pTarget = m_hTargetEnt; - - if (pTarget != NULL) - { - if (pTarget->IsPlayer()) - { - if (pTarget->IsAlive()) - { - m_hTalkTarget = m_hTargetEnt; - if (!FBitSet(m_bitsSaid, bit_saidDamageHeavy) && - (m_hTargetEnt->pev->health <= m_hTargetEnt->pev->max_health / 8)) - { - //EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, m_szGrp[TLK_PLHURT3], 1.0, ATTN_IDLE, 0, pitch); - PlaySentence(m_szGrp[TLK_PLHURT3], duration, VOL_NORM, ATTN_IDLE); - SetBits(m_bitsSaid, bit_saidDamageHeavy); - return TRUE; - } - else if (!FBitSet(m_bitsSaid, bit_saidDamageMedium) && - (m_hTargetEnt->pev->health <= m_hTargetEnt->pev->max_health / 4)) - { - //EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, m_szGrp[TLK_PLHURT2], 1.0, ATTN_IDLE, 0, pitch); - PlaySentence(m_szGrp[TLK_PLHURT2], duration, VOL_NORM, ATTN_IDLE); - SetBits(m_bitsSaid, bit_saidDamageMedium); - return TRUE; - } - else if (!FBitSet(m_bitsSaid, bit_saidDamageLight) && - (m_hTargetEnt->pev->health <= m_hTargetEnt->pev->max_health / 2)) - { - //EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, m_szGrp[TLK_PLHURT1], 1.0, ATTN_IDLE, 0, pitch); - PlaySentence(m_szGrp[TLK_PLHURT1], duration, VOL_NORM, ATTN_IDLE); - SetBits(m_bitsSaid, bit_saidDamageLight); - return TRUE; - } - } - else - { - //!!!KELLY - here's a cool spot to have the talkmonster talk about the dead player if we want. - // "Oh dear, Gordon Freeman is dead!" -Scientist - // "Damn, I can't do this without you." -Barney - } - } - } - - // if there is a friend nearby to speak to, play sentence, set friend's response time, return - CBaseEntity *pFriend = FindNearestFriend(FALSE); - - if (pFriend && !(pFriend->IsMoving()) && (RANDOM_LONG(0, 99) < 75)) - { - PlaySentence(szQuestionGroup, duration, VOL_NORM, ATTN_IDLE); - //SENTENCEG_PlayRndSz( ENT(pev), szQuestionGroup, 1.0, ATTN_IDLE, 0, pitch ); - - // force friend to answer - CTalkMonster *pTalkMonster = (CTalkMonster *)pFriend; - m_hTalkTarget = pFriend; - pTalkMonster->SetAnswerQuestion(this); // UNDONE: This is EVIL!!! - pTalkMonster->m_flStopTalkTime = m_flStopTalkTime; - - m_nSpeak++; - return TRUE; - } - - // otherwise, play an idle statement, try to face client when making a statement. - if (RANDOM_LONG(0, 1)) - { - //SENTENCEG_PlayRndSz( ENT(pev), szIdleGroup, 1.0, ATTN_IDLE, 0, pitch ); - CBaseEntity *pFriend = FindNearestFriend(TRUE); - - if (pFriend) - { - m_hTalkTarget = pFriend; - PlaySentence(szIdleGroup, duration, VOL_NORM, ATTN_IDLE); - m_nSpeak++; - return TRUE; - } - } - - // didn't speak - Talk(0); - CTalkMonster::g_talkWaitTime = 0; - return FALSE; -} - -void CTalkMonster::PlayScriptedSentence(const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener) -{ - if (!bConcurrent) - ShutUpFriends(); - - ClearConditions(bits_COND_CLIENT_PUSH); // Forget about moving! I've got something to say! - m_useTime = gpGlobals->time + duration; - PlaySentence(pszSentence, duration, volume, attenuation); - - m_hTalkTarget = pListener; -} - -void CTalkMonster::PlaySentence(const char *pszSentence, float duration, float volume, float attenuation) -{ - if (!pszSentence) - return; - - Talk(duration); - - CTalkMonster::g_talkWaitTime = gpGlobals->time + duration + 2.0; - if (pszSentence[0] == '!') - EMIT_SOUND_DYN(edict(), CHAN_VOICE, pszSentence, volume, attenuation, 0, GetVoicePitch()); - else - SENTENCEG_PlayRndSz(edict(), pszSentence, volume, attenuation, 0, GetVoicePitch()); - - // If you say anything, don't greet the player - you may have already spoken to them - SetBits(m_bitsSaid, bit_saidHelloPlayer); -} - -//========================================================= -// Talk - set a timer that tells us when the monster is done -// talking. -//========================================================= -void CTalkMonster ::Talk(float flDuration) -{ - if (flDuration <= 0) - { - // no duration :( - m_flStopTalkTime = gpGlobals->time + 3; - } - else - { - m_flStopTalkTime = gpGlobals->time + flDuration; - } -} - -// Prepare this talking monster to answer question -void CTalkMonster ::SetAnswerQuestion(CTalkMonster *pSpeaker) -{ - if (!m_pCine) - ChangeSchedule(slIdleResponse); - m_hTalkTarget = (CBaseMonster *)pSpeaker; -} - -int CTalkMonster ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (IsAlive()) - { - // if player damaged this entity, have other friends talk about it - if (pevAttacker && m_MonsterState != MONSTERSTATE_PRONE && FBitSet(pevAttacker->flags, FL_CLIENT)) - { - CBaseEntity *pFriend = FindNearestFriend(FALSE); - - if (pFriend && pFriend->IsAlive()) - { - // only if not dead or dying! - CTalkMonster *pTalkMonster = (CTalkMonster *)pFriend; - pTalkMonster->ChangeSchedule(slIdleStopShooting); - } - } - } - return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -Schedule_t *CTalkMonster ::GetScheduleOfType(int Type) -{ - switch (Type) - { - case SCHED_MOVE_AWAY: - return slMoveAway; - - case SCHED_MOVE_AWAY_FOLLOW: - return slMoveAwayFollow; - - case SCHED_MOVE_AWAY_FAIL: - return slMoveAwayFail; - - case SCHED_TARGET_FACE: - // speak during 'use' - if (RANDOM_LONG(0, 99) < 2) - //ALERT ( at_console, "target chase speak\n" ); - return slIdleSpeakWait; - else - return slIdleStand; - - case SCHED_IDLE_STAND: - { - // if never seen player, try to greet him - if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer)) - { - return slIdleHello; - } - - // sustained light wounds? - if (!FBitSet(m_bitsSaid, bit_saidWoundLight) && (pev->health <= (pev->max_health * 0.75))) - { - //SENTENCEG_PlayRndSz( ENT(pev), m_szGrp[TLK_WOUND], 1.0, ATTN_IDLE, 0, GetVoicePitch() ); - //CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(2.8, 3.2); - PlaySentence(m_szGrp[TLK_WOUND], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE); - SetBits(m_bitsSaid, bit_saidWoundLight); - return slIdleStand; - } - // sustained heavy wounds? - else if (!FBitSet(m_bitsSaid, bit_saidWoundHeavy) && (pev->health <= (pev->max_health * 0.5))) - { - //SENTENCEG_PlayRndSz( ENT(pev), m_szGrp[TLK_MORTAL], 1.0, ATTN_IDLE, 0, GetVoicePitch() ); - //CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(2.8, 3.2); - PlaySentence(m_szGrp[TLK_MORTAL], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE); - SetBits(m_bitsSaid, bit_saidWoundHeavy); - return slIdleStand; - } - - // talk about world - if (FOkToSpeak() && RANDOM_LONG(0, m_nSpeak * 2) == 0) - { - //ALERT ( at_console, "standing idle speak\n" ); - return slIdleSpeak; - } - - if (!IsTalking() && HasConditions(bits_COND_SEE_CLIENT) && RANDOM_LONG(0, 6) == 0) - { - edict_t *pPlayer = g_engfuncs.pfnPEntityOfEntIndex(1); - - if (pPlayer) - { - // watch the client. - UTIL_MakeVectors(pPlayer->v.angles); - if ((pPlayer->v.origin - pev->origin).Length2D() < TLK_STARE_DIST && - UTIL_DotPoints(pPlayer->v.origin, pev->origin, gpGlobals->v_forward) >= m_flFieldOfView) - { - // go into the special STARE schedule if the player is close, and looking at me too. - return &slTlkIdleWatchClient[1]; - } - - return slTlkIdleWatchClient; - } - } - else - { - if (IsTalking()) - // look at who we're talking to - return slTlkIdleEyecontact; - else - // regular standing idle - return slIdleStand; - } - - // NOTE - caller must first CTalkMonster::GetScheduleOfType, - // then check result and decide what to return ie: if sci gets back - // slIdleStand, return slIdleSciStand - } - break; - } - - return CBaseMonster::GetScheduleOfType(Type); -} - -//========================================================= -// IsTalking - am I saying a sentence right now? -//========================================================= -BOOL CTalkMonster ::IsTalking(void) -{ - if (m_flStopTalkTime > gpGlobals->time) - { - return TRUE; - } - - return FALSE; -} - -//========================================================= -// If there's a player around, watch him. -//========================================================= -void CTalkMonster ::PrescheduleThink(void) -{ - if (!HasConditions(bits_COND_SEE_CLIENT)) - { - SetConditions(bits_COND_CLIENT_UNSEEN); - } -} - -// try to smell something -void CTalkMonster ::TrySmellTalk(void) -{ - if (!FOkToSpeak()) - return; - - // clear smell bits periodically - if (gpGlobals->time > m_flLastSaidSmelled) - { - // ALERT ( at_aiconsole, "Clear smell bits\n" ); - ClearBits(m_bitsSaid, bit_saidSmelled); - } - // smelled something? - if (!FBitSet(m_bitsSaid, bit_saidSmelled) && HasConditions(bits_COND_SMELL)) - { - PlaySentence(m_szGrp[TLK_SMELL], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE); - m_flLastSaidSmelled = gpGlobals->time + 60; // don't talk about the stinky for a while. - SetBits(m_bitsSaid, bit_saidSmelled); - } -} - -int CTalkMonster::IRelationship(CBaseEntity *pTarget) -{ - if (pTarget->IsPlayer()) - if (m_afMemory & bits_MEMORY_PROVOKED) - return R_HT; - return CBaseMonster::IRelationship(pTarget); -} - -void CTalkMonster::StopFollowing(BOOL clearSchedule) -{ - if (IsFollowing()) - { - if (!(m_afMemory & bits_MEMORY_PROVOKED)) - { - PlaySentence(m_szGrp[TLK_UNUSE], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE); - m_hTalkTarget = m_hTargetEnt; - } - - if (m_movementGoal == MOVEGOAL_TARGETENT) - RouteClear(); // Stop him from walking toward the player - m_hTargetEnt = NULL; - if (clearSchedule) - ClearSchedule(); - if (m_hEnemy != NULL) - m_IdealMonsterState = MONSTERSTATE_COMBAT; - } -} - -void CTalkMonster::StartFollowing(CBaseEntity *pLeader) -{ - if (m_pCine) - m_pCine->CancelScript(); - - if (m_hEnemy != NULL) - m_IdealMonsterState = MONSTERSTATE_ALERT; - - m_hTargetEnt = pLeader; - PlaySentence(m_szGrp[TLK_USE], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE); - m_hTalkTarget = m_hTargetEnt; - ClearConditions(bits_COND_CLIENT_PUSH); - ClearSchedule(); -} - -BOOL CTalkMonster::CanFollow(void) -{ - if (m_MonsterState == MONSTERSTATE_SCRIPT) - { - if (!m_pCine->CanInterrupt()) - return FALSE; - } - - if (!IsAlive()) - return FALSE; - - return !IsFollowing(); -} - -void CTalkMonster ::FollowerUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - // Don't allow use during a scripted_sentence - if (m_useTime > gpGlobals->time) - return; - - if (pCaller != NULL && pCaller->IsPlayer()) - { - // Pre-disaster followers can't be used - if (pev->spawnflags & SF_MONSTER_PREDISASTER) - { - DeclineFollowing(); - } - else if (CanFollow()) - { - LimitFollowers(pCaller, 1); - - if (m_afMemory & bits_MEMORY_PROVOKED) - ALERT(at_console, "I'm not following you, you evil person!\n"); - else - { - StartFollowing(pCaller); - SetBits(m_bitsSaid, bit_saidHelloPlayer); // Don't say hi after you've started following - } - } - else - { - StopFollowing(TRUE); - } - } -} - -void CTalkMonster::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "UseSentence")) - { - m_iszUse = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "UnUseSentence")) - { - m_iszUnUse = ALLOC_STRING(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else - CBaseMonster::KeyValue(pkvd); -} - -void CTalkMonster::Precache(void) -{ - if (m_iszUse) - m_szGrp[TLK_USE] = STRING(m_iszUse); - if (m_iszUnUse) - m_szGrp[TLK_UNUSE] = STRING(m_iszUnUse); -} diff --git a/dlls/Half-life/talkmonster.h b/dlls/Half-life/talkmonster.h deleted file mode 100644 index bfdd1ac6..00000000 --- a/dlls/Half-life/talkmonster.h +++ /dev/null @@ -1,178 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -#ifndef TALKMONSTER_H -#define TALKMONSTER_H - -#ifndef MONSTERS_H -#include "monsters.h" -#endif - -//========================================================= -// Talking monster base class -// Used for scientists and barneys -//========================================================= - -#define TALKRANGE_MIN 500.0 // don't talk to anyone farther away than this - -#define TLK_STARE_DIST 128 // anyone closer than this and looking at me is probably staring at me. - -#define bit_saidDamageLight (1 << 0) // bits so we don't repeat key sentences -#define bit_saidDamageMedium (1 << 1) -#define bit_saidDamageHeavy (1 << 2) -#define bit_saidHelloPlayer (1 << 3) -#define bit_saidWoundLight (1 << 4) -#define bit_saidWoundHeavy (1 << 5) -#define bit_saidHeard (1 << 6) -#define bit_saidSmelled (1 << 7) - -#define TLK_CFRIENDS 3 - -typedef enum -{ - TLK_ANSWER = 0, - TLK_QUESTION, - TLK_IDLE, - TLK_STARE, - TLK_USE, - TLK_UNUSE, - TLK_STOP, - TLK_NOSHOOT, - TLK_HELLO, - TLK_PHELLO, - TLK_PIDLE, - TLK_PQUESTION, - TLK_PLHURT1, - TLK_PLHURT2, - TLK_PLHURT3, - TLK_SMELL, - TLK_WOUND, - TLK_MORTAL, - - TLK_CGROUPS, // MUST be last entry -} TALKGROUPNAMES; - -enum -{ - SCHED_CANT_FOLLOW = LAST_COMMON_SCHEDULE + 1, - SCHED_MOVE_AWAY, // Try to get out of the player's way - SCHED_MOVE_AWAY_FOLLOW, // same, but follow afterward - SCHED_MOVE_AWAY_FAIL, // Turn back toward player - - LAST_TALKMONSTER_SCHEDULE, // MUST be last -}; - -enum -{ - TASK_CANT_FOLLOW = LAST_COMMON_TASK + 1, - TASK_MOVE_AWAY_PATH, - TASK_WALK_PATH_FOR_UNITS, - - TASK_TLK_RESPOND, // say my response - TASK_TLK_SPEAK, // question or remark - TASK_TLK_HELLO, // Try to say hello to player - TASK_TLK_HEADRESET, // reset head position - TASK_TLK_STOPSHOOTING, // tell player to stop shooting friend - TASK_TLK_STARE, // let the player know I know he's staring at me. - TASK_TLK_LOOK_AT_CLIENT, // faces player if not moving and not talking and in idle. - TASK_TLK_CLIENT_STARE, // same as look at client, but says something if the player stares. - TASK_TLK_EYECONTACT, // maintain eyecontact with person who I'm talking to - TASK_TLK_IDEALYAW, // set ideal yaw to face who I'm talking to - TASK_FACE_PLAYER, // Face the player - - LAST_TALKMONSTER_TASK, // MUST be last -}; - -class CTalkMonster : public CBaseMonster -{ -public: - void TalkInit(void); - CBaseEntity *FindNearestFriend(BOOL fPlayer); - float TargetDistance(void); - void StopTalking(void) { SentenceStop(); } - - // Base Monster functions - void Precache(void); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - void Touch(CBaseEntity *pOther); - void Killed(entvars_t *pevAttacker, int iGib); - int IRelationship(CBaseEntity *pTarget); - virtual int CanPlaySentence(BOOL fDisregardState); - virtual void PlaySentence(const char *pszSentence, float duration, float volume, float attenuation); - void PlayScriptedSentence(const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener); - void KeyValue(KeyValueData *pkvd); - - // AI functions - void SetActivity(Activity newActivity); - Schedule_t *GetScheduleOfType(int Type); - void StartTask(Task_t *pTask); - void RunTask(Task_t *pTask); - void HandleAnimEvent(MonsterEvent_t *pEvent); - void PrescheduleThink(void); - - // Conversations / communication - int GetVoicePitch(void); - void IdleRespond(void); - int FIdleSpeak(void); - int FIdleStare(void); - int FIdleHello(void); - void IdleHeadTurn(Vector &vecFriend); - int FOkToSpeak(void); - void TrySmellTalk(void); - CBaseEntity *EnumFriends(CBaseEntity *pentPrevious, int listNumber, BOOL bTrace); - void AlertFriends(void); - void ShutUpFriends(void); - BOOL IsTalking(void); - void Talk(float flDuration); - // For following - BOOL CanFollow(void); - BOOL IsFollowing(void) { return m_hTargetEnt != NULL && m_hTargetEnt->IsPlayer(); } - void StopFollowing(BOOL clearSchedule); - void StartFollowing(CBaseEntity *pLeader); - virtual void DeclineFollowing(void) {} - void LimitFollowers(CBaseEntity *pPlayer, int maxFollowers); - - void EXPORT FollowerUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - - virtual void SetAnswerQuestion(CTalkMonster *pSpeaker); - virtual int FriendNumber(int arrayNumber) { return arrayNumber; } - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - static char *m_szFriends[TLK_CFRIENDS]; // array of friend names - static float g_talkWaitTime; - - int m_bitsSaid; // set bits for sentences we don't want repeated - int m_nSpeak; // number of times initiated talking - int m_voicePitch; // pitch of voice for this head - const char *m_szGrp[TLK_CGROUPS]; // sentence group names - float m_useTime; // Don't allow +USE until this time - int m_iszUse; // Custom +USE sentence group (follow) - int m_iszUnUse; // Custom +USE sentence group (stop following) - - float m_flLastSaidSmelled; // last time we talked about something that stinks - float m_flStopTalkTime; // when in the future that I'll be done saying this sentence. - - EHANDLE m_hTalkTarget; // who to look at while talking - CUSTOM_SCHEDULES; -}; - -// Clients can push talkmonsters out of their way -#define bits_COND_CLIENT_PUSH (bits_COND_SPECIAL1) -// Don't see a client right now. -#define bits_COND_CLIENT_UNSEEN (bits_COND_SPECIAL2) - -#endif //TALKMONSTER_H diff --git a/dlls/Half-life/teamplay_gamerules.cpp b/dlls/Half-life/teamplay_gamerules.cpp deleted file mode 100644 index e13157d9..00000000 --- a/dlls/Half-life/teamplay_gamerules.cpp +++ /dev/null @@ -1,576 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// teamplay_gamerules.cpp -// -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "player.h" -#include "weapons.h" -#include "gamerules.h" -#include "teamplay_gamerules.h" -#include "game.h" - -static char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH]; -static int team_scores[MAX_TEAMS]; -static int num_teams = 0; - -extern DLL_GLOBAL BOOL g_fGameOver; - -CHalfLifeTeamplay ::CHalfLifeTeamplay() -{ - m_DisableDeathMessages = FALSE; - m_DisableDeathPenalty = FALSE; - - memset(team_names, 0, sizeof(team_names)); - memset(team_scores, 0, sizeof(team_scores)); - num_teams = 0; - - // Copy over the team from the server config - m_szTeamList[0] = 0; - - // Cache this because the team code doesn't want to deal with changing this in the middle of a game - strncpy(m_szTeamList, teamlist.string, TEAMPLAY_TEAMLISTLENGTH); - - edict_t *pWorld = INDEXENT(0); - if (pWorld && pWorld->v.team) - { - if (teamoverride.value) - { - const char *pTeamList = STRING(pWorld->v.team); - if (pTeamList && strlen(pTeamList)) - { - strncpy(m_szTeamList, pTeamList, TEAMPLAY_TEAMLISTLENGTH); - } - } - } - // Has the server set teams - if (strlen(m_szTeamList)) - m_teamLimit = TRUE; - else - m_teamLimit = FALSE; - - RecountTeams(); -} - -extern cvar_t timeleft, fragsleft; - -void CHalfLifeTeamplay ::Think(void) -{ - ///// Check game rules ///// - static int last_frags; - static int last_time; - - int frags_remaining = 0; - int time_remaining = 0; - - if (g_fGameOver) // someone else quit the game already - { - CHalfLifeMultiplay::Think(); - return; - } - - float flTimeLimit = CVAR_GET_FLOAT("mp_timelimit") * 60; - - time_remaining = (int)(flTimeLimit ? (flTimeLimit - gpGlobals->time) : 0); - - if (flTimeLimit != 0 && gpGlobals->time >= flTimeLimit) - { - GoToIntermission(); - return; - } - - float flFragLimit = fraglimit.value; - if (flFragLimit) - { - int bestfrags = 9999; - int remain; - - // check if any team is over the frag limit - for (int i = 0; i < num_teams; i++) - { - if (team_scores[i] >= flFragLimit) - { - GoToIntermission(); - return; - } - - remain = flFragLimit - team_scores[i]; - if (remain < bestfrags) - { - bestfrags = remain; - } - } - frags_remaining = bestfrags; - } - - // Updates when frags change - if (frags_remaining != last_frags) - { - g_engfuncs.pfnCvar_DirectSet(&fragsleft, UTIL_VarArgs("%i", frags_remaining)); - } - - // Updates once per second - if (timeleft.value != last_time) - { - g_engfuncs.pfnCvar_DirectSet(&timeleft, UTIL_VarArgs("%i", time_remaining)); - } - - last_frags = frags_remaining; - last_time = time_remaining; -} - -//========================================================= -// ClientCommand -// the user has typed a command which is unrecognized by everything else; -// this check to see if the gamerules knows anything about the command -//========================================================= -BOOL CHalfLifeTeamplay ::ClientCommand(CBasePlayer *pPlayer, const char *pcmd) -{ - if (FStrEq(pcmd, "menuselect")) - { - if (CMD_ARGC() < 2) - return TRUE; - - int slot = atoi(CMD_ARGV(1)); - - // select the item from the current menu - - return TRUE; - } - - return FALSE; -} - -extern int gmsgGameMode; -extern int gmsgSayText; -extern int gmsgTeamInfo; - -void CHalfLifeTeamplay ::UpdateGameMode(CBasePlayer *pPlayer) -{ - MESSAGE_BEGIN(MSG_ONE, gmsgGameMode, NULL, pPlayer->edict()); - WRITE_BYTE(1); // game mode teamplay - MESSAGE_END(); -} - -const char *CHalfLifeTeamplay::SetDefaultPlayerTeam(CBasePlayer *pPlayer) -{ - // copy out the team name from the model - char *mdls = g_engfuncs.pfnInfoKeyValue(g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "model"); - strncpy(pPlayer->m_szTeamName, mdls, TEAM_NAME_LENGTH); - - RecountTeams(); - - // update the current player of the team he is joining - if (pPlayer->m_szTeamName[0] == '\0' || !IsValidTeam(pPlayer->m_szTeamName) || defaultteam.value) - { - const char *pTeamName = NULL; - - if (defaultteam.value) - { - pTeamName = team_names[0]; - } - else - { - pTeamName = TeamWithFewestPlayers(); - } - strncpy(pPlayer->m_szTeamName, pTeamName, TEAM_NAME_LENGTH); - } - - return pPlayer->m_szTeamName; -} - -//========================================================= -// InitHUD -//========================================================= -void CHalfLifeTeamplay::InitHUD(CBasePlayer *pPlayer) -{ - SetDefaultPlayerTeam(pPlayer); - CHalfLifeMultiplay::InitHUD(pPlayer); - - RecountTeams(); - - char *mdls = g_engfuncs.pfnInfoKeyValue(g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "model"); - // update the current player of the team he is joining - char text[1024]; - if (!strcmp(mdls, pPlayer->m_szTeamName)) - { - _snprintf(text, sizeof(text), "* you are on team \'%s\'\n", pPlayer->m_szTeamName ); - } - else - { - _snprintf(text, sizeof(text), "* assigned to team %s\n", pPlayer->m_szTeamName ); - } - - ChangePlayerTeam(pPlayer, pPlayer->m_szTeamName, FALSE, FALSE); - UTIL_SayText(text, pPlayer); - int clientIndex = pPlayer->entindex(); - RecountTeams(); - // update this player with all the other players team info - // loop through all active players and send their team info to the new client - for (int i = 1; i <= gpGlobals->maxClients; i++) - { - CBaseEntity *plr = UTIL_PlayerByIndex(i); - if (plr && IsValidTeam(plr->TeamID())) - { - MESSAGE_BEGIN(MSG_ONE, gmsgTeamInfo, NULL, pPlayer->edict()); - WRITE_BYTE(plr->entindex()); - WRITE_STRING(plr->TeamID()); - MESSAGE_END(); - } - } -} - -void CHalfLifeTeamplay::ChangePlayerTeam(CBasePlayer *pPlayer, const char *pTeamName, BOOL bKill, BOOL bGib) -{ - int damageFlags = DMG_GENERIC; - int clientIndex = pPlayer->entindex(); - - if (!bGib) - { - damageFlags |= DMG_NEVERGIB; - } - else - { - damageFlags |= DMG_ALWAYSGIB; - } - - if (bKill) - { - // kill the player, remove a death, and let them start on the new team - m_DisableDeathMessages = TRUE; - m_DisableDeathPenalty = TRUE; - - entvars_t *pevWorld = VARS(INDEXENT(0)); - pPlayer->TakeDamage(pevWorld, pevWorld, 900, damageFlags); - - m_DisableDeathMessages = FALSE; - m_DisableDeathPenalty = FALSE; - } - - // copy out the team name from the model - strncpy(pPlayer->m_szTeamName, pTeamName, TEAM_NAME_LENGTH); - - g_engfuncs.pfnSetClientKeyValue(clientIndex, g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "model", pPlayer->m_szTeamName); - g_engfuncs.pfnSetClientKeyValue(clientIndex, g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "team", pPlayer->m_szTeamName); - - // notify everyone's HUD of the team change - MESSAGE_BEGIN(MSG_ALL, gmsgTeamInfo); - WRITE_BYTE(clientIndex); - WRITE_STRING(pPlayer->m_szTeamName); - MESSAGE_END(); -} - -//========================================================= -// ClientUserInfoChanged -//========================================================= -void CHalfLifeTeamplay::ClientUserInfoChanged(CBasePlayer *pPlayer, char *infobuffer) -{ - char text[1024]; - - // prevent skin/color/model changes - char *mdls = g_engfuncs.pfnInfoKeyValue(infobuffer, "model"); - - if (!stricmp(mdls, pPlayer->m_szTeamName)) - return; - - if (defaultteam.value) - { - int clientIndex = pPlayer->entindex(); - - g_engfuncs.pfnSetClientKeyValue(clientIndex, g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "model", pPlayer->m_szTeamName); - g_engfuncs.pfnSetClientKeyValue(clientIndex, g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "team", pPlayer->m_szTeamName); - strncpy(text, "* Not allowed to change teams in this game!\n", sizeof(text) ); - UTIL_SayText(text, pPlayer); - return; - } - - if (defaultteam.value || !IsValidTeam(mdls)) - { - int clientIndex = pPlayer->entindex(); - - g_engfuncs.pfnSetClientKeyValue(clientIndex, g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "model", pPlayer->m_szTeamName); - _snprintf(text, sizeof(text), "* Can't change team to \'%s\'\n", mdls ); - UTIL_SayText(text, pPlayer); - _snprintf(text, sizeof(text), "* Server limits teams to \'%s\'\n", m_szTeamList ); - UTIL_SayText(text, pPlayer); - return; - } - // notify everyone of the team change - _snprintf(text, sizeof(text), "* %s has changed to team \'%s\'\n", STRING(pPlayer->pev->netname), mdls ); - UTIL_SayTextAll(text, pPlayer); - - UTIL_LogPrintf("\"%s<%i>\" changed to team %s\n", STRING(pPlayer->pev->netname), GETPLAYERUSERID(pPlayer->edict()), mdls); - - ChangePlayerTeam(pPlayer, mdls, TRUE, TRUE); - // recound stuff - RecountTeams(); -} - -extern int gmsgDeathMsg; - -//========================================================= -// Deathnotice. -//========================================================= -void CHalfLifeTeamplay::DeathNotice(CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor) -{ - if (m_DisableDeathMessages) - return; - - if (pVictim && pKiller && pKiller->flags & FL_CLIENT) - { - CBasePlayer *pk = (CBasePlayer *)CBaseEntity::Instance(pKiller); - - if (pk) - { - if ((pk != pVictim) && (PlayerRelationship(pVictim, pk) == GR_TEAMMATE)) - { - MESSAGE_BEGIN(MSG_ALL, gmsgDeathMsg); - WRITE_BYTE(ENTINDEX(ENT(pKiller))); // the killer - WRITE_BYTE(ENTINDEX(pVictim->edict())); // the victim - WRITE_STRING("teammate"); // flag this as a teammate kill - MESSAGE_END(); - return; - } - } - } - - CHalfLifeMultiplay::DeathNotice(pVictim, pKiller, pevInflictor); -} - -//========================================================= -//========================================================= -void CHalfLifeTeamplay ::PlayerKilled(CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor) -{ - if (!m_DisableDeathPenalty) - { - CHalfLifeMultiplay::PlayerKilled(pVictim, pKiller, pInflictor); - RecountTeams(); - } -} - -//========================================================= -// IsTeamplay -//========================================================= -BOOL CHalfLifeTeamplay::IsTeamplay(void) -{ - return TRUE; -} - -BOOL CHalfLifeTeamplay::FPlayerCanTakeDamage(CBasePlayer *pPlayer, CBaseEntity *pAttacker) -{ - if (pAttacker && PlayerRelationship(pPlayer, pAttacker) == GR_TEAMMATE) - { - // my teammate hit me. - if ((CVAR_GET_FLOAT("mp_friendlyfire") == 0) && (pAttacker != pPlayer)) - { - // friendly fire is off, and this hit came from someone other than myself, then don't get hurt - return FALSE; - } - } - - return CHalfLifeMultiplay::FPlayerCanTakeDamage(pPlayer, pAttacker); -} - -//========================================================= -//========================================================= -int CHalfLifeTeamplay::PlayerRelationship(CBaseEntity *pPlayer, CBaseEntity *pTarget) -{ - // half life multiplay has a simple concept of Player Relationships. - // you are either on another player's team, or you are not. - if (!pPlayer || !pTarget || !pTarget->IsPlayer()) - return GR_NOTTEAMMATE; - - if ((*GetTeamID(pPlayer) != '\0') && (*GetTeamID(pTarget) != '\0') && !stricmp(GetTeamID(pPlayer), GetTeamID(pTarget))) - { - return GR_TEAMMATE; - } - - return GR_NOTTEAMMATE; -} - -//========================================================= -//========================================================= -BOOL CHalfLifeTeamplay::ShouldAutoAim(CBasePlayer *pPlayer, edict_t *target) -{ - // always autoaim, unless target is a teammate - CBaseEntity *pTgt = CBaseEntity::Instance(target); - if (pTgt && pTgt->IsPlayer()) - { - if (PlayerRelationship(pPlayer, pTgt) == GR_TEAMMATE) - return FALSE; // don't autoaim at teammates - } - - return CHalfLifeMultiplay::ShouldAutoAim(pPlayer, target); -} - -//========================================================= -//========================================================= -int CHalfLifeTeamplay::IPointsForKill(CBasePlayer *pAttacker, CBasePlayer *pKilled) -{ - if (!pKilled) - return 0; - - if (!pAttacker) - return 1; - - if (pAttacker != pKilled && PlayerRelationship(pAttacker, pKilled) == GR_TEAMMATE) - return -1; - - return 1; -} - -//========================================================= -//========================================================= -const char *CHalfLifeTeamplay::GetTeamID(CBaseEntity *pEntity) -{ - if (pEntity == NULL || pEntity->pev == NULL) - return ""; - - // return their team name - return pEntity->TeamID(); -} - -int CHalfLifeTeamplay::GetTeamIndex(const char *pTeamName) -{ - if (pTeamName && *pTeamName != 0) - { - // try to find existing team - for (int tm = 0; tm < num_teams; tm++) - { - if (!stricmp(team_names[tm], pTeamName)) - return tm; - } - } - - return -1; // No match -} - -const char *CHalfLifeTeamplay::GetIndexedTeamName(int teamIndex) -{ - if (teamIndex < 0 || teamIndex >= num_teams) - return ""; - - return team_names[teamIndex]; -} - -BOOL CHalfLifeTeamplay::IsValidTeam(const char *pTeamName) -{ - if (!m_teamLimit) // Any team is valid if the teamlist isn't set - return TRUE; - - return (GetTeamIndex(pTeamName) != -1) ? TRUE : FALSE; -} - -const char *CHalfLifeTeamplay::TeamWithFewestPlayers(void) -{ - int i; - int minPlayers = MAX_TEAMS; - int teamCount[MAX_TEAMS]; - char *pTeamName = NULL; - - memset(teamCount, 0, MAX_TEAMS * sizeof(int)); - - // loop through all clients, count number of players on each team - for (i = 1; i <= gpGlobals->maxClients; i++) - { - CBaseEntity *plr = UTIL_PlayerByIndex(i); - - if (plr) - { - int team = GetTeamIndex(plr->TeamID()); - if (team >= 0) - teamCount[team]++; - } - } - - // Find team with least players - for (i = 0; i < num_teams; i++) - { - if (teamCount[i] < minPlayers) - { - minPlayers = teamCount[i]; - pTeamName = team_names[i]; - } - } - - return pTeamName; -} - -//========================================================= -//========================================================= -void CHalfLifeTeamplay::RecountTeams(void) -{ - char *pName; - char teamlist[TEAMPLAY_TEAMLISTLENGTH]; - - // loop through all teams, recounting everything - num_teams = 0; - - // Copy all of the teams from the teamlist - // make a copy because strtok is destructive - strncpy(teamlist, m_szTeamList, sizeof(teamlist) ); - pName = teamlist; - pName = strtok(pName, ";"); - while (pName != NULL && *pName) - { - if (GetTeamIndex(pName) < 0) - { - strncpy(team_names[num_teams], pName, sizeof(team_names[num_teams]) ); - num_teams++; - } - pName = strtok(NULL, ";"); - } - - if (num_teams < 2) - { - num_teams = 0; - m_teamLimit = FALSE; - } - - // Sanity check - memset(team_scores, 0, sizeof(team_scores)); - - // loop through all clients - for (int i = 1; i <= gpGlobals->maxClients; i++) - { - CBaseEntity *plr = UTIL_PlayerByIndex(i); - - if (plr) - { - const char *pTeamName = plr->TeamID(); - // try add to existing team - int tm = GetTeamIndex(pTeamName); - - if (tm < 0) // no team match found - { - if (!m_teamLimit) - { - // add to new team - tm = num_teams; - num_teams++; - team_scores[tm] = 0; - strncpy(team_names[tm], pTeamName, MAX_TEAMNAME_LENGTH); - } - } - - if (tm >= 0) - { - team_scores[tm] += plr->pev->frags; - } - } - } -} diff --git a/dlls/Half-life/tempmonster.cpp b/dlls/Half-life/tempmonster.cpp deleted file mode 100644 index c3d85fbc..00000000 --- a/dlls/Half-life/tempmonster.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// monster template -//========================================================= -#if 0 - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= - -class CMyMonster : public CBaseMonster -{ -public: - void Spawn( void ); - void Precache( void ); - void SetYawSpeed( void ); - int Classify ( void ); - void HandleAnimEvent( MonsterEvent_t *pEvent ); -}; -LINK_ENTITY_TO_CLASS( my_monster, CMyMonster ); - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CMyMonster :: Classify ( void ) -{ - return CLASS_MY_MONSTER; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CMyMonster :: SetYawSpeed ( void ) -{ - int ys; - - switch ( m_Activity ) - { - case ACT_IDLE: - default: - ys = 90; - } - - pev->yaw_speed = ys; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CMyMonster :: HandleAnimEvent( MonsterEvent_t *pEvent ) -{ - switch( pEvent->event ) - { - case 0: - default: - CBaseMonster::HandleAnimEvent( pEvent ); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CMyMonster :: Spawn() -{ - Precache( ); - - SET_MODEL(ENT(pev), "models/mymodel.mdl"); - UTIL_SetSize( pev, Vector( -12, -12, 0 ), Vector( 12, 12, 24 ) ); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->health = 8; - pev->view_ofs = Vector ( 0, 0, 0 );// position of the eyes relative to monster's origin. - m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CMyMonster :: Precache() -{ - PRECACHE_SOUND("mysound.wav"); - - PRECACHE_MODEL("models/mymodel.mdl"); -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= -#endif 0 diff --git a/dlls/Half-life/tentacle.cpp b/dlls/Half-life/tentacle.cpp deleted file mode 100644 index 22120782..00000000 --- a/dlls/Half-life/tentacle.cpp +++ /dev/null @@ -1,1029 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -#if !defined(OEM_BUILD) && !defined(HLDEMO_BUILD) - -/* - - h_tentacle.cpp - silo of death tentacle monster (half life) - -*/ - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "soundent.h" - -#define ACT_T_IDLE 1010 -#define ACT_T_TAP 1020 -#define ACT_T_STRIKE 1030 -#define ACT_T_REARIDLE 1040 - -class CTentacle : public CBaseMonster -{ -public: - CTentacle(void); - - void Spawn(); - void Precache(); - void KeyValue(KeyValueData *pkvd); - - int Save(CSave &save); - int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - // Don't allow the tentacle to go across transitions!!! - virtual int ObjectCaps(void) { return CBaseMonster ::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - void SetObjectCollisionBox(void) - { - pev->absmin = pev->origin + Vector(-400, -400, 0); - pev->absmax = pev->origin + Vector(400, 400, 850); - } - - void EXPORT Cycle(void); - void EXPORT CommandUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void EXPORT Start(void); - void EXPORT DieThink(void); - - void EXPORT Test(void); - - void EXPORT HitTouch(CBaseEntity *pOther); - - float HearingSensitivity(void) { return 2.0; }; - - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - void HandleAnimEvent(MonsterEvent_t *pEvent); - void Killed(entvars_t *pevAttacker, int iGib); - - MONSTERSTATE GetIdealState(void) { return MONSTERSTATE_IDLE; }; - int CanPlaySequence(BOOL fDisregardState) { return TRUE; }; - - int Classify(void); - - int Level(float dz); - int MyLevel(void); - float MyHeight(void); - - float m_flInitialYaw; - int m_iGoalAnim; - int m_iLevel; - int m_iDir; - float m_flFramerateAdj; - float m_flSoundYaw; - int m_iSoundLevel; - float m_flSoundTime; - float m_flSoundRadius; - int m_iHitDmg; - float m_flHitTime; - - float m_flTapRadius; - - float m_flNextSong; - static int g_fFlySound; - static int g_fSquirmSound; - - float m_flMaxYaw; - int m_iTapSound; - - Vector m_vecPrevSound; - float m_flPrevSoundTime; - - static const char *pHitSilo[]; - static const char *pHitDirt[]; - static const char *pHitWater[]; -}; - -int CTentacle ::g_fFlySound; -int CTentacle ::g_fSquirmSound; - -LINK_ENTITY_TO_CLASS(monster_tentacle, CTentacle); - -// stike sounds -#define TE_NONE -1 -#define TE_SILO 0 -#define TE_DIRT 1 -#define TE_WATER 2 - -const char *CTentacle::pHitSilo[] = - { - "tentacle/te_strike1.wav", - "tentacle/te_strike2.wav", -}; - -const char *CTentacle::pHitDirt[] = - { - "player/pl_dirt1.wav", - "player/pl_dirt2.wav", - "player/pl_dirt3.wav", - "player/pl_dirt4.wav", -}; - -const char *CTentacle::pHitWater[] = - { - "player/pl_slosh1.wav", - "player/pl_slosh2.wav", - "player/pl_slosh3.wav", - "player/pl_slosh4.wav", -}; - -TYPEDESCRIPTION CTentacle::m_SaveData[] = - { - DEFINE_FIELD(CTentacle, m_flInitialYaw, FIELD_FLOAT), - DEFINE_FIELD(CTentacle, m_iGoalAnim, FIELD_INTEGER), - DEFINE_FIELD(CTentacle, m_iLevel, FIELD_INTEGER), - DEFINE_FIELD(CTentacle, m_iDir, FIELD_INTEGER), - DEFINE_FIELD(CTentacle, m_flFramerateAdj, FIELD_FLOAT), - DEFINE_FIELD(CTentacle, m_flSoundYaw, FIELD_FLOAT), - DEFINE_FIELD(CTentacle, m_iSoundLevel, FIELD_INTEGER), - DEFINE_FIELD(CTentacle, m_flSoundTime, FIELD_TIME), - DEFINE_FIELD(CTentacle, m_flSoundRadius, FIELD_FLOAT), - DEFINE_FIELD(CTentacle, m_iHitDmg, FIELD_INTEGER), - DEFINE_FIELD(CTentacle, m_flHitTime, FIELD_TIME), - DEFINE_FIELD(CTentacle, m_flTapRadius, FIELD_FLOAT), - DEFINE_FIELD(CTentacle, m_flNextSong, FIELD_TIME), - DEFINE_FIELD(CTentacle, m_iTapSound, FIELD_INTEGER), - DEFINE_FIELD(CTentacle, m_flMaxYaw, FIELD_FLOAT), - DEFINE_FIELD(CTentacle, m_vecPrevSound, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CTentacle, m_flPrevSoundTime, FIELD_TIME), -}; -IMPLEMENT_SAVERESTORE(CTentacle, CBaseMonster); - -// animation sequence aliases -typedef enum -{ - TENTACLE_ANIM_Pit_Idle, - - TENTACLE_ANIM_rise_to_Temp1, - TENTACLE_ANIM_Temp1_to_Floor, - TENTACLE_ANIM_Floor_Idle, - TENTACLE_ANIM_Floor_Fidget_Pissed, - TENTACLE_ANIM_Floor_Fidget_SmallRise, - TENTACLE_ANIM_Floor_Fidget_Wave, - TENTACLE_ANIM_Floor_Strike, - TENTACLE_ANIM_Floor_Tap, - TENTACLE_ANIM_Floor_Rotate, - TENTACLE_ANIM_Floor_Rear, - TENTACLE_ANIM_Floor_Rear_Idle, - TENTACLE_ANIM_Floor_to_Lev1, - - TENTACLE_ANIM_Lev1_Idle, - TENTACLE_ANIM_Lev1_Fidget_Claw, - TENTACLE_ANIM_Lev1_Fidget_Shake, - TENTACLE_ANIM_Lev1_Fidget_Snap, - TENTACLE_ANIM_Lev1_Strike, - TENTACLE_ANIM_Lev1_Tap, - TENTACLE_ANIM_Lev1_Rotate, - TENTACLE_ANIM_Lev1_Rear, - TENTACLE_ANIM_Lev1_Rear_Idle, - TENTACLE_ANIM_Lev1_to_Lev2, - - TENTACLE_ANIM_Lev2_Idle, - TENTACLE_ANIM_Lev2_Fidget_Shake, - TENTACLE_ANIM_Lev2_Fidget_Swing, - TENTACLE_ANIM_Lev2_Fidget_Tut, - TENTACLE_ANIM_Lev2_Strike, - TENTACLE_ANIM_Lev2_Tap, - TENTACLE_ANIM_Lev2_Rotate, - TENTACLE_ANIM_Lev2_Rear, - TENTACLE_ANIM_Lev2_Rear_Idle, - TENTACLE_ANIM_Lev2_to_Lev3, - - TENTACLE_ANIM_Lev3_Idle, - TENTACLE_ANIM_Lev3_Fidget_Shake, - TENTACLE_ANIM_Lev3_Fidget_Side, - TENTACLE_ANIM_Lev3_Fidget_Swipe, - TENTACLE_ANIM_Lev3_Strike, - TENTACLE_ANIM_Lev3_Tap, - TENTACLE_ANIM_Lev3_Rotate, - TENTACLE_ANIM_Lev3_Rear, - TENTACLE_ANIM_Lev3_Rear_Idle, - - TENTACLE_ANIM_Lev1_Door_reach, - - TENTACLE_ANIM_Lev3_to_Engine, - TENTACLE_ANIM_Engine_Idle, - TENTACLE_ANIM_Engine_Sway, - TENTACLE_ANIM_Engine_Swat, - TENTACLE_ANIM_Engine_Bob, - TENTACLE_ANIM_Engine_Death1, - TENTACLE_ANIM_Engine_Death2, - TENTACLE_ANIM_Engine_Death3, - - TENTACLE_ANIM_none -} TENTACLE_ANIM; - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CTentacle ::Classify(void) -{ - return CLASS_ALIEN_MONSTER; -} - -// -// Tentacle Spawn -// -void CTentacle ::Spawn() -{ - Precache(); - - pev->solid = SOLID_BBOX; - pev->movetype = MOVETYPE_FLY; - pev->effects = 0; - pev->health = 75; - pev->sequence = 0; - - SET_MODEL(ENT(pev), "models/tentacle2.mdl"); - UTIL_SetSize(pev, Vector(-32, -32, 0), Vector(32, 32, 64)); - - pev->takedamage = DAMAGE_AIM; - pev->flags |= FL_MONSTER; - - m_bloodColor = BLOOD_COLOR_GREEN; - - SetThink(Start); - SetTouch(HitTouch); - SetUse(CommandUse); - - pev->nextthink = gpGlobals->time + 0.2; - - ResetSequenceInfo(); - m_iDir = 1; - - pev->yaw_speed = 18; - m_flInitialYaw = pev->angles.y; - pev->ideal_yaw = m_flInitialYaw; - - g_fFlySound = FALSE; - g_fSquirmSound = FALSE; - - m_iHitDmg = 20; - - if (m_flMaxYaw <= 0) - m_flMaxYaw = 65; - - m_MonsterState = MONSTERSTATE_IDLE; - - // SetThink( Test ); - UTIL_SetOrigin(pev, pev->origin); -} - -void CTentacle ::Precache() -{ - PRECACHE_MODEL("models/tentacle2.mdl"); - - PRECACHE_SOUND("ambience/flies.wav"); - PRECACHE_SOUND("ambience/squirm2.wav"); - - PRECACHE_SOUND("tentacle/te_alert1.wav"); - PRECACHE_SOUND("tentacle/te_alert2.wav"); - PRECACHE_SOUND("tentacle/te_flies1.wav"); - PRECACHE_SOUND("tentacle/te_move1.wav"); - PRECACHE_SOUND("tentacle/te_move2.wav"); - PRECACHE_SOUND("tentacle/te_roar1.wav"); - PRECACHE_SOUND("tentacle/te_roar2.wav"); - PRECACHE_SOUND("tentacle/te_search1.wav"); - PRECACHE_SOUND("tentacle/te_search2.wav"); - PRECACHE_SOUND("tentacle/te_sing1.wav"); - PRECACHE_SOUND("tentacle/te_sing2.wav"); - PRECACHE_SOUND("tentacle/te_squirm2.wav"); - PRECACHE_SOUND("tentacle/te_strike1.wav"); - PRECACHE_SOUND("tentacle/te_strike2.wav"); - PRECACHE_SOUND("tentacle/te_swing1.wav"); - PRECACHE_SOUND("tentacle/te_swing2.wav"); - - PRECACHE_SOUND_ARRAY(pHitSilo); - PRECACHE_SOUND_ARRAY(pHitDirt); - PRECACHE_SOUND_ARRAY(pHitWater); -} - -CTentacle::CTentacle() -{ - m_flMaxYaw = 65; - m_iTapSound = 0; -} - -void CTentacle::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "sweeparc")) - { - m_flMaxYaw = atof(pkvd->szValue) / 2.0; - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "sound")) - { - m_iTapSound = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else - CBaseMonster::KeyValue(pkvd); -} - -int CTentacle ::Level(float dz) -{ - if (dz < 216) - return 0; - if (dz < 408) - return 1; - if (dz < 600) - return 2; - return 3; -} - -float CTentacle ::MyHeight() -{ - switch (MyLevel()) - { - case 1: - return 256; - case 2: - return 448; - case 3: - return 640; - } - return 0; -} - -int CTentacle ::MyLevel() -{ - switch (pev->sequence) - { - case TENTACLE_ANIM_Pit_Idle: - return -1; - - case TENTACLE_ANIM_rise_to_Temp1: - case TENTACLE_ANIM_Temp1_to_Floor: - case TENTACLE_ANIM_Floor_to_Lev1: - return 0; - - case TENTACLE_ANIM_Floor_Idle: - case TENTACLE_ANIM_Floor_Fidget_Pissed: - case TENTACLE_ANIM_Floor_Fidget_SmallRise: - case TENTACLE_ANIM_Floor_Fidget_Wave: - case TENTACLE_ANIM_Floor_Strike: - case TENTACLE_ANIM_Floor_Tap: - case TENTACLE_ANIM_Floor_Rotate: - case TENTACLE_ANIM_Floor_Rear: - case TENTACLE_ANIM_Floor_Rear_Idle: - return 0; - - case TENTACLE_ANIM_Lev1_Idle: - case TENTACLE_ANIM_Lev1_Fidget_Claw: - case TENTACLE_ANIM_Lev1_Fidget_Shake: - case TENTACLE_ANIM_Lev1_Fidget_Snap: - case TENTACLE_ANIM_Lev1_Strike: - case TENTACLE_ANIM_Lev1_Tap: - case TENTACLE_ANIM_Lev1_Rotate: - case TENTACLE_ANIM_Lev1_Rear: - case TENTACLE_ANIM_Lev1_Rear_Idle: - return 1; - - case TENTACLE_ANIM_Lev1_to_Lev2: - return 1; - - case TENTACLE_ANIM_Lev2_Idle: - case TENTACLE_ANIM_Lev2_Fidget_Shake: - case TENTACLE_ANIM_Lev2_Fidget_Swing: - case TENTACLE_ANIM_Lev2_Fidget_Tut: - case TENTACLE_ANIM_Lev2_Strike: - case TENTACLE_ANIM_Lev2_Tap: - case TENTACLE_ANIM_Lev2_Rotate: - case TENTACLE_ANIM_Lev2_Rear: - case TENTACLE_ANIM_Lev2_Rear_Idle: - return 2; - - case TENTACLE_ANIM_Lev2_to_Lev3: - return 2; - - case TENTACLE_ANIM_Lev3_Idle: - case TENTACLE_ANIM_Lev3_Fidget_Shake: - case TENTACLE_ANIM_Lev3_Fidget_Side: - case TENTACLE_ANIM_Lev3_Fidget_Swipe: - case TENTACLE_ANIM_Lev3_Strike: - case TENTACLE_ANIM_Lev3_Tap: - case TENTACLE_ANIM_Lev3_Rotate: - case TENTACLE_ANIM_Lev3_Rear: - case TENTACLE_ANIM_Lev3_Rear_Idle: - return 3; - - case TENTACLE_ANIM_Lev1_Door_reach: - return -1; - } - return -1; -} - -void CTentacle ::Test(void) -{ - pev->sequence = TENTACLE_ANIM_Floor_Strike; - pev->framerate = 0; - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; -} - -// -// TentacleThink -// -void CTentacle ::Cycle(void) -{ - // ALERT( at_console, "%s %.2f %d %d\n", STRING( pev->targetname ), pev->origin.z, m_MonsterState, m_IdealMonsterState ); - pev->nextthink = gpGlobals->time + 0.1; - - // ALERT( at_console, "%s %d %d %d %f %f\n", STRING( pev->targetname ), pev->sequence, m_iGoalAnim, m_iDir, pev->framerate, pev->health ); - - if (m_MonsterState == MONSTERSTATE_SCRIPT || m_IdealMonsterState == MONSTERSTATE_SCRIPT) - { - pev->angles.y = m_flInitialYaw; - pev->ideal_yaw = m_flInitialYaw; - ClearConditions(IgnoreConditions()); - MonsterThink(); - m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; - return; - } - - DispatchAnimEvents(); - StudioFrameAdvance(); - - ChangeYaw(pev->yaw_speed); - - CSound *pSound; - - Listen(); - - // Listen will set this if there's something in my sound list - if (HasConditions(bits_COND_HEAR_SOUND)) - pSound = PBestSound(); - else - pSound = NULL; - - if (pSound) - { - Vector vecDir; - if (gpGlobals->time - m_flPrevSoundTime < 0.5) - { - float dt = gpGlobals->time - m_flPrevSoundTime; - vecDir = pSound->m_vecOrigin + (pSound->m_vecOrigin - m_vecPrevSound) / dt - pev->origin; - } - else - { - vecDir = pSound->m_vecOrigin - pev->origin; - } - m_flPrevSoundTime = gpGlobals->time; - m_vecPrevSound = pSound->m_vecOrigin; - - m_flSoundYaw = UTIL_VecToYaw(vecDir) - m_flInitialYaw; - m_iSoundLevel = Level(vecDir.z); - - if (m_flSoundYaw < -180) - m_flSoundYaw += 360; - if (m_flSoundYaw > 180) - m_flSoundYaw -= 360; - - // ALERT( at_console, "sound %d %.0f\n", m_iSoundLevel, m_flSoundYaw ); - if (m_flSoundTime < gpGlobals->time) - { - // play "I hear new something" sound - char *sound; - - switch (RANDOM_LONG(0, 1)) - { - case 0: - sound = "tentacle/te_alert1.wav"; - break; - case 1: - sound = "tentacle/te_alert2.wav"; - break; - } - - // UTIL_EmitAmbientSound(ENT(pev), pev->origin + Vector( 0, 0, MyHeight()), sound, 1.0, ATTN_NORM, 0, 100); - } - m_flSoundTime = gpGlobals->time + RANDOM_FLOAT(5.0, 10.0); - } - - // clip ideal_yaw - float dy = m_flSoundYaw; - switch (pev->sequence) - { - case TENTACLE_ANIM_Floor_Rear: - case TENTACLE_ANIM_Floor_Rear_Idle: - case TENTACLE_ANIM_Lev1_Rear: - case TENTACLE_ANIM_Lev1_Rear_Idle: - case TENTACLE_ANIM_Lev2_Rear: - case TENTACLE_ANIM_Lev2_Rear_Idle: - case TENTACLE_ANIM_Lev3_Rear: - case TENTACLE_ANIM_Lev3_Rear_Idle: - if (dy < 0 && dy > -m_flMaxYaw) - dy = -m_flMaxYaw; - if (dy > 0 && dy < m_flMaxYaw) - dy = m_flMaxYaw; - break; - default: - if (dy < -m_flMaxYaw) - dy = -m_flMaxYaw; - if (dy > m_flMaxYaw) - dy = m_flMaxYaw; - } - pev->ideal_yaw = m_flInitialYaw + dy; - - if (m_fSequenceFinished) - { - // ALERT( at_console, "%s done %d %d\n", STRING( pev->targetname ), pev->sequence, m_iGoalAnim ); - if (pev->health <= 1) - { - m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; - if (pev->sequence == TENTACLE_ANIM_Pit_Idle) - { - pev->health = 75; - } - } - else if (m_flSoundTime > gpGlobals->time) - { - if (m_flSoundYaw >= -(m_flMaxYaw + 30) && m_flSoundYaw <= (m_flMaxYaw + 30)) - { - // strike - m_iGoalAnim = LookupActivity(ACT_T_STRIKE + m_iSoundLevel); - } - else if (m_flSoundYaw >= -m_flMaxYaw * 2 && m_flSoundYaw <= m_flMaxYaw * 2) - { - // tap - m_iGoalAnim = LookupActivity(ACT_T_TAP + m_iSoundLevel); - } - else - { - // go into rear idle - m_iGoalAnim = LookupActivity(ACT_T_REARIDLE + m_iSoundLevel); - } - } - else if (pev->sequence == TENTACLE_ANIM_Pit_Idle) - { - // stay in pit until hear noise - m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; - } - else if (pev->sequence == m_iGoalAnim) - { - if (MyLevel() >= 0 && gpGlobals->time < m_flSoundTime) - { - if (RANDOM_LONG(0, 9) < m_flSoundTime - gpGlobals->time) - { - // continue stike - m_iGoalAnim = LookupActivity(ACT_T_STRIKE + m_iSoundLevel); - } - else - { - // tap - m_iGoalAnim = LookupActivity(ACT_T_TAP + m_iSoundLevel); - } - } - else if (MyLevel() < 0) - { - m_iGoalAnim = LookupActivity(ACT_T_IDLE + 0); - } - else - { - if (m_flNextSong < gpGlobals->time) - { - // play "I hear new something" sound - char *sound; - - switch (RANDOM_LONG(0, 1)) - { - case 0: - sound = "tentacle/te_sing1.wav"; - break; - case 1: - sound = "tentacle/te_sing2.wav"; - break; - } - - EMIT_SOUND(ENT(pev), CHAN_VOICE, sound, 1.0, ATTN_NORM); - - m_flNextSong = gpGlobals->time + RANDOM_FLOAT(10, 20); - } - - if (RANDOM_LONG(0, 15) == 0) - { - // idle on new level - m_iGoalAnim = LookupActivity(ACT_T_IDLE + RANDOM_LONG(0, 3)); - } - else if (RANDOM_LONG(0, 3) == 0) - { - // tap - m_iGoalAnim = LookupActivity(ACT_T_TAP + MyLevel()); - } - else - { - // idle - m_iGoalAnim = LookupActivity(ACT_T_IDLE + MyLevel()); - } - } - if (m_flSoundYaw < 0) - m_flSoundYaw += RANDOM_FLOAT(2, 8); - else - m_flSoundYaw -= RANDOM_FLOAT(2, 8); - } - - pev->sequence = FindTransition(pev->sequence, m_iGoalAnim, &m_iDir); - - if (m_iDir > 0) - { - pev->frame = 0; - } - else - { - m_iDir = -1; // just to safe - pev->frame = 255; - } - ResetSequenceInfo(); - - m_flFramerateAdj = RANDOM_FLOAT(-0.2, 0.2); - pev->framerate = m_iDir * 1.0 + m_flFramerateAdj; - - switch (pev->sequence) - { - case TENTACLE_ANIM_Floor_Tap: - case TENTACLE_ANIM_Lev1_Tap: - case TENTACLE_ANIM_Lev2_Tap: - case TENTACLE_ANIM_Lev3_Tap: - { - Vector vecSrc; - UTIL_MakeVectors(pev->angles); - - TraceResult tr1, tr2; - - vecSrc = pev->origin + Vector(0, 0, MyHeight() - 4); - UTIL_TraceLine(vecSrc, vecSrc + gpGlobals->v_forward * 512, ignore_monsters, ENT(pev), &tr1); - - vecSrc = pev->origin + Vector(0, 0, MyHeight() + 8); - UTIL_TraceLine(vecSrc, vecSrc + gpGlobals->v_forward * 512, ignore_monsters, ENT(pev), &tr2); - - // ALERT( at_console, "%f %f\n", tr1.flFraction * 512, tr2.flFraction * 512 ); - - m_flTapRadius = SetBlending(0, RANDOM_FLOAT(tr1.flFraction * 512, tr2.flFraction * 512)); - } - break; - default: - m_flTapRadius = 336; // 400 - 64 - break; - } - pev->view_ofs.z = MyHeight(); - // ALERT( at_console, "seq %d\n", pev->sequence ); - } - - if (m_flPrevSoundTime + 2.0 > gpGlobals->time) - { - // 1.5 normal speed if hears sounds - pev->framerate = m_iDir * 1.5 + m_flFramerateAdj; - } - else if (m_flPrevSoundTime + 5.0 > gpGlobals->time) - { - // slowdown to normal - pev->framerate = m_iDir + m_iDir * (5 - (gpGlobals->time - m_flPrevSoundTime)) / 2 + m_flFramerateAdj; - } -} - -void CTentacle::CommandUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - // ALERT( at_console, "%s triggered %d\n", STRING( pev->targetname ), useType ); - switch (useType) - { - case USE_OFF: - pev->takedamage = DAMAGE_NO; - SetThink(DieThink); - m_iGoalAnim = TENTACLE_ANIM_Engine_Death1; - break; - case USE_ON: - if (pActivator) - { - // ALERT( at_console, "insert sound\n"); - CSoundEnt::InsertSound(bits_SOUND_WORLD, pActivator->pev->origin, 1024, 1.0); - } - break; - case USE_SET: - break; - case USE_TOGGLE: - pev->takedamage = DAMAGE_NO; - SetThink(DieThink); - m_iGoalAnim = TENTACLE_ANIM_Engine_Idle; - break; - } -} - -void CTentacle ::DieThink(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - - DispatchAnimEvents(); - StudioFrameAdvance(); - - ChangeYaw(24); - - if (m_fSequenceFinished) - { - if (pev->sequence == m_iGoalAnim) - { - switch (m_iGoalAnim) - { - case TENTACLE_ANIM_Engine_Idle: - case TENTACLE_ANIM_Engine_Sway: - case TENTACLE_ANIM_Engine_Swat: - case TENTACLE_ANIM_Engine_Bob: - m_iGoalAnim = TENTACLE_ANIM_Engine_Sway + RANDOM_LONG(0, 2); - break; - case TENTACLE_ANIM_Engine_Death1: - case TENTACLE_ANIM_Engine_Death2: - case TENTACLE_ANIM_Engine_Death3: - UTIL_Remove(this); - return; - } - } - - // ALERT( at_console, "%d : %d => ", pev->sequence, m_iGoalAnim ); - pev->sequence = FindTransition(pev->sequence, m_iGoalAnim, &m_iDir); - // ALERT( at_console, "%d\n", pev->sequence ); - - if (m_iDir > 0) - { - pev->frame = 0; - } - else - { - pev->frame = 255; - } - ResetSequenceInfo(); - - float dy; - switch (pev->sequence) - { - case TENTACLE_ANIM_Floor_Rear: - case TENTACLE_ANIM_Floor_Rear_Idle: - case TENTACLE_ANIM_Lev1_Rear: - case TENTACLE_ANIM_Lev1_Rear_Idle: - case TENTACLE_ANIM_Lev2_Rear: - case TENTACLE_ANIM_Lev2_Rear_Idle: - case TENTACLE_ANIM_Lev3_Rear: - case TENTACLE_ANIM_Lev3_Rear_Idle: - case TENTACLE_ANIM_Engine_Idle: - case TENTACLE_ANIM_Engine_Sway: - case TENTACLE_ANIM_Engine_Swat: - case TENTACLE_ANIM_Engine_Bob: - case TENTACLE_ANIM_Engine_Death1: - case TENTACLE_ANIM_Engine_Death2: - case TENTACLE_ANIM_Engine_Death3: - pev->framerate = RANDOM_FLOAT(m_iDir - 0.2, m_iDir + 0.2); - dy = 180; - break; - default: - pev->framerate = 1.5; - dy = 0; - break; - } - pev->ideal_yaw = m_flInitialYaw + dy; - } -} - -void CTentacle ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - char *sound; - - switch (pEvent->event) - { - case 1: // bang - { - Vector vecSrc, vecAngles; - GetAttachment(0, vecSrc, vecAngles); - - // Vector vecSrc = pev->origin + m_flTapRadius * Vector( cos( pev->angles.y * (3.14192653 / 180.0) ), sin( pev->angles.y * (M_PI / 180.0) ), 0.0 ); - - // vecSrc.z += MyHeight( ); - - switch (m_iTapSound) - { - case TE_SILO: - UTIL_EmitAmbientSound(ENT(pev), vecSrc, RANDOM_SOUND_ARRAY(pHitSilo), 1.0, ATTN_NORM, 0, 100); - break; - case TE_NONE: - break; - case TE_DIRT: - UTIL_EmitAmbientSound(ENT(pev), vecSrc, RANDOM_SOUND_ARRAY(pHitDirt), 1.0, ATTN_NORM, 0, 100); - break; - case TE_WATER: - UTIL_EmitAmbientSound(ENT(pev), vecSrc, RANDOM_SOUND_ARRAY(pHitWater), 1.0, ATTN_NORM, 0, 100); - break; - } - gpGlobals->force_retouch++; - } - break; - - case 3: // start killing swing - m_iHitDmg = 200; - // UTIL_EmitAmbientSound(ENT(pev), pev->origin + Vector( 0, 0, MyHeight()), "tentacle/te_swing1.wav", 1.0, ATTN_NORM, 0, 100); - break; - - case 4: // end killing swing - m_iHitDmg = 25; - break; - - case 5: // just "whoosh" sound - // UTIL_EmitAmbientSound(ENT(pev), pev->origin + Vector( 0, 0, MyHeight()), "tentacle/te_swing2.wav", 1.0, ATTN_NORM, 0, 100); - break; - - case 2: // tap scrape - case 6: // light tap - { - Vector vecSrc = pev->origin + m_flTapRadius * Vector(cos(pev->angles.y * (M_PI / 180.0)), sin(pev->angles.y * (M_PI / 180.0)), 0.0); - - vecSrc.z += MyHeight(); - - float flVol = RANDOM_FLOAT(0.3, 0.5); - - switch (m_iTapSound) - { - case TE_SILO: - UTIL_EmitAmbientSound(ENT(pev), vecSrc, RANDOM_SOUND_ARRAY(pHitSilo), flVol, ATTN_NORM, 0, 100); - break; - case TE_NONE: - break; - case TE_DIRT: - UTIL_EmitAmbientSound(ENT(pev), vecSrc, RANDOM_SOUND_ARRAY(pHitDirt), flVol, ATTN_NORM, 0, 100); - break; - case TE_WATER: - UTIL_EmitAmbientSound(ENT(pev), vecSrc, RANDOM_SOUND_ARRAY(pHitWater), flVol, ATTN_NORM, 0, 100); - break; - } - } - break; - - case 7: // roar - switch (RANDOM_LONG(0, 1)) - { - case 0: - sound = "tentacle/te_roar1.wav"; - break; - case 1: - sound = "tentacle/te_roar2.wav"; - break; - } - - UTIL_EmitAmbientSound(ENT(pev), pev->origin + Vector(0, 0, MyHeight()), sound, 1.0, ATTN_NORM, 0, 100); - break; - - case 8: // search - switch (RANDOM_LONG(0, 1)) - { - case 0: - sound = "tentacle/te_search1.wav"; - break; - case 1: - sound = "tentacle/te_search2.wav"; - break; - } - - UTIL_EmitAmbientSound(ENT(pev), pev->origin + Vector(0, 0, MyHeight()), sound, 1.0, ATTN_NORM, 0, 100); - break; - - case 9: // swing - switch (RANDOM_LONG(0, 1)) - { - case 0: - sound = "tentacle/te_move1.wav"; - break; - case 1: - sound = "tentacle/te_move2.wav"; - break; - } - - UTIL_EmitAmbientSound(ENT(pev), pev->origin + Vector(0, 0, MyHeight()), sound, 1.0, ATTN_NORM, 0, 100); - break; - - default: - CBaseMonster::HandleAnimEvent(pEvent); - } -} - -// -// TentacleStart -// -// void CTentacle :: Start( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -void CTentacle ::Start(void) -{ - SetThink(Cycle); - - if (!g_fFlySound) - { - EMIT_SOUND(ENT(pev), CHAN_BODY, "ambience/flies.wav", 1, ATTN_NORM); - g_fFlySound = TRUE; - // pev->nextthink = gpGlobals-> time + 0.1; - } - else if (!g_fSquirmSound) - { - EMIT_SOUND(ENT(pev), CHAN_BODY, "ambience/squirm2.wav", 1, ATTN_NORM); - g_fSquirmSound = TRUE; - } - - pev->nextthink = gpGlobals->time + 0.1; -} - -void CTentacle ::HitTouch(CBaseEntity *pOther) -{ - TraceResult tr = UTIL_GetGlobalTrace(); - - if (pOther->pev->modelindex == pev->modelindex) - return; - - if (m_flHitTime > gpGlobals->time) - return; - - // only look at the ones where the player hit me - if (tr.pHit == NULL || tr.pHit->v.modelindex != pev->modelindex) - return; - - if (tr.iHitgroup >= 3) - { - pOther->TakeDamage(pev, pev, m_iHitDmg, DMG_CRUSH); - // ALERT( at_console, "wack %3d : ", m_iHitDmg ); - } - else if (tr.iHitgroup != 0) - { - pOther->TakeDamage(pev, pev, 20, DMG_CRUSH); - // ALERT( at_console, "tap %3d : ", 20 ); - } - else - { - return; // Huh? - } - - m_flHitTime = gpGlobals->time + 0.5; - - // ALERT( at_console, "%s : ", STRING( tr.pHit->v.classname ) ); - - // ALERT( at_console, "%.0f : %s : %d\n", pev->angles.y, STRING( pOther->pev->classname ), tr.iHitgroup ); -} - -int CTentacle::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (flDamage > pev->health) - { - pev->health = 1; - } - else - { - pev->health -= flDamage; - } - return 1; -} - -void CTentacle ::Killed(entvars_t *pevAttacker, int iGib) -{ - m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; - return; -} - -class CTentacleMaw : public CBaseMonster -{ -public: - void Spawn(); - void Precache(); -}; - -LINK_ENTITY_TO_CLASS(monster_tentaclemaw, CTentacleMaw); - -// -// Tentacle Spawn -// -void CTentacleMaw ::Spawn() -{ - Precache(); - SET_MODEL(ENT(pev), "models/maw.mdl"); - UTIL_SetSize(pev, Vector(-32, -32, 0), Vector(32, 32, 64)); - - pev->solid = SOLID_NOT; - pev->movetype = MOVETYPE_STEP; - pev->effects = 0; - pev->health = 75; - pev->yaw_speed = 8; - pev->sequence = 0; - - pev->angles.x = 90; - // ResetSequenceInfo( ); -} - -void CTentacleMaw ::Precache() -{ - PRECACHE_MODEL("models/maw.mdl"); -} - -#endif \ No newline at end of file diff --git a/dlls/Half-life/tripmine.cpp b/dlls/Half-life/tripmine.cpp deleted file mode 100644 index 01000927..00000000 --- a/dlls/Half-life/tripmine.cpp +++ /dev/null @@ -1,519 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "nodes.h" -#include "player.h" -#include "effects.h" -#include "gamerules.h" - -#define TRIPMINE_PRIMARY_VOLUME 450 - -enum tripmine_e -{ - TRIPMINE_IDLE1 = 0, - TRIPMINE_IDLE2, - TRIPMINE_ARM1, - TRIPMINE_ARM2, - TRIPMINE_FIDGET, - TRIPMINE_HOLSTER, - TRIPMINE_DRAW, - TRIPMINE_WORLD, - TRIPMINE_GROUND, -}; - -class CTripmineGrenade : public CGrenade -{ - void Spawn(void); - void Precache(void); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - - static TYPEDESCRIPTION m_SaveData[]; - - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - - void EXPORT WarningThink(void); - void EXPORT PowerupThink(void); - void EXPORT BeamBreakThink(void); - void EXPORT DelayDeathThink(void); - void Killed(entvars_t *pevAttacker, int iGib); - - void MakeBeam(void); - void KillBeam(void); - - float m_flPowerUp; - Vector m_vecDir; - Vector m_vecEnd; - float m_flBeamLength; - - EHANDLE m_hOwner; - CBeam *m_pBeam; - Vector m_posOwner; - Vector m_angleOwner; - edict_t *m_pRealOwner; // tracelines don't hit PEV->OWNER, which means a player couldn't detonate his own trip mine, so we store the owner here. -}; - -LINK_ENTITY_TO_CLASS(monster_tripmine, CTripmineGrenade); - -TYPEDESCRIPTION CTripmineGrenade::m_SaveData[] = - { - DEFINE_FIELD(CTripmineGrenade, m_flPowerUp, FIELD_TIME), - DEFINE_FIELD(CTripmineGrenade, m_vecDir, FIELD_VECTOR), - DEFINE_FIELD(CTripmineGrenade, m_vecEnd, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CTripmineGrenade, m_flBeamLength, FIELD_FLOAT), - DEFINE_FIELD(CTripmineGrenade, m_hOwner, FIELD_EHANDLE), - DEFINE_FIELD(CTripmineGrenade, m_pBeam, FIELD_CLASSPTR), - DEFINE_FIELD(CTripmineGrenade, m_posOwner, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CTripmineGrenade, m_angleOwner, FIELD_VECTOR), - DEFINE_FIELD(CTripmineGrenade, m_pRealOwner, FIELD_EDICT), -}; - -IMPLEMENT_SAVERESTORE(CTripmineGrenade, CGrenade); - -void CTripmineGrenade ::Spawn(void) -{ - Precache(); - // motor - pev->movetype = MOVETYPE_FLY; - pev->solid = SOLID_NOT; - - SET_MODEL(ENT(pev), "models/v_tripmine.mdl"); - pev->frame = 0; - pev->body = 3; - pev->sequence = TRIPMINE_WORLD; - ResetSequenceInfo(); - pev->framerate = 0; - - UTIL_SetSize(pev, Vector(-8, -8, -8), Vector(8, 8, 8)); - UTIL_SetOrigin(pev, pev->origin); - - if (pev->spawnflags & 1) - { - // power up quickly - m_flPowerUp = gpGlobals->time + 1.0; - } - else - { - // power up in 2.5 seconds - m_flPowerUp = gpGlobals->time + 2.5; - } - - SetThink(PowerupThink); - pev->nextthink = gpGlobals->time + 0.2; - - pev->takedamage = DAMAGE_YES; - pev->dmg = gSkillData.plrDmgTripmine; - pev->health = 1; // don't let die normally - - if (pev->owner != NULL) - { - // play deploy sound - EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/mine_deploy.wav", 1.0, ATTN_NORM); - EMIT_SOUND(ENT(pev), CHAN_BODY, "weapons/mine_charge.wav", 0.2, ATTN_NORM); // chargeup - - m_pRealOwner = pev->owner; // see CTripmineGrenade for why. - } - - UTIL_MakeAimVectors(pev->angles); - - m_vecDir = gpGlobals->v_forward; - m_vecEnd = pev->origin + m_vecDir * 2048; -} - -void CTripmineGrenade ::Precache(void) -{ - PRECACHE_MODEL("models/v_tripmine.mdl"); - PRECACHE_SOUND("weapons/mine_deploy.wav"); - PRECACHE_SOUND("weapons/mine_activate.wav"); - PRECACHE_SOUND("weapons/mine_charge.wav"); -} - -void CTripmineGrenade ::WarningThink(void) -{ - // play warning sound - // EMIT_SOUND( ENT(pev), CHAN_VOICE, "buttons/Blip2.wav", 1.0, ATTN_NORM ); - - // set to power up - SetThink(PowerupThink); - pev->nextthink = gpGlobals->time + 1.0; -} - -void CTripmineGrenade ::PowerupThink(void) -{ - TraceResult tr; - - if (m_hOwner == NULL) - { - // find an owner - edict_t *oldowner = pev->owner; - pev->owner = NULL; - UTIL_TraceLine(pev->origin + m_vecDir * 8, pev->origin - m_vecDir * 32, dont_ignore_monsters, ENT(pev), &tr); - if (tr.fStartSolid || (oldowner && tr.pHit == oldowner)) - { - pev->owner = oldowner; - m_flPowerUp += 0.1; - pev->nextthink = gpGlobals->time + 0.1; - return; - } - if (tr.flFraction < 1.0) - { - pev->owner = tr.pHit; - m_hOwner = CBaseEntity::Instance(pev->owner); - m_posOwner = m_hOwner->pev->origin; - m_angleOwner = m_hOwner->pev->angles; - } - else - { - STOP_SOUND(ENT(pev), CHAN_VOICE, "weapons/mine_deploy.wav"); - STOP_SOUND(ENT(pev), CHAN_BODY, "weapons/mine_charge.wav"); - SetThink(SUB_Remove); - pev->nextthink = gpGlobals->time + 0.1; - ALERT(at_console, "WARNING:Tripmine at %.0f, %.0f, %.0f removed\n", pev->origin.x, pev->origin.y, pev->origin.z); - KillBeam(); - return; - } - } - else if (m_posOwner != m_hOwner->pev->origin || m_angleOwner != m_hOwner->pev->angles) - { - // disable - STOP_SOUND(ENT(pev), CHAN_VOICE, "weapons/mine_deploy.wav"); - STOP_SOUND(ENT(pev), CHAN_BODY, "weapons/mine_charge.wav"); - CBaseEntity *pMine = Create("weapon_tripmine", pev->origin + m_vecDir * 24, pev->angles); - pMine->pev->spawnflags |= SF_NORESPAWN; - - SetThink(SUB_Remove); - KillBeam(); - pev->nextthink = gpGlobals->time + 0.1; - return; - } - // ALERT( at_console, "%d %.0f %.0f %0.f\n", pev->owner, m_pOwner->pev->origin.x, m_pOwner->pev->origin.y, m_pOwner->pev->origin.z ); - - if (gpGlobals->time > m_flPowerUp) - { - // make solid - pev->solid = SOLID_BBOX; - UTIL_SetOrigin(pev, pev->origin); - - MakeBeam(); - - // play enabled sound - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "weapons/mine_activate.wav", 0.5, ATTN_NORM, 1.0, 75); - } - pev->nextthink = gpGlobals->time + 0.1; -} - -void CTripmineGrenade ::KillBeam(void) -{ - if (m_pBeam) - { - UTIL_Remove(m_pBeam); - m_pBeam = NULL; - } -} - -void CTripmineGrenade ::MakeBeam(void) -{ - TraceResult tr; - - // ALERT( at_console, "serverflags %f\n", gpGlobals->serverflags ); - - UTIL_TraceLine(pev->origin, m_vecEnd, dont_ignore_monsters, ENT(pev), &tr); - - m_flBeamLength = tr.flFraction; - - // set to follow laser spot - SetThink(BeamBreakThink); - pev->nextthink = gpGlobals->time + 0.1; - - Vector vecTmpEnd = pev->origin + m_vecDir * 2048 * m_flBeamLength; - - m_pBeam = CBeam::BeamCreate(g_pModelNameLaser, 10); - m_pBeam->PointEntInit(vecTmpEnd, entindex()); - m_pBeam->SetColor(0, 214, 198); - m_pBeam->SetScrollRate(255); - m_pBeam->SetBrightness(64); -} - -void CTripmineGrenade ::BeamBreakThink(void) -{ - BOOL bBlowup = 0; - - TraceResult tr; - - // HACKHACK Set simple box using this really nice global! - gpGlobals->trace_flags = FTRACE_SIMPLEBOX; - UTIL_TraceLine(pev->origin, m_vecEnd, dont_ignore_monsters, ENT(pev), &tr); - - // ALERT( at_console, "%f : %f\n", tr.flFraction, m_flBeamLength ); - - // respawn detect. - if (!m_pBeam) - { - MakeBeam(); - if (tr.pHit) - m_hOwner = CBaseEntity::Instance(tr.pHit); // reset owner too - } - - if (fabs(m_flBeamLength - tr.flFraction) > 0.001) - { - bBlowup = 1; - } - else - { - if (m_hOwner == NULL) - bBlowup = 1; - else if (m_posOwner != m_hOwner->pev->origin) - bBlowup = 1; - else if (m_angleOwner != m_hOwner->pev->angles) - bBlowup = 1; - } - - if (bBlowup) - { - // a bit of a hack, but all CGrenade code passes pev->owner along to make sure the proper player gets credit for the kill - // so we have to restore pev->owner from pRealOwner, because an entity's tracelines don't strike it's pev->owner which meant - // that a player couldn't trigger his own tripmine. Now that the mine is exploding, it's safe the restore the owner so the - // CGrenade code knows who the explosive really belongs to. - pev->owner = m_pRealOwner; - pev->health = 0; - Killed(VARS(pev->owner), GIB_NORMAL); - return; - } - - pev->nextthink = gpGlobals->time + 0.1; -} - -int CTripmineGrenade ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (gpGlobals->time < m_flPowerUp && flDamage < pev->health) - { - // disable - // Create( "weapon_tripmine", pev->origin + m_vecDir * 24, pev->angles ); - SetThink(SUB_Remove); - pev->nextthink = gpGlobals->time + 0.1; - KillBeam(); - return FALSE; - } - return CGrenade::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -void CTripmineGrenade::Killed(entvars_t *pevAttacker, int iGib) -{ - pev->takedamage = DAMAGE_NO; - - if (pevAttacker && (pevAttacker->flags & FL_CLIENT)) - { - // some client has destroyed this mine, he'll get credit for any kills - pev->owner = ENT(pevAttacker); - } - - SetThink(DelayDeathThink); - pev->nextthink = gpGlobals->time + RANDOM_FLOAT(0.1, 0.3); - - EMIT_SOUND(ENT(pev), CHAN_BODY, "common/null.wav", 0.5, ATTN_NORM); // shut off chargeup -} - -void CTripmineGrenade::DelayDeathThink(void) -{ - KillBeam(); - TraceResult tr; - UTIL_TraceLine(pev->origin + m_vecDir * 8, pev->origin - m_vecDir * 64, dont_ignore_monsters, ENT(pev), &tr); - - Explode(&tr, DMG_BLAST); -} - -class CTripmine : public CBasePlayerWeapon -{ -public: - void Spawn(void); - void Precache(void); - int iItemSlot(void) { return 5; } - int GetItemInfo(ItemInfo *p); - void SetObjectCollisionBox(void) - { - //!!!BUGBUG - fix the model! - pev->absmin = pev->origin + Vector(-16, -16, -5); - pev->absmax = pev->origin + Vector(16, 16, 28); - } - - void PrimaryAttack(void); - BOOL Deploy(void); - void Holster(int skiplocal = 0); - void WeaponIdle(void); -}; -LINK_ENTITY_TO_CLASS(weapon_tripmine, CTripmine); - -void CTripmine::Spawn() -{ - Precache(); - m_iId = WEAPON_TRIPMINE; - SET_MODEL(ENT(pev), "models/v_tripmine.mdl"); - pev->frame = 0; - pev->body = 3; - pev->sequence = TRIPMINE_GROUND; - // ResetSequenceInfo( ); - pev->framerate = 0; - - FallInit(); // get ready to fall down - - m_iDefaultAmmo = TRIPMINE_DEFAULT_GIVE; - - if (!g_pGameRules->IsDeathmatch()) - { - UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 28)); - } -} - -void CTripmine::Precache(void) -{ - PRECACHE_MODEL("models/v_tripmine.mdl"); - PRECACHE_MODEL("models/p_tripmine.mdl"); - UTIL_PrecacheOther("monster_tripmine"); -} - -int CTripmine::GetItemInfo(ItemInfo *p) -{ - p->pszName = STRING(pev->classname); - p->pszAmmo1 = "Trip Mine"; - p->iMaxAmmo1 = TRIPMINE_MAX_CARRY; - p->pszAmmo2 = NULL; - p->iMaxAmmo2 = -1; - p->iMaxClip = WEAPON_NOCLIP; - p->iSlot = 4; - p->iPosition = 2; - p->iId = m_iId = WEAPON_TRIPMINE; - p->iWeight = TRIPMINE_WEIGHT; - p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE; - - return 1; -} - -BOOL CTripmine::Deploy() -{ - pev->body = 0; - return DefaultDeploy("models/v_tripmine.mdl", "models/p_tripmine.mdl", TRIPMINE_DRAW, "trip"); -} - -void CTripmine::Holster(int skiplocal /* = 0 */) -{ - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - - if (!m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) - { - // out of mines - m_pPlayer->pev->weapons &= ~(1 << WEAPON_TRIPMINE); - SetThink(DestroyItem); - pev->nextthink = gpGlobals->time + 0.1; - } - - SendWeaponAnim(TRIPMINE_HOLSTER); - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM); -} - -void CTripmine::PrimaryAttack(void) -{ - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - return; - - UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle); - Vector vecSrc = m_pPlayer->GetGunPosition(); - Vector vecAiming = gpGlobals->v_forward; - - TraceResult tr; - - UTIL_TraceLine(vecSrc, vecSrc + vecAiming * 128, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr); - - if (tr.flFraction < 1.0) - { - // ALERT( at_console, "hit %f\n", tr.flFraction ); - - CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); - if (pEntity && !(pEntity->pev->flags & FL_CONVEYOR)) - { - Vector angles = UTIL_VecToAngles(tr.vecPlaneNormal); - - CBaseEntity *pEnt = CBaseEntity::Create("monster_tripmine", tr.vecEndPos + tr.vecPlaneNormal * 8, angles, m_pPlayer->edict()); - - CTripmineGrenade *pMine = (CTripmineGrenade *)pEnt; - - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; - - // player "shoot" animation - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0) - { - SendWeaponAnim(TRIPMINE_DRAW); - } - else - { - // no more mines! - RetireWeapon(); - return; - } - } - else - { - // ALERT( at_console, "no deploy\n" ); - } - } - else - { - } - - m_flNextPrimaryAttack = gpGlobals->time + 0.3; - m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10, 15); -} - -void CTripmine::WeaponIdle(void) -{ - if (m_flTimeWeaponIdle > gpGlobals->time) - return; - - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0) - { - SendWeaponAnim(TRIPMINE_DRAW); - } - else - { - RetireWeapon(); - return; - } - - int iAnim; - float flRand = RANDOM_FLOAT(0, 1); - if (flRand <= 0.25) - { - iAnim = TRIPMINE_IDLE1; - m_flTimeWeaponIdle = gpGlobals->time + 90.0 / 30.0; - } - else if (flRand <= 0.75) - { - iAnim = TRIPMINE_IDLE2; - m_flTimeWeaponIdle = gpGlobals->time + 60.0 / 30.0; - } - else - { - iAnim = TRIPMINE_FIDGET; - m_flTimeWeaponIdle = gpGlobals->time + 100.0 / 30.0; - } - - SendWeaponAnim(iAnim); -} diff --git a/dlls/Half-life/turret.cpp b/dlls/Half-life/turret.cpp deleted file mode 100644 index e7fd9c04..00000000 --- a/dlls/Half-life/turret.cpp +++ /dev/null @@ -1,1283 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -/* - -===== turret.cpp ======================================================== - -*/ - -// -// TODO: -// Take advantage of new monster fields like m_hEnemy and get rid of that OFFSET() stuff -// Revisit enemy validation stuff, maybe it's not necessary with the newest monster code -// - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "weapons.h" -#include "effects.h" - -extern Vector VecBModelOrigin(entvars_t *pevBModel); - -#define TURRET_SHOTS 2 -#define TURRET_RANGE (100 * 12) -#define TURRET_SPREAD Vector(0, 0, 0) -#define TURRET_TURNRATE 30 //angles per 0.1 second -#define TURRET_MAXWAIT 15 // seconds turret will stay active w/o a target -#define TURRET_MAXSPIN 5 // seconds turret barrel will spin w/o a target -#define TURRET_MACHINE_VOLUME 0.5 - -typedef enum -{ - TURRET_ANIM_NONE = 0, - TURRET_ANIM_FIRE, - TURRET_ANIM_SPIN, - TURRET_ANIM_DEPLOY, - TURRET_ANIM_RETIRE, - TURRET_ANIM_DIE, -} TURRET_ANIM; - -class CBaseTurret : public CBaseMonster -{ -public: - void Spawn(void); - virtual void Precache(void); - void KeyValue(KeyValueData *pkvd); - void EXPORT TurretUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - - virtual void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); - virtual int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - virtual int Classify(void); - - int BloodColor(void) { return DONT_BLEED; } - void GibMonster(void) {} // UNDONE: Throw turret gibs? - - // Think functions - - void EXPORT ActiveThink(void); - void EXPORT SearchThink(void); - void EXPORT AutoSearchThink(void); - void EXPORT TurretDeath(void); - - virtual void EXPORT SpinDownCall(void) { m_iSpin = 0; } - virtual void EXPORT SpinUpCall(void) { m_iSpin = 1; } - - // void SpinDown(void); - // float EXPORT SpinDownCall( void ) { return SpinDown(); } - - // virtual float SpinDown(void) { return 0;} - // virtual float Retire(void) { return 0;} - - void EXPORT Deploy(void); - void EXPORT Retire(void); - - void EXPORT Initialize(void); - - virtual void Ping(void); - virtual void EyeOn(void); - virtual void EyeOff(void); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - - static TYPEDESCRIPTION m_SaveData[]; - - // other functions - void SetTurretAnim(TURRET_ANIM anim); - int MoveTurret(void); - virtual void Shoot(Vector &vecSrc, Vector &vecDirToEnemy){}; - - float m_flMaxSpin; // Max time to spin the barrel w/o a target - int m_iSpin; - - CSprite *m_pEyeGlow; - int m_eyeBrightness; - - int m_iDeployHeight; - int m_iRetractHeight; - int m_iMinPitch; - - int m_iBaseTurnRate; // angles per second - float m_fTurnRate; // actual turn rate - int m_iOrientation; // 0 = floor, 1 = Ceiling - int m_iOn; - int m_fBeserk; // Sometimes this bitch will just freak out - int m_iAutoStart; // true if the turret auto deploys when a target - // enters its range - - Vector m_vecLastSight; - float m_flLastSight; // Last time we saw a target - float m_flMaxWait; // Max time to seach w/o a target - int m_iSearchSpeed; // Not Used! - - // movement - float m_flStartYaw; - Vector m_vecCurAngles; - Vector m_vecGoalAngles; - - float m_flPingTime; // Time until the next ping, used when searching - float m_flSpinUpTime; // Amount of time until the barrel should spin down when searching -}; - -TYPEDESCRIPTION CBaseTurret::m_SaveData[] = - { - DEFINE_FIELD(CBaseTurret, m_flMaxSpin, FIELD_FLOAT), - DEFINE_FIELD(CBaseTurret, m_iSpin, FIELD_INTEGER), - - DEFINE_FIELD(CBaseTurret, m_pEyeGlow, FIELD_CLASSPTR), - DEFINE_FIELD(CBaseTurret, m_eyeBrightness, FIELD_INTEGER), - DEFINE_FIELD(CBaseTurret, m_iDeployHeight, FIELD_INTEGER), - DEFINE_FIELD(CBaseTurret, m_iRetractHeight, FIELD_INTEGER), - DEFINE_FIELD(CBaseTurret, m_iMinPitch, FIELD_INTEGER), - - DEFINE_FIELD(CBaseTurret, m_iBaseTurnRate, FIELD_INTEGER), - DEFINE_FIELD(CBaseTurret, m_fTurnRate, FIELD_FLOAT), - DEFINE_FIELD(CBaseTurret, m_iOrientation, FIELD_INTEGER), - DEFINE_FIELD(CBaseTurret, m_iOn, FIELD_INTEGER), - DEFINE_FIELD(CBaseTurret, m_fBeserk, FIELD_INTEGER), - DEFINE_FIELD(CBaseTurret, m_iAutoStart, FIELD_INTEGER), - - DEFINE_FIELD(CBaseTurret, m_vecLastSight, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CBaseTurret, m_flLastSight, FIELD_TIME), - DEFINE_FIELD(CBaseTurret, m_flMaxWait, FIELD_FLOAT), - DEFINE_FIELD(CBaseTurret, m_iSearchSpeed, FIELD_INTEGER), - - DEFINE_FIELD(CBaseTurret, m_flStartYaw, FIELD_FLOAT), - DEFINE_FIELD(CBaseTurret, m_vecCurAngles, FIELD_VECTOR), - DEFINE_FIELD(CBaseTurret, m_vecGoalAngles, FIELD_VECTOR), - - DEFINE_FIELD(CBaseTurret, m_flPingTime, FIELD_TIME), - DEFINE_FIELD(CBaseTurret, m_flSpinUpTime, FIELD_TIME), -}; - -IMPLEMENT_SAVERESTORE(CBaseTurret, CBaseMonster); - -class CTurret : public CBaseTurret -{ -public: - void Spawn(void); - void Precache(void); - // Think functions - void SpinUpCall(void); - void SpinDownCall(void); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - - static TYPEDESCRIPTION m_SaveData[]; - - // other functions - void Shoot(Vector &vecSrc, Vector &vecDirToEnemy); - -private: - int m_iStartSpin; -}; -TYPEDESCRIPTION CTurret::m_SaveData[] = - { - DEFINE_FIELD(CTurret, m_iStartSpin, FIELD_INTEGER), -}; - -IMPLEMENT_SAVERESTORE(CTurret, CBaseTurret); - -class CMiniTurret : public CBaseTurret -{ -public: - void Spawn(); - void Precache(void); - // other functions - void Shoot(Vector &vecSrc, Vector &vecDirToEnemy); -}; - -LINK_ENTITY_TO_CLASS(monster_turret, CTurret); -LINK_ENTITY_TO_CLASS(monster_miniturret, CMiniTurret); - -void CBaseTurret::KeyValue(KeyValueData *pkvd) -{ - if (FStrEq(pkvd->szKeyName, "maxsleep")) - { - m_flMaxWait = atof(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "orientation")) - { - m_iOrientation = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "searchspeed")) - { - m_iSearchSpeed = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "turnrate")) - { - m_iBaseTurnRate = atoi(pkvd->szValue); - pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "style") || - FStrEq(pkvd->szKeyName, "height") || - FStrEq(pkvd->szKeyName, "value1") || - FStrEq(pkvd->szKeyName, "value2") || - FStrEq(pkvd->szKeyName, "value3")) - pkvd->fHandled = TRUE; - else - CBaseMonster::KeyValue(pkvd); -} - -void CBaseTurret::Spawn() -{ - Precache(); - pev->nextthink = gpGlobals->time + 1; - pev->movetype = MOVETYPE_FLY; - pev->sequence = 0; - pev->frame = 0; - pev->solid = SOLID_SLIDEBOX; - pev->takedamage = DAMAGE_AIM; - - SetBits(pev->flags, FL_MONSTER); - SetUse(TurretUse); - - if ((pev->spawnflags & SF_MONSTER_TURRET_AUTOACTIVATE) && !(pev->spawnflags & SF_MONSTER_TURRET_STARTINACTIVE)) - { - m_iAutoStart = TRUE; - } - - ResetSequenceInfo(); - SetBoneController(0, 0); - SetBoneController(1, 0); - m_flFieldOfView = VIEW_FIELD_FULL; - // m_flSightRange = TURRET_RANGE; -} - -void CBaseTurret::Precache() -{ - PRECACHE_SOUND("turret/tu_fire1.wav"); - PRECACHE_SOUND("turret/tu_ping.wav"); - PRECACHE_SOUND("turret/tu_active2.wav"); - PRECACHE_SOUND("turret/tu_die.wav"); - PRECACHE_SOUND("turret/tu_die2.wav"); - PRECACHE_SOUND("turret/tu_die3.wav"); - // PRECACHE_SOUND ("turret/tu_retract.wav"); // just use deploy sound to save memory - PRECACHE_SOUND("turret/tu_deploy.wav"); - PRECACHE_SOUND("turret/tu_spinup.wav"); - PRECACHE_SOUND("turret/tu_spindown.wav"); - PRECACHE_SOUND("turret/tu_search.wav"); - PRECACHE_SOUND("turret/tu_alert.wav"); -} - -#define TURRET_GLOW_SPRITE "sprites/flare3.spr" - -void CTurret::Spawn() -{ - Precache(); - SET_MODEL(ENT(pev), "models/turret.mdl"); - pev->health = gSkillData.turretHealth; - m_HackedGunPos = Vector(0, 0, 12.75); - m_flMaxSpin = TURRET_MAXSPIN; - pev->view_ofs.z = 12.75; - - CBaseTurret::Spawn(); - - m_iRetractHeight = 16; - m_iDeployHeight = 32; - m_iMinPitch = -15; - UTIL_SetSize(pev, Vector(-32, -32, -m_iRetractHeight), Vector(32, 32, m_iRetractHeight)); - - SetThink(Initialize); - - m_pEyeGlow = CSprite::SpriteCreate(TURRET_GLOW_SPRITE, pev->origin, FALSE); - m_pEyeGlow->SetTransparency(kRenderGlow, 255, 0, 0, 0, kRenderFxNoDissipation); - m_pEyeGlow->SetAttachment(edict(), 2); - m_eyeBrightness = 0; - - pev->nextthink = gpGlobals->time + 0.3; -} - -void CTurret::Precache() -{ - CBaseTurret::Precache(); - PRECACHE_MODEL("models/turret.mdl"); - PRECACHE_MODEL(TURRET_GLOW_SPRITE); -} - -void CMiniTurret::Spawn() -{ - Precache(); - SET_MODEL(ENT(pev), "models/miniturret.mdl"); - pev->health = gSkillData.miniturretHealth; - m_HackedGunPos = Vector(0, 0, 12.75); - m_flMaxSpin = 0; - pev->view_ofs.z = 12.75; - - CBaseTurret::Spawn(); - m_iRetractHeight = 16; - m_iDeployHeight = 32; - m_iMinPitch = -15; - UTIL_SetSize(pev, Vector(-16, -16, -m_iRetractHeight), Vector(16, 16, m_iRetractHeight)); - - SetThink(Initialize); - pev->nextthink = gpGlobals->time + 0.3; -} - -void CMiniTurret::Precache() -{ - CBaseTurret::Precache(); - PRECACHE_MODEL("models/miniturret.mdl"); - PRECACHE_SOUND("weapons/hks1.wav"); - PRECACHE_SOUND("weapons/hks2.wav"); - PRECACHE_SOUND("weapons/hks3.wav"); -} - -void CBaseTurret::Initialize(void) -{ - m_iOn = 0; - m_fBeserk = 0; - m_iSpin = 0; - - SetBoneController(0, 0); - SetBoneController(1, 0); - - if (m_iBaseTurnRate == 0) - m_iBaseTurnRate = TURRET_TURNRATE; - if (m_flMaxWait == 0) - m_flMaxWait = TURRET_MAXWAIT; - m_flStartYaw = pev->angles.y; - if (m_iOrientation == 1) - { - pev->idealpitch = 180; - pev->angles.x = 180; - pev->view_ofs.z = -pev->view_ofs.z; - pev->effects |= EF_INVLIGHT; - pev->angles.y = pev->angles.y + 180; - if (pev->angles.y > 360) - pev->angles.y = pev->angles.y - 360; - } - - m_vecGoalAngles.x = 0; - - if (m_iAutoStart) - { - m_flLastSight = gpGlobals->time + m_flMaxWait; - SetThink(AutoSearchThink); - pev->nextthink = gpGlobals->time + .1; - } - else - SetThink(SUB_DoNothing); -} - -void CBaseTurret::TurretUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if (!ShouldToggle(useType, m_iOn)) - return; - - if (m_iOn) - { - m_hEnemy = NULL; - pev->nextthink = gpGlobals->time + 0.1; - m_iAutoStart = FALSE; // switching off a turret disables autostart - //!!!! this should spin down first!!BUGBUG - SetThink(Retire); - } - else - { - pev->nextthink = gpGlobals->time + 0.1; // turn on delay - - // if the turret is flagged as an autoactivate turret, re-enable it's ability open self. - if (pev->spawnflags & SF_MONSTER_TURRET_AUTOACTIVATE) - { - m_iAutoStart = TRUE; - } - - SetThink(Deploy); - } -} - -void CBaseTurret::Ping(void) -{ - // make the pinging noise every second while searching - if (m_flPingTime == 0) - m_flPingTime = gpGlobals->time + 1; - else if (m_flPingTime <= gpGlobals->time) - { - m_flPingTime = gpGlobals->time + 1; - EMIT_SOUND(ENT(pev), CHAN_ITEM, "turret/tu_ping.wav", 1, ATTN_NORM); - EyeOn(); - } - else if (m_eyeBrightness > 0) - { - EyeOff(); - } -} - -void CBaseTurret::EyeOn() -{ - if (m_pEyeGlow) - { - if (m_eyeBrightness != 255) - { - m_eyeBrightness = 255; - } - m_pEyeGlow->SetBrightness(m_eyeBrightness); - } -} - -void CBaseTurret::EyeOff() -{ - if (m_pEyeGlow) - { - if (m_eyeBrightness > 0) - { - m_eyeBrightness = max(0, m_eyeBrightness - 30); - m_pEyeGlow->SetBrightness(m_eyeBrightness); - } - } -} - -void CBaseTurret::ActiveThink(void) -{ - int fAttack = 0; - Vector vecDirToEnemy; - - pev->nextthink = gpGlobals->time + 0.1; - StudioFrameAdvance(); - - if ((!m_iOn) || (m_hEnemy == NULL)) - { - m_hEnemy = NULL; - m_flLastSight = gpGlobals->time + m_flMaxWait; - SetThink(SearchThink); - return; - } - - // if it's dead, look for something new - if (!m_hEnemy->IsAlive()) - { - if (!m_flLastSight) - { - m_flLastSight = gpGlobals->time + 0.5; // continue-shooting timeout - } - else - { - if (gpGlobals->time > m_flLastSight) - { - m_hEnemy = NULL; - m_flLastSight = gpGlobals->time + m_flMaxWait; - SetThink(SearchThink); - return; - } - } - } - - Vector vecMid = pev->origin + pev->view_ofs; - Vector vecMidEnemy = m_hEnemy->BodyTarget(vecMid); - - // Look for our current enemy - int fEnemyVisible = FBoxVisible(pev, m_hEnemy->pev, vecMidEnemy); - - vecDirToEnemy = vecMidEnemy - vecMid; // calculate dir and dist to enemy - float flDistToEnemy = vecDirToEnemy.Length(); - - Vector vec = UTIL_VecToAngles(vecMidEnemy - vecMid); - - // Current enmey is not visible. - if (!fEnemyVisible || (flDistToEnemy > TURRET_RANGE)) - { - if (!m_flLastSight) - m_flLastSight = gpGlobals->time + 0.5; - else - { - // Should we look for a new target? - if (gpGlobals->time > m_flLastSight) - { - m_hEnemy = NULL; - m_flLastSight = gpGlobals->time + m_flMaxWait; - SetThink(SearchThink); - return; - } - } - fEnemyVisible = 0; - } - else - { - m_vecLastSight = vecMidEnemy; - } - - UTIL_MakeAimVectors(m_vecCurAngles); - - /* - ALERT( at_console, "%.0f %.0f : %.2f %.2f %.2f\n", - m_vecCurAngles.x, m_vecCurAngles.y, - gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_forward.z ); - */ - - Vector vecLOS = vecDirToEnemy; //vecMid - m_vecLastSight; - vecLOS = vecLOS.Normalize(); - - // Is the Gun looking at the target - if (DotProduct(vecLOS, gpGlobals->v_forward) <= 0.866) // 30 degree slop - fAttack = FALSE; - else - fAttack = TRUE; - - // fire the gun - if (m_iSpin && ((fAttack) || (m_fBeserk))) - { - Vector vecSrc, vecAng; - GetAttachment(0, vecSrc, vecAng); - SetTurretAnim(TURRET_ANIM_FIRE); - Shoot(vecSrc, gpGlobals->v_forward); - } - else - { - SetTurretAnim(TURRET_ANIM_SPIN); - } - - //move the gun - if (m_fBeserk) - { - if (RANDOM_LONG(0, 9) == 0) - { - m_vecGoalAngles.y = RANDOM_FLOAT(0, 360); - m_vecGoalAngles.x = RANDOM_FLOAT(0, 90) - 90 * m_iOrientation; - TakeDamage(pev, pev, 1, DMG_GENERIC); // don't beserk forever - return; - } - } - else if (fEnemyVisible) - { - if (vec.y > 360) - vec.y -= 360; - - if (vec.y < 0) - vec.y += 360; - - //ALERT(at_console, "[%.2f]", vec.x); - - if (vec.x < -180) - vec.x += 360; - - if (vec.x > 180) - vec.x -= 360; - - // now all numbers should be in [1...360] - // pin to turret limitations to [-90...15] - - if (m_iOrientation == 0) - { - if (vec.x > 90) - vec.x = 90; - else if (vec.x < m_iMinPitch) - vec.x = m_iMinPitch; - } - else - { - if (vec.x < -90) - vec.x = -90; - else if (vec.x > -m_iMinPitch) - vec.x = -m_iMinPitch; - } - - // ALERT(at_console, "->[%.2f]\n", vec.x); - - m_vecGoalAngles.y = vec.y; - m_vecGoalAngles.x = vec.x; - } - - SpinUpCall(); - MoveTurret(); -} - -void CTurret::Shoot(Vector &vecSrc, Vector &vecDirToEnemy) -{ - FireBullets(1, vecSrc, vecDirToEnemy, TURRET_SPREAD, TURRET_RANGE, BULLET_MONSTER_12MM, 1); - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "turret/tu_fire1.wav", 1, 0.6); - pev->effects = pev->effects | EF_MUZZLEFLASH; -} - -void CMiniTurret::Shoot(Vector &vecSrc, Vector &vecDirToEnemy) -{ - FireBullets(1, vecSrc, vecDirToEnemy, TURRET_SPREAD, TURRET_RANGE, BULLET_MONSTER_9MM, 1); - - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/hks1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/hks2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/hks3.wav", 1, ATTN_NORM); - break; - } - pev->effects = pev->effects | EF_MUZZLEFLASH; -} - -void CBaseTurret::Deploy(void) -{ - pev->nextthink = gpGlobals->time + 0.1; - StudioFrameAdvance(); - - if (pev->sequence != TURRET_ANIM_DEPLOY) - { - m_iOn = 1; - SetTurretAnim(TURRET_ANIM_DEPLOY); - EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_deploy.wav", TURRET_MACHINE_VOLUME, ATTN_NORM); - SUB_UseTargets(this, USE_ON, 0); - } - - if (m_fSequenceFinished) - { - pev->maxs.z = m_iDeployHeight; - pev->mins.z = -m_iDeployHeight; - UTIL_SetSize(pev, pev->mins, pev->maxs); - - m_vecCurAngles.x = 0; - - if (m_iOrientation == 1) - { - m_vecCurAngles.y = UTIL_AngleMod(pev->angles.y + 180); - } - else - { - m_vecCurAngles.y = UTIL_AngleMod(pev->angles.y); - } - - SetTurretAnim(TURRET_ANIM_SPIN); - pev->framerate = 0; - SetThink(SearchThink); - } - - m_flLastSight = gpGlobals->time + m_flMaxWait; -} - -void CBaseTurret::Retire(void) -{ - // make the turret level - m_vecGoalAngles.x = 0; - m_vecGoalAngles.y = m_flStartYaw; - - pev->nextthink = gpGlobals->time + 0.1; - - StudioFrameAdvance(); - - EyeOff(); - - if (!MoveTurret()) - { - if (m_iSpin) - { - SpinDownCall(); - } - else if (pev->sequence != TURRET_ANIM_RETIRE) - { - SetTurretAnim(TURRET_ANIM_RETIRE); - EMIT_SOUND_DYN(ENT(pev), CHAN_BODY, "turret/tu_deploy.wav", TURRET_MACHINE_VOLUME, ATTN_NORM, 0, 120); - SUB_UseTargets(this, USE_OFF, 0); - } - else if (m_fSequenceFinished) - { - m_iOn = 0; - m_flLastSight = 0; - SetTurretAnim(TURRET_ANIM_NONE); - pev->maxs.z = m_iRetractHeight; - pev->mins.z = -m_iRetractHeight; - UTIL_SetSize(pev, pev->mins, pev->maxs); - if (m_iAutoStart) - { - SetThink(AutoSearchThink); - pev->nextthink = gpGlobals->time + .1; - } - else - SetThink(SUB_DoNothing); - } - } - else - { - SetTurretAnim(TURRET_ANIM_SPIN); - } -} - -void CTurret::SpinUpCall(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - // Are we already spun up? If not start the two stage process. - if (!m_iSpin) - { - SetTurretAnim(TURRET_ANIM_SPIN); - // for the first pass, spin up the the barrel - if (!m_iStartSpin) - { - pev->nextthink = gpGlobals->time + 1.0; // spinup delay - EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_spinup.wav", TURRET_MACHINE_VOLUME, ATTN_NORM); - m_iStartSpin = 1; - pev->framerate = 0.1; - } - // after the barrel is spun up, turn on the hum - else if (pev->framerate >= 1.0) - { - pev->nextthink = gpGlobals->time + 0.1; // retarget delay - EMIT_SOUND(ENT(pev), CHAN_STATIC, "turret/tu_active2.wav", TURRET_MACHINE_VOLUME, ATTN_NORM); - SetThink(ActiveThink); - m_iStartSpin = 0; - m_iSpin = 1; - } - else - { - pev->framerate += 0.075; - } - } - - if (m_iSpin) - { - SetThink(ActiveThink); - } -} - -void CTurret::SpinDownCall(void) -{ - if (m_iSpin) - { - SetTurretAnim(TURRET_ANIM_SPIN); - if (pev->framerate == 1.0) - { - EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "turret/tu_active2.wav", 0, 0, SND_STOP, 100); - EMIT_SOUND(ENT(pev), CHAN_ITEM, "turret/tu_spindown.wav", TURRET_MACHINE_VOLUME, ATTN_NORM); - } - pev->framerate -= 0.02; - if (pev->framerate <= 0) - { - pev->framerate = 0; - m_iSpin = 0; - } - } -} - -void CBaseTurret::SetTurretAnim(TURRET_ANIM anim) -{ - if (pev->sequence != anim) - { - switch (anim) - { - case TURRET_ANIM_FIRE: - case TURRET_ANIM_SPIN: - if (pev->sequence != TURRET_ANIM_FIRE && pev->sequence != TURRET_ANIM_SPIN) - { - pev->frame = 0; - } - break; - default: - pev->frame = 0; - break; - } - - pev->sequence = anim; - ResetSequenceInfo(); - - switch (anim) - { - case TURRET_ANIM_RETIRE: - pev->frame = 255; - pev->framerate = -1.0; - break; - case TURRET_ANIM_DIE: - pev->framerate = 1.0; - break; - } - //ALERT(at_console, "Turret anim #%d\n", anim); - } -} - -// -// This search function will sit with the turret deployed and look for a new target. -// After a set amount of time, the barrel will spin down. After m_flMaxWait, the turret will -// retact. -// -void CBaseTurret::SearchThink(void) -{ - // ensure rethink - SetTurretAnim(TURRET_ANIM_SPIN); - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - if (m_flSpinUpTime == 0 && m_flMaxSpin) - m_flSpinUpTime = gpGlobals->time + m_flMaxSpin; - - Ping(); - - // If we have a target and we're still healthy - if (m_hEnemy != NULL) - { - if (!m_hEnemy->IsAlive()) - m_hEnemy = NULL; // Dead enemy forces a search for new one - } - - // Acquire Target - if (m_hEnemy == NULL) - { - Look(TURRET_RANGE); - m_hEnemy = BestVisibleEnemy(); - } - - // If we've found a target, spin up the barrel and start to attack - if (m_hEnemy != NULL) - { - m_flLastSight = 0; - m_flSpinUpTime = 0; - SetThink(ActiveThink); - } - else - { - // Are we out of time, do we need to retract? - if (gpGlobals->time > m_flLastSight) - { - //Before we retrace, make sure that we are spun down. - m_flLastSight = 0; - m_flSpinUpTime = 0; - SetThink(Retire); - } - // should we stop the spin? - else if ((m_flSpinUpTime) && (gpGlobals->time > m_flSpinUpTime)) - { - SpinDownCall(); - } - - // generic hunt for new victims - m_vecGoalAngles.y = (m_vecGoalAngles.y + 0.1 * m_fTurnRate); - if (m_vecGoalAngles.y >= 360) - m_vecGoalAngles.y -= 360; - MoveTurret(); - } -} - -// -// This think function will deploy the turret when something comes into range. This is for -// automatically activated turrets. -// -void CBaseTurret::AutoSearchThink(void) -{ - // ensure rethink - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.3; - - // If we have a target and we're still healthy - - if (m_hEnemy != NULL) - { - if (!m_hEnemy->IsAlive()) - m_hEnemy = NULL; // Dead enemy forces a search for new one - } - - // Acquire Target - - if (m_hEnemy == NULL) - { - Look(TURRET_RANGE); - m_hEnemy = BestVisibleEnemy(); - } - - if (m_hEnemy != NULL) - { - SetThink(Deploy); - EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_alert.wav", TURRET_MACHINE_VOLUME, ATTN_NORM); - } -} - -void CBaseTurret ::TurretDeath(void) -{ - BOOL iActive = FALSE; - - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - if (pev->deadflag != DEAD_DEAD) - { - pev->deadflag = DEAD_DEAD; - - float flRndSound = RANDOM_FLOAT(0, 1); - - if (flRndSound <= 0.33) - EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_die.wav", 1.0, ATTN_NORM); - else if (flRndSound <= 0.66) - EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_die2.wav", 1.0, ATTN_NORM); - else - EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_die3.wav", 1.0, ATTN_NORM); - - EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "turret/tu_active2.wav", 0, 0, SND_STOP, 100); - - if (m_iOrientation == 0) - m_vecGoalAngles.x = -15; - else - m_vecGoalAngles.x = -90; - - SetTurretAnim(TURRET_ANIM_DIE); - - EyeOn(); - } - - EyeOff(); - - if (pev->dmgtime + RANDOM_FLOAT(0, 2) > gpGlobals->time) - { - // lots of smoke - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(RANDOM_FLOAT(pev->absmin.x, pev->absmax.x)); - WRITE_COORD(RANDOM_FLOAT(pev->absmin.y, pev->absmax.y)); - WRITE_COORD(pev->origin.z - m_iOrientation * 64); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(25); // scale * 10 - WRITE_BYTE(10 - m_iOrientation * 5); // framerate - MESSAGE_END(); - } - - if (pev->dmgtime + RANDOM_FLOAT(0, 5) > gpGlobals->time) - { - Vector vecSrc = Vector(RANDOM_FLOAT(pev->absmin.x, pev->absmax.x), RANDOM_FLOAT(pev->absmin.y, pev->absmax.y), 0); - if (m_iOrientation == 0) - vecSrc = vecSrc + Vector(0, 0, RANDOM_FLOAT(pev->origin.z, pev->absmax.z)); - else - vecSrc = vecSrc + Vector(0, 0, RANDOM_FLOAT(pev->absmin.z, pev->origin.z)); - - UTIL_Sparks(vecSrc); - } - - if (m_fSequenceFinished && !MoveTurret() && pev->dmgtime + 5 < gpGlobals->time) - { - pev->framerate = 0; - SetThink(NULL); - } -} - -void CBaseTurret ::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) -{ - if (ptr->iHitgroup == 10) - { - // hit armor - if (pev->dmgtime != gpGlobals->time || (RANDOM_LONG(0, 10) < 1)) - { - UTIL_Ricochet(ptr->vecEndPos, RANDOM_FLOAT(1, 2)); - pev->dmgtime = gpGlobals->time; - } - - flDamage = 0.1; // don't hurt the monster much, but allow bits_COND_LIGHT_DAMAGE to be generated - } - - if (!pev->takedamage) - return; - - AddMultiDamage(pevAttacker, this, flDamage, bitsDamageType); -} - -// take damage. bitsDamageType indicates type of damage sustained, ie: DMG_BULLET - -int CBaseTurret::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (!pev->takedamage) - return 0; - - if (!m_iOn) - flDamage /= 10.0; - - pev->health -= flDamage; - if (pev->health <= 0) - { - pev->health = 0; - pev->takedamage = DAMAGE_NO; - pev->dmgtime = gpGlobals->time; - - ClearBits(pev->flags, FL_MONSTER); // why are they set in the first place??? - - SetUse(NULL); - SetThink(TurretDeath); - SUB_UseTargets(this, USE_ON, 0); // wake up others - pev->nextthink = gpGlobals->time + 0.1; - - return 0; - } - - if (pev->health <= 10) - { - if (m_iOn && (1 || RANDOM_LONG(0, 0x7FFF) > 800)) - { - m_fBeserk = 1; - SetThink(SearchThink); - } - } - - return 1; -} - -int CBaseTurret::MoveTurret(void) -{ - int state = 0; - // any x movement? - - if (m_vecCurAngles.x != m_vecGoalAngles.x) - { - float flDir = m_vecGoalAngles.x > m_vecCurAngles.x ? 1 : -1; - - m_vecCurAngles.x += 0.1 * m_fTurnRate * flDir; - - // if we started below the goal, and now we're past, peg to goal - if (flDir == 1) - { - if (m_vecCurAngles.x > m_vecGoalAngles.x) - m_vecCurAngles.x = m_vecGoalAngles.x; - } - else - { - if (m_vecCurAngles.x < m_vecGoalAngles.x) - m_vecCurAngles.x = m_vecGoalAngles.x; - } - - if (m_iOrientation == 0) - SetBoneController(1, -m_vecCurAngles.x); - else - SetBoneController(1, m_vecCurAngles.x); - state = 1; - } - - if (m_vecCurAngles.y != m_vecGoalAngles.y) - { - float flDir = m_vecGoalAngles.y > m_vecCurAngles.y ? 1 : -1; - float flDist = fabs(m_vecGoalAngles.y - m_vecCurAngles.y); - - if (flDist > 180) - { - flDist = 360 - flDist; - flDir = -flDir; - } - if (flDist > 30) - { - if (m_fTurnRate < m_iBaseTurnRate * 10) - { - m_fTurnRate += m_iBaseTurnRate; - } - } - else if (m_fTurnRate > 45) - { - m_fTurnRate -= m_iBaseTurnRate; - } - else - { - m_fTurnRate += m_iBaseTurnRate; - } - - m_vecCurAngles.y += 0.1 * m_fTurnRate * flDir; - - if (m_vecCurAngles.y < 0) - m_vecCurAngles.y += 360; - else if (m_vecCurAngles.y >= 360) - m_vecCurAngles.y -= 360; - - if (flDist < (0.05 * m_iBaseTurnRate)) - m_vecCurAngles.y = m_vecGoalAngles.y; - - //ALERT(at_console, "%.2f -> %.2f\n", m_vecCurAngles.y, y); - if (m_iOrientation == 0) - SetBoneController(0, m_vecCurAngles.y - pev->angles.y); - else - SetBoneController(0, pev->angles.y - 180 - m_vecCurAngles.y); - state = 1; - } - - if (!state) - m_fTurnRate = m_iBaseTurnRate; - - //ALERT(at_console, "(%.2f, %.2f)->(%.2f, %.2f)\n", m_vecCurAngles.x, - // m_vecCurAngles.y, m_vecGoalAngles.x, m_vecGoalAngles.y); - return state; -} - -// -// ID as a machine -// -int CBaseTurret::Classify(void) -{ - if (m_iOn || m_iAutoStart) - return CLASS_MACHINE; - return CLASS_NONE; -} - -//========================================================= -// Sentry gun - smallest turret, placed near grunt entrenchments -//========================================================= -class CSentry : public CBaseTurret -{ -public: - void Spawn(); - void Precache(void); - // other functions - void Shoot(Vector &vecSrc, Vector &vecDirToEnemy); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - void EXPORT SentryTouch(CBaseEntity *pOther); - void EXPORT SentryDeath(void); -}; - -LINK_ENTITY_TO_CLASS(monster_sentry, CSentry); - -void CSentry::Precache() -{ - CBaseTurret::Precache(); - PRECACHE_MODEL("models/sentry.mdl"); -} - -void CSentry::Spawn() -{ - Precache(); - SET_MODEL(ENT(pev), "models/sentry.mdl"); - pev->health = gSkillData.sentryHealth; - m_HackedGunPos = Vector(0, 0, 48); - pev->view_ofs.z = 48; - m_flMaxWait = 1E6; - m_flMaxSpin = 1E6; - - CBaseTurret::Spawn(); - m_iRetractHeight = 64; - m_iDeployHeight = 64; - m_iMinPitch = -60; - UTIL_SetSize(pev, Vector(-16, -16, -m_iRetractHeight), Vector(16, 16, m_iRetractHeight)); - - SetTouch(SentryTouch); - SetThink(Initialize); - pev->nextthink = gpGlobals->time + 0.3; -} - -void CSentry::Shoot(Vector &vecSrc, Vector &vecDirToEnemy) -{ - FireBullets(1, vecSrc, vecDirToEnemy, TURRET_SPREAD, TURRET_RANGE, BULLET_MONSTER_MP5, 1); - - switch (RANDOM_LONG(0, 2)) - { - case 0: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/hks1.wav", 1, ATTN_NORM); - break; - case 1: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/hks2.wav", 1, ATTN_NORM); - break; - case 2: - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/hks3.wav", 1, ATTN_NORM); - break; - } - pev->effects = pev->effects | EF_MUZZLEFLASH; -} - -int CSentry::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (!pev->takedamage) - return 0; - - if (!m_iOn) - { - SetThink(Deploy); - SetUse(NULL); - pev->nextthink = gpGlobals->time + 0.1; - } - - pev->health -= flDamage; - if (pev->health <= 0) - { - pev->health = 0; - pev->takedamage = DAMAGE_NO; - pev->dmgtime = gpGlobals->time; - - ClearBits(pev->flags, FL_MONSTER); // why are they set in the first place??? - - SetUse(NULL); - SetThink(SentryDeath); - SUB_UseTargets(this, USE_ON, 0); // wake up others - pev->nextthink = gpGlobals->time + 0.1; - - return 0; - } - - return 1; -} - -void CSentry::SentryTouch(CBaseEntity *pOther) -{ - if (pOther && (pOther->IsPlayer() || (pOther->pev->flags & FL_MONSTER))) - { - TakeDamage(pOther->pev, pOther->pev, 0, 0); - } -} - -void CSentry ::SentryDeath(void) -{ - BOOL iActive = FALSE; - - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - if (pev->deadflag != DEAD_DEAD) - { - pev->deadflag = DEAD_DEAD; - - float flRndSound = RANDOM_FLOAT(0, 1); - - if (flRndSound <= 0.33) - EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_die.wav", 1.0, ATTN_NORM); - else if (flRndSound <= 0.66) - EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_die2.wav", 1.0, ATTN_NORM); - else - EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_die3.wav", 1.0, ATTN_NORM); - - EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "turret/tu_active2.wav", 0, 0, SND_STOP, 100); - - SetBoneController(0, 0); - SetBoneController(1, 0); - - SetTurretAnim(TURRET_ANIM_DIE); - - pev->solid = SOLID_NOT; - pev->angles.y = UTIL_AngleMod(pev->angles.y + RANDOM_LONG(0, 2) * 120); - - EyeOn(); - } - - EyeOff(); - - Vector vecSrc, vecAng; - GetAttachment(1, vecSrc, vecAng); - - if (pev->dmgtime + RANDOM_FLOAT(0, 2) > gpGlobals->time) - { - // lots of smoke - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - WRITE_BYTE(TE_SMOKE); - WRITE_COORD(vecSrc.x + RANDOM_FLOAT(-16, 16)); - WRITE_COORD(vecSrc.y + RANDOM_FLOAT(-16, 16)); - WRITE_COORD(vecSrc.z - 32); - WRITE_SHORT(g_sModelIndexSmoke); - WRITE_BYTE(15); // scale * 10 - WRITE_BYTE(8); // framerate - MESSAGE_END(); - } - - if (pev->dmgtime + RANDOM_FLOAT(0, 8) > gpGlobals->time) - { - UTIL_Sparks(vecSrc); - } - - if (m_fSequenceFinished && pev->dmgtime + 5 < gpGlobals->time) - { - pev->framerate = 0; - SetThink(NULL); - } -} diff --git a/dlls/Half-life/xen.cpp b/dlls/Half-life/xen.cpp deleted file mode 100644 index f644bb98..00000000 --- a/dlls/Half-life/xen.cpp +++ /dev/null @@ -1,563 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "animation.h" -#include "effects.h" - -#define XEN_PLANT_GLOW_SPRITE "sprites/flare3.spr" -#define XEN_PLANT_HIDE_TIME 5 - -class CActAnimating : public CBaseAnimating -{ -public: - void SetActivity(Activity act); - inline Activity GetActivity(void) { return m_Activity; } - - virtual int ObjectCaps(void) { return CBaseAnimating ::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - -private: - Activity m_Activity; -}; - -TYPEDESCRIPTION CActAnimating::m_SaveData[] = - { - DEFINE_FIELD(CActAnimating, m_Activity, FIELD_INTEGER), -}; - -IMPLEMENT_SAVERESTORE(CActAnimating, CBaseAnimating); - -void CActAnimating ::SetActivity(Activity act) -{ - int sequence = LookupActivity(act); - if (sequence != ACTIVITY_NOT_AVAILABLE) - { - pev->sequence = sequence; - m_Activity = act; - pev->frame = 0; - ResetSequenceInfo(); - } -} - -class CXenPLight : public CActAnimating -{ -public: - void Spawn(void); - void Precache(void); - void Touch(CBaseEntity *pOther); - void Think(void); - - void LightOn(void); - void LightOff(void); - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - -private: - CSprite *m_pGlow; -}; - -LINK_ENTITY_TO_CLASS(xen_plantlight, CXenPLight); - -TYPEDESCRIPTION CXenPLight::m_SaveData[] = - { - DEFINE_FIELD(CXenPLight, m_pGlow, FIELD_CLASSPTR), -}; - -IMPLEMENT_SAVERESTORE(CXenPLight, CActAnimating); - -void CXenPLight ::Spawn(void) -{ - Precache(); - - SET_MODEL(ENT(pev), "models/light.mdl"); - pev->movetype = MOVETYPE_NONE; - pev->solid = SOLID_TRIGGER; - - UTIL_SetSize(pev, Vector(-80, -80, 0), Vector(80, 80, 32)); - SetActivity(ACT_IDLE); - pev->nextthink = gpGlobals->time + 0.1; - pev->frame = RANDOM_FLOAT(0, 255); - - m_pGlow = CSprite::SpriteCreate(XEN_PLANT_GLOW_SPRITE, pev->origin + Vector(0, 0, (pev->mins.z + pev->maxs.z) * 0.5), FALSE); - m_pGlow->SetTransparency(kRenderGlow, pev->rendercolor.x, pev->rendercolor.y, pev->rendercolor.z, pev->renderamt, pev->renderfx); - m_pGlow->SetAttachment(edict(), 1); -} - -void CXenPLight ::Precache(void) -{ - PRECACHE_MODEL("models/light.mdl"); - PRECACHE_MODEL(XEN_PLANT_GLOW_SPRITE); -} - -void CXenPLight ::Think(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - - switch (GetActivity()) - { - case ACT_CROUCH: - if (m_fSequenceFinished) - { - SetActivity(ACT_CROUCHIDLE); - LightOff(); - } - break; - - case ACT_CROUCHIDLE: - if (gpGlobals->time > pev->dmgtime) - { - SetActivity(ACT_STAND); - LightOn(); - } - break; - - case ACT_STAND: - if (m_fSequenceFinished) - SetActivity(ACT_IDLE); - break; - - case ACT_IDLE: - default: - break; - } -} - -void CXenPLight ::Touch(CBaseEntity *pOther) -{ - if (pOther->IsPlayer()) - { - pev->dmgtime = gpGlobals->time + XEN_PLANT_HIDE_TIME; - if (GetActivity() == ACT_IDLE || GetActivity() == ACT_STAND) - { - SetActivity(ACT_CROUCH); - } - } -} - -void CXenPLight ::LightOn(void) -{ - SUB_UseTargets(this, USE_ON, 0); - if (m_pGlow) - m_pGlow->pev->effects &= ~EF_NODRAW; -} - -void CXenPLight ::LightOff(void) -{ - SUB_UseTargets(this, USE_OFF, 0); - if (m_pGlow) - m_pGlow->pev->effects |= EF_NODRAW; -} - -class CXenHair : public CActAnimating -{ -public: - void Spawn(void); - void Precache(void); - void Think(void); -}; - -LINK_ENTITY_TO_CLASS(xen_hair, CXenHair); - -#define SF_HAIR_SYNC 0x0001 - -void CXenHair::Spawn(void) -{ - Precache(); - SET_MODEL(edict(), "models/hair.mdl"); - UTIL_SetSize(pev, Vector(-4, -4, 0), Vector(4, 4, 32)); - pev->sequence = 0; - - if (!(pev->spawnflags & SF_HAIR_SYNC)) - { - pev->frame = RANDOM_FLOAT(0, 255); - pev->framerate = RANDOM_FLOAT(0.7, 1.4); - } - ResetSequenceInfo(); - - pev->solid = SOLID_NOT; - pev->movetype = MOVETYPE_NONE; - pev->nextthink = gpGlobals->time + RANDOM_FLOAT(0.1, 0.4); // Load balance these a bit -} - -void CXenHair::Think(void) -{ - StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.5; -} - -void CXenHair::Precache(void) -{ - PRECACHE_MODEL("models/hair.mdl"); -} - -class CXenTreeTrigger : public CBaseEntity -{ -public: - void Touch(CBaseEntity *pOther); - static CXenTreeTrigger *TriggerCreate(edict_t *pOwner, const Vector &position); -}; -LINK_ENTITY_TO_CLASS(xen_ttrigger, CXenTreeTrigger); - -CXenTreeTrigger *CXenTreeTrigger ::TriggerCreate(edict_t *pOwner, const Vector &position) -{ - CXenTreeTrigger *pTrigger = GetClassPtr((CXenTreeTrigger *)NULL); - pTrigger->pev->origin = position; - pTrigger->pev->classname = MAKE_STRING("xen_ttrigger"); - pTrigger->pev->solid = SOLID_TRIGGER; - pTrigger->pev->movetype = MOVETYPE_NONE; - pTrigger->pev->owner = pOwner; - - return pTrigger; -} - -void CXenTreeTrigger::Touch(CBaseEntity *pOther) -{ - if (pev->owner) - { - CBaseEntity *pEntity = CBaseEntity::Instance(pev->owner); - pEntity->Touch(pOther); - } -} - -#define TREE_AE_ATTACK 1 - -class CXenTree : public CActAnimating -{ -public: - void Spawn(void); - void Precache(void); - void Touch(CBaseEntity *pOther); - void Think(void); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) - { - Attack(); - return 0; - } - void HandleAnimEvent(MonsterEvent_t *pEvent); - void Attack(void); - int Classify(void) { return CLASS_BARNACLE; } - - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); - static TYPEDESCRIPTION m_SaveData[]; - - static const char *pAttackHitSounds[]; - static const char *pAttackMissSounds[]; - -private: - CXenTreeTrigger *m_pTrigger; -}; - -LINK_ENTITY_TO_CLASS(xen_tree, CXenTree); - -TYPEDESCRIPTION CXenTree::m_SaveData[] = - { - DEFINE_FIELD(CXenTree, m_pTrigger, FIELD_CLASSPTR), -}; - -IMPLEMENT_SAVERESTORE(CXenTree, CActAnimating); - -void CXenTree ::Spawn(void) -{ - Precache(); - - SET_MODEL(ENT(pev), "models/tree.mdl"); - pev->movetype = MOVETYPE_NONE; - pev->solid = SOLID_BBOX; - - pev->takedamage = DAMAGE_YES; - - UTIL_SetSize(pev, Vector(-30, -30, 0), Vector(30, 30, 188)); - SetActivity(ACT_IDLE); - pev->nextthink = gpGlobals->time + 0.1; - pev->frame = RANDOM_FLOAT(0, 255); - pev->framerate = RANDOM_FLOAT(0.7, 1.4); - - Vector triggerPosition; - UTIL_MakeVectorsPrivate(pev->angles, triggerPosition, NULL, NULL); - triggerPosition = pev->origin + (triggerPosition * 64); - // Create the trigger - m_pTrigger = CXenTreeTrigger::TriggerCreate(edict(), triggerPosition); - UTIL_SetSize(m_pTrigger->pev, Vector(-24, -24, 0), Vector(24, 24, 128)); -} - -const char *CXenTree::pAttackHitSounds[] = - { - "zombie/claw_strike1.wav", - "zombie/claw_strike2.wav", - "zombie/claw_strike3.wav", -}; - -const char *CXenTree::pAttackMissSounds[] = - { - "zombie/claw_miss1.wav", - "zombie/claw_miss2.wav", -}; - -void CXenTree ::Precache(void) -{ - PRECACHE_MODEL("models/tree.mdl"); - PRECACHE_MODEL(XEN_PLANT_GLOW_SPRITE); - PRECACHE_SOUND_ARRAY(pAttackHitSounds); - PRECACHE_SOUND_ARRAY(pAttackMissSounds); -} - -void CXenTree ::Touch(CBaseEntity *pOther) -{ - if (!pOther->IsPlayer() && FClassnameIs(pOther->pev, "monster_bigmomma")) - return; - - Attack(); -} - -void CXenTree ::Attack(void) -{ - if (GetActivity() == ACT_IDLE) - { - SetActivity(ACT_MELEE_ATTACK1); - pev->framerate = RANDOM_FLOAT(1.0, 1.4); - EMIT_SOUND_ARRAY_DYN(CHAN_WEAPON, pAttackMissSounds); - } -} - -void CXenTree ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case TREE_AE_ATTACK: - { - CBaseEntity *pList[8]; - BOOL sound = FALSE; - int count = UTIL_EntitiesInBox(pList, 8, m_pTrigger->pev->absmin, m_pTrigger->pev->absmax, FL_MONSTER | FL_CLIENT); - Vector forward; - - UTIL_MakeVectorsPrivate(pev->angles, forward, NULL, NULL); - - for (int i = 0; i < count; i++) - { - if (pList[i] != this) - { - if (pList[i]->pev->owner != edict()) - { - sound = TRUE; - pList[i]->TakeDamage(pev, pev, 25, DMG_CRUSH | DMG_SLASH); - pList[i]->pev->punchangle.x = 15; - pList[i]->pev->velocity = pList[i]->pev->velocity + forward * 100; - } - } - } - - if (sound) - { - EMIT_SOUND_ARRAY_DYN(CHAN_WEAPON, pAttackHitSounds); - } - } - return; - } - - CActAnimating::HandleAnimEvent(pEvent); -} - -void CXenTree ::Think(void) -{ - float flInterval = StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - DispatchAnimEvents(flInterval); - - switch (GetActivity()) - { - case ACT_MELEE_ATTACK1: - if (m_fSequenceFinished) - { - SetActivity(ACT_IDLE); - pev->framerate = RANDOM_FLOAT(0.6, 1.4); - } - break; - - default: - case ACT_IDLE: - break; - } -} - -// UNDONE: These need to smoke somehow when they take damage -// Touch behavior? -// Cause damage in smoke area - -// -// Spores -// -class CXenSpore : public CActAnimating -{ -public: - void Spawn(void); - void Precache(void); - void Touch(CBaseEntity *pOther); - void Think(void); - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) - { - Attack(); - return 0; - } - // void HandleAnimEvent( MonsterEvent_t *pEvent ); - void Attack(void) {} - - static const char *pModelNames[]; -}; - -class CXenSporeSmall : public CXenSpore -{ - void Spawn(void); -}; - -class CXenSporeMed : public CXenSpore -{ - void Spawn(void); -}; - -class CXenSporeLarge : public CXenSpore -{ - void Spawn(void); - - static const Vector m_hullSizes[]; -}; - -// Fake collision box for big spores -class CXenHull : public CPointEntity -{ -public: - static CXenHull *CreateHull(CBaseEntity *source, const Vector &mins, const Vector &maxs, const Vector &offset); - int Classify(void) { return CLASS_BARNACLE; } -}; - -CXenHull *CXenHull ::CreateHull(CBaseEntity *source, const Vector &mins, const Vector &maxs, const Vector &offset) -{ - CXenHull *pHull = GetClassPtr((CXenHull *)NULL); - - UTIL_SetOrigin(pHull->pev, source->pev->origin + offset); - SET_MODEL(pHull->edict(), STRING(source->pev->model)); - pHull->pev->solid = SOLID_BBOX; - pHull->pev->classname = MAKE_STRING("xen_hull"); - pHull->pev->movetype = MOVETYPE_NONE; - pHull->pev->owner = source->edict(); - UTIL_SetSize(pHull->pev, mins, maxs); - pHull->pev->renderamt = 0; - pHull->pev->rendermode = kRenderTransTexture; - // pHull->pev->effects = EF_NODRAW; - - return pHull; -} - -LINK_ENTITY_TO_CLASS(xen_spore_small, CXenSporeSmall); -LINK_ENTITY_TO_CLASS(xen_spore_medium, CXenSporeMed); -LINK_ENTITY_TO_CLASS(xen_spore_large, CXenSporeLarge); -LINK_ENTITY_TO_CLASS(xen_hull, CXenHull); - -void CXenSporeSmall::Spawn(void) -{ - pev->skin = 0; - CXenSpore::Spawn(); - UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 64)); -} -void CXenSporeMed::Spawn(void) -{ - pev->skin = 1; - CXenSpore::Spawn(); - UTIL_SetSize(pev, Vector(-40, -40, 0), Vector(40, 40, 120)); -} - -// I just eyeballed these -- fill in hulls for the legs -const Vector CXenSporeLarge::m_hullSizes[] = - { - Vector(90, -25, 0), - Vector(25, 75, 0), - Vector(-15, -100, 0), - Vector(-90, -35, 0), - Vector(-90, 60, 0), -}; - -void CXenSporeLarge::Spawn(void) -{ - pev->skin = 2; - CXenSpore::Spawn(); - UTIL_SetSize(pev, Vector(-48, -48, 110), Vector(48, 48, 240)); - - Vector forward, right; - - UTIL_MakeVectorsPrivate(pev->angles, forward, right, NULL); - - // Rotate the leg hulls into position - for (int i = 0; i < ARRAYSIZE(m_hullSizes); i++) - CXenHull ::CreateHull(this, Vector(-12, -12, 0), Vector(12, 12, 120), (m_hullSizes[i].x * forward) + (m_hullSizes[i].y * right)); -} - -void CXenSpore ::Spawn(void) -{ - Precache(); - - SET_MODEL(ENT(pev), pModelNames[pev->skin]); - pev->movetype = MOVETYPE_NONE; - pev->solid = SOLID_BBOX; - pev->takedamage = DAMAGE_YES; - - // SetActivity( ACT_IDLE ); - pev->sequence = 0; - pev->frame = RANDOM_FLOAT(0, 255); - pev->framerate = RANDOM_FLOAT(0.7, 1.4); - ResetSequenceInfo(); - pev->nextthink = gpGlobals->time + RANDOM_FLOAT(0.1, 0.4); // Load balance these a bit -} - -const char *CXenSpore::pModelNames[] = - { - "models/fungus(small).mdl", - "models/fungus.mdl", - "models/fungus(large).mdl", -}; - -void CXenSpore ::Precache(void) -{ - PRECACHE_MODEL((char *)pModelNames[pev->skin]); -} - -void CXenSpore ::Touch(CBaseEntity *pOther) -{ -} - -void CXenSpore ::Think(void) -{ - float flInterval = StudioFrameAdvance(); - pev->nextthink = gpGlobals->time + 0.1; - -#if 0 - DispatchAnimEvents( flInterval ); - - switch( GetActivity() ) - { - default: - case ACT_IDLE: - break; - - } -#endif -} diff --git a/dlls/Items/Shields/shield.cpp b/dlls/Items/Shields/shield.cpp index 800c3b47..0721deb3 100644 --- a/dlls/Items/Shields/shield.cpp +++ b/dlls/Items/Shields/shield.cpp @@ -3,7 +3,6 @@ #include "animation.h" #include "Weapons/Weapons.h" #include "Player/player.h" -#include "shieldglobal.h" #include "Shield.h" #include "logfile.h" diff --git a/dlls/Items/Shields/shieldglobal.h b/dlls/Items/Shields/shieldglobal.h deleted file mode 100644 index 47ad87f1..00000000 --- a/dlls/Items/Shields/shieldglobal.h +++ /dev/null @@ -1 +0,0 @@ -class CShieldArea; diff --git a/dlls/Monsters/Bludgeon.cpp b/dlls/Monsters/Bludgeon.cpp deleted file mode 100644 index 66c837cc..00000000 --- a/dlls/Monsters/Bludgeon.cpp +++ /dev/null @@ -1,505 +0,0 @@ -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "../MSItemDefs.h" -#include "../Weapons/Weapons.h" - -#include "../Items/Shields/shieldglobal.h" -#include "MSmonster.h" -#include "Script.h" -#include "../MSUtils.h" - -extern int iBeam; //Global cuz this can be shared across players - -#define INTERVAL_ATTACK_LOW .7 -#define INTERVAL_ATTACK_HIGH 1.2 -#define INTERVAL_WALK 1 -#define INTERVAL_SWITCHTARGET1 4.0 //Target is found -#define INTERVAL_SWITCHTARGET2 3.0 //No target found -#define INTERVAL_LOOK 5 - -class CBludgeon : public CMSMonster -{ -public: - EHANDLE m_LastEnemy; - float LookTime, //Time until you next check around for enemies - FindTargetTime, //Time until you next check for the best enemy to fight - MoveTime, //Time until you update your movement path - LostEnemyTime, //Time until you forget about an enemy that's gone - AttackTime, //Time until you can next attack - AttackLandTime, //Time until your attack actually tracelines and hits - // TurnRate, //Rate of turning (unused) - SequenceTime; //Time that this sequence ends - - BOOL bAttacking, - bCanChangeVel; //FALSE if velocity is temporarily being skewed (like jumping) - - Vector AttackAngle; - - void Attack(); //Initiate the attack - void AttackLand(); //Land the attack later - void FinishAttack(); //Finish the attack when the sequence is finished - void StopWalking(); - void Growl(); - void DeathSound(); - - // Overridden Functions - void Spawn(); - void Precache(); - void Think(); - int BloodColor() { return BLOOD_COLOR_RED; } - int Classify() { return CLASS_MONSTER; } - int IRelationship(CBaseEntity *pTarget); - BOOL HasHumanGibs(void) { return TRUE; } - float WalkSpeed(); - float RunSpeed(); - void Move(); //Walk or run around idly or towards the enemy - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); - float BaseDamage(); - void HandleAnimEvent(MonsterEvent_t *pEvent); - void Jump(); -}; - -//LINK_ENTITY_TO_CLASS( monster_bludgeon, CBludgeon ); - -/*enum { //Bludgeon Animations -};*/ - -#define BLUDGEON_MODEL "models/monsters/bludgeon.mdl" -#define BLUDGEON_GROWL1 "bullchicken/bc_attackgrowl.wav" -#define BLUDGEON_GROWL2 "bullchicken/bc_attackgrowl2.wav" -#define BLUDGEON_GROWL3 "bullchicken/bc_attackgrowl3.wav" -#define BLUDGEON_DIE1 "bullchicken/bc_die1.wav" -#define BLUDGEON_DIE2 "bullchicken/bc_pain3.wav" -#define BLUDGEON_HITWORLD1 "debris/wood2.wav" -#define BLUDGEON_HITWORLD2 "debris/wood3.wav" -#define BLUDGEON_HITMONSTER1 "weapons/cbar_hitbod1.wav" -#define BLUDGEON_HITMONSTER2 "weapons/cbar_hitbod2.wav" -#define BLUDGEON_HITMONSTER3 "weapons/cbar_hitbod3.wav" -#define BLUDGEON_SWING1 "weapons/cbar_miss1.wav" - -void CBludgeon::Spawn() -{ - Precache(); - pev->model = MAKE_STRING(BLUDGEON_MODEL); - SET_MODEL(edict(), STRING(pev->model)); - - pev->movetype = MOVETYPE_STEP; //MOVETYPE_FLY - pev->solid = SOLID_BBOX; - pev->classname = MAKE_STRING("bludgeon"); - pev->gravity = 4; - UTIL_SetOrigin(pev, pev->origin); - UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 72)); - - pev->flags |= FL_MONSTER | FL_MONSTERCLIP; - pev->takedamage = DAMAGE_AIM; - pev->max_health = 30; //200 - pev->health = pev->max_health; - pev->deadflag = DEAD_NO; - - Gold = 50; - m_hEnemy = NULL; - m_LastEnemy = NULL; - m_EnemyListNum = 0; - bCanChangeVel = TRUE; - bAttacking = FALSE; - AttackTime = 0; - AttackLandTime = 0; - NodeCancelTime = 0; - NextNodeTime = 0; - StepSize = 24; - JumpHeight = 64; - WalkProximity = (pev->maxs - pev->mins).Length2D(); - RunProximity = WalkProximity + 25; - AttackProximity = WalkProximity + 32; //48 - // TurnRate = .8;//.7 - m_flFieldOfView = .5235; // +/-30 degrees in radians - pev->view_ofs = Vector(0, 0, 72); - StopWalking(); - SetAnimation(); - // pev->sequence = LookupActivity( ACT_IDLE ); - // ResetSequenceInfo( ); - - pev->nextthink = gpGlobals->time + 0.1; - CMSMonster::Spawn(); -} -void CBludgeon::Precache() -{ - PRECACHE_MODEL(BLUDGEON_MODEL); - PRECACHE_SOUND(BLUDGEON_GROWL1); - PRECACHE_SOUND(BLUDGEON_GROWL2); - PRECACHE_SOUND(BLUDGEON_GROWL3); - PRECACHE_SOUND(BLUDGEON_DIE1); - PRECACHE_SOUND(BLUDGEON_DIE2); - PRECACHE_SOUND(BLUDGEON_HITWORLD1); - PRECACHE_SOUND(BLUDGEON_HITWORLD2); - PRECACHE_SOUND(BLUDGEON_HITMONSTER1); - PRECACHE_SOUND(BLUDGEON_HITMONSTER2); - PRECACHE_SOUND(BLUDGEON_SWING1); -} -void CBludgeon::Think() -{ - - if (m_pfnThink) - { - (this->*m_pfnThink)(); - return; - } - if (!IsAlive()) - return; - - int OldActivity = m_Activity; - - StudioFrameAdvance(); - if (pev->health < 0) - return; - - if (m_hEnemy == NULL || !m_hEnemy->IsAlive() || m_hEnemy->pev->flags & FL_NOTARGET || gpGlobals->time > FindTargetTime) - { - EHANDLE ehPrevEnemy = m_hEnemy; - // find the current best target... this may change in the middle of combat - m_hEnemy = BestVisibleEnemy(); - if (m_hEnemy != NULL) - { - // ALERT( at_console, "m_hEnemy != NULL\n" ); - if (ehPrevEnemy != NULL && ehPrevEnemy.Get() != m_hEnemy.Get()) - m_LastEnemy = ehPrevEnemy; - //If this is a new target, growl - if (ehPrevEnemy == NULL || ehPrevEnemy.Get() != m_hEnemy.Get()) - Growl(); - MoveTime = 0; - FindTargetTime = gpGlobals->time + INTERVAL_SWITCHTARGET1; - } - else if (m_LastEnemy != NULL) - { - // ALERT( at_console, "m_LastEnemy\n" ); - if (m_LastEnemy->IsAlive() && FVisible(m_LastEnemy)) - m_hEnemy = m_LastEnemy; - FindTargetTime = gpGlobals->time + INTERVAL_SWITCHTARGET1; - } - else if (ehPrevEnemy != NULL) - { - // ALERT( at_console, "ehPrevEnemy\n" ); - if (ehPrevEnemy->IsAlive()) - m_hEnemy = ehPrevEnemy; - FindTargetTime = gpGlobals->time + INTERVAL_SWITCHTARGET1; - } - if (m_hEnemy == NULL) - { //m_hEnemy is still invalid - // ALERT( at_console, "m_hEnemy == NULL\n" ); - //StopWalking( ); - FindTargetTime = gpGlobals->time + INTERVAL_SWITCHTARGET2; - } - } - if (gpGlobals->time >= LookTime && (m_hEnemy == NULL || !m_hEnemy->IsAlive())) - { - Look(1024); //was 512 - // Look around me for targets if I don't have one - // if( m_hEnemy ) { if( m_hEnemy->IsAlive() ) - LookTime = gpGlobals->time + INTERVAL_LOOK; - // else LookTime = gpGlobals->time + 3.0; - } - // ALERT( at_console, "Done.\n" ); - if (gpGlobals->time >= AttackTime) - Attack(); - if (gpGlobals->time >= AttackLandTime) - AttackLand(); - if (bAttacking) - FinishAttack(); - if (gpGlobals->time >= MoveTime) - Move(); - - //Some Movement rules that always take place - //[gravity] - // if( !FBitSet(pev->flags,FL_ONGROUND) ) { - /* TraceResult tr; - UTIL_TraceLine(pev->origin, pev->origin + Vector(0,0,-2), dont_ignore_monsters, dont_ignore_glass, edict(), &tr); - if( tr.flFraction >= 1.0 ) pev->movetype = MOVETYPE_STEP; - else pev->movetype = MOVETYPE_FLY;*/ - // } - // else pev->movetype = MOVETYPE_FLY; - - //pev->angles = UTIL_VecToAngles( pev->velocity ); - - Step(); //Walk up steps and the such - Jump(); //Jump if neccesary - - //AtferMath - //[Animation to play] - SetAnimation(); - DispatchAnimEvents(); - - pev->angles.x = 0; - pev->angles.z = 0; - if (m_flGroundSpeed) - { - //if( m_flGroundSpeed < 0 ) m_flGroundSpeed = -m_flGroundSpeed; - if (bCanChangeVel) - { - UTIL_MakeVectors(pev->angles); - pev->velocity = gpGlobals->v_forward * m_flGroundSpeed * SpeedMultiplier; - } - } - //if( FBitSet(pev->flags,FL_ONGROUND) ) pev->velocity.z = 0; - - CMSMonster::Think(); - pev->nextthink = gpGlobals->time + 0.1; - //UTIL_BloodDrips( pev->origin, g_vecZero, BloodColor(), 80 ); -} -float CBludgeon::WalkSpeed() { return 1.5; } -float CBludgeon::RunSpeed() { return 3; } -int CBludgeon::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - if (RANDOM_LONG(0, 1)) - Growl(); - return CMSMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} -float CBludgeon::BaseDamage() { return RANDOM_LONG(1, 3); } -void CBludgeon::Attack() -{ - if (AttackLandTime || m_Activity == ACT_HOP) - return; - if (m_hEnemy == NULL || !m_hEnemy->IsAlive()) - return; - Vector m_vecTarget = m_hEnemy->EyePosition() - EyePosition(); - //Are we close enough? - if (m_vecTarget.Length() > AttackProximity) - return; - StopWalking(); - pev->angles = pev->v_angle = UTIL_VecToAngles(m_vecTarget); - pev->angles.z = 0; - - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, BLUDGEON_SWING1, RANDOM_FLOAT(0.85, 1.0), ATTN_NORM, 0, 65 + RANDOM_FLOAT(0, 40)); - - m_Activity = ACT_MELEE_ATTACK1; - pev->sequence = 0; //Causes it to play this animation NOW no matter what - - SequenceTime = 256 / (m_flFrameRate * pev->framerate); //Relative time - - bAttacking = TRUE; - AttackLandTime = gpGlobals->time + .1; - AttackTime = AttackLandTime + RANDOM_FLOAT(INTERVAL_ATTACK_LOW, INTERVAL_ATTACK_HIGH); - SequenceTime += gpGlobals->time; //Absolute time -} -void CBludgeon::AttackLand() -{ - if (!AttackLandTime) - return; - - TraceResult tr; - Vector vecSrc, vecEnd; - switch (m_Activity) - { - case ACT_MELEE_ATTACK1: - Vector vRand = Vector(RANDOM_FLOAT(-15, 15), RANDOM_FLOAT(-15, 15), RANDOM_FLOAT(-15, 15)); - UTIL_MakeVectors(pev->angles); - vecSrc = pev->origin + gpGlobals->v_forward * 10 + pev->view_ofs - Vector(0, 0, 30); - pev->punchangle = g_vecZero; - UTIL_MakeVectors(pev->v_angle + pev->punchangle + vRand); - vecEnd = vecSrc + gpGlobals->v_forward * 60; - } - - G_MakeSHIELDs(); - UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, edict(), &tr); - G_RemoveSHIELDs(); - - if (tr.flFraction < 1.0) - { - CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); - if (pEntity) - { - int iTemp; - if (pEntity->Classify() == CLASS_NONE || pEntity->Classify() == CLASS_MACHINE) - { - //Hit the world - if ((iTemp = RANDOM_LONG(0, 1)) == 0) - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, BLUDGEON_HITWORLD1, RANDOM_FLOAT(0.85, 1.0), ATTN_NORM, 0, 55 + RANDOM_FLOAT(0, 40)); - else if (iTemp == 1) - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, BLUDGEON_HITWORLD2, RANDOM_FLOAT(0.85, 1.0), ATTN_NORM, 0, 55 + RANDOM_FLOAT(0, 40)); - if (pEntity->MSProperties() & ITEM_SHIELD) - pEntity->DamageDecal(BaseDamage()); - } - else - { //Hit something organic - if ((iTemp = RANDOM_LONG(0, 1)) == 0) - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, BLUDGEON_HITMONSTER1, RANDOM_FLOAT(0.85, 1.0), ATTN_NORM, 0, 55 + RANDOM_FLOAT(0, 40)); - else if (iTemp == 1) - EMIT_SOUND_DYN(edict(), CHAN_WEAPON, BLUDGEON_HITMONSTER2, RANDOM_FLOAT(0.85, 1.0), ATTN_NORM, 0, 55 + RANDOM_FLOAT(0, 40)); - //ALERT( at_console, "Hit: %s.\n", STRING(pEntity->pev->classname) ); - } - - ClearMultiDamage(); - pEntity->TraceAttack(pev, pev, BaseDamage(), gpGlobals->v_forward, &tr, DMG_CLUB); - ApplyMultiDamage(pev, pev); - float flMult = BaseDamage() * 10; - pEntity->pev->punchangle.x += RANDOM_FLOAT(-1, 1) * flMult; - pEntity->pev->punchangle.y += RANDOM_FLOAT(-1, 1) * flMult; - pEntity->pev->punchangle.z += RANDOM_FLOAT(-1, 1) * flMult; - } - } - AttackLandTime = 0; - // BeamEffect( vecSrc, vecEnd, iBeam, 0, 0, 100, 1, 0, 255, 255,255, 255, 20 ); -} -void CBludgeon::FinishAttack() -{ - if (!bAttacking) - return; - if (!AttackLandTime && gpGlobals->time > SequenceTime) - { - bAttacking = FALSE; - } -} -void CBludgeon::Move() -{ - if (bAttacking || m_Activity == ACT_HOP) - return; - bCanChangeVel = TRUE; - Vector m_vecTarget, ExactAngle; //ExactAngle: The vector m_vecTarget as an angle - Activity OldActivity = m_Activity; - TraceResult tr; - Vector VecDest; - BOOL bCloseEnough; //Close enough to our target to stop walking - - if (m_hEnemy != NULL && m_hEnemy->IsAlive()) - { - //Track the enemy - bCloseEnough = FALSE; - if (FVisible(m_hEnemy)) - { - m_vecTarget = m_hEnemy->EyePosition() - EyePosition(); - //ALERT( at_console, "Length: %f, Close: %f\n", m_vecTarget.Length2D(), Proximity ); - m_vecEnemyLKP = m_hEnemy->EyePosition(); - } - else if (m_vecEnemyLKP) - m_vecTarget = m_vecEnemyLKP - EyePosition(); - - //Are we close enough? - if (m_vecTarget.Length2D() < WalkProximity) - { - pev->angles.y = UTIL_VecToAngles(m_vecTarget.Normalize()).y; - StopWalking(); - bCloseEnough = TRUE; - return; - } - else if (m_vecTarget.Length2D() < RunProximity) - { - m_Activity = ACT_WALK; - SpeedMultiplier = WalkSpeed(); - } - else - { - m_Activity = ACT_RUN; - SpeedMultiplier = RunSpeed(); - } - - //This must be done AFTER we check m_vecTarget's length - m_vecTarget = m_vecTarget.Normalize(); - - /* UTIL_MakeVectors( pev->angles ); - //UNDONE --> only turn a certain amount each frame (TurnRate in radians) - if( DotProduct(gpGlobals->v_right, m_vecTarget) > - DotProduct(-gpGlobals->v_right, m_vecTarget) ) flTemp = 1; - else flTemp = -1; - - flRemainingTurn = 1-DotProduct(gpGlobals->v_forward.Make2D(), m_vecTarget.Make2D()); -*/ - // pev->avelocity = Vector( 0, 180 * (flRemainingTurn*1) * -flTemp, 0 ); - // ALERT( at_console, "1: %f, 2: %f\n", 1-DotProduct(gpGlobals->v_forward.Make2D(), m_vecTarget.Make2D()), TurnRate ); - ExactAngle = UTIL_VecToAngles(m_vecTarget); - //Get an angle in the middle - pev->angles.y = pev->angles.y + UTIL_AngleDiff(ExactAngle.y, pev->angles.y) / 3; - } - else - CMSMonster::Move(); //No enemy, walk around randomly (here m_vecEnemyLKP is the random place to walk) - - MoveTime = gpGlobals->time + INTERVAL_WALK / 2; -} -void CBludgeon::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - LastEvent = *pEvent; - float z; - // ALERT( at_console, "event %i\n", LastEvent.event ); - switch (LastEvent.event) - { - case 400: //Animation Event 400 - Jump - UTIL_MakeVectors(pev->angles); - pev->velocity = gpGlobals->v_forward * 250; - pev->velocity.z = 450; - break; - case 401: //Animation Event 401 - Move forward in Jump - z = pev->velocity.z; - UTIL_MakeVectors(pev->angles); - pev->velocity = gpGlobals->v_forward * 250; - pev->velocity.z = z; - break; - case 500: //Animation Event 500 - Stop forward/backward movement - bCanChangeVel = FALSE; - pev->velocity.x = 0; - pev->velocity.y = 0; - break; - default: - CBaseAnimating::HandleAnimEvent(pEvent); - break; - } -} -void CBludgeon::StopWalking() -{ - switch (m_Activity) - { - case ACT_WALK: - m_Activity = ACT_IDLE; - break; - } - pev->velocity = g_vecZero; - m_flGroundSpeed = 0; - SpeedMultiplier = 0; -} -void CBludgeon::Jump() -{ - Activity OldActivity = m_Activity; - if (m_Activity != ACT_HOP && m_hEnemy != NULL) - { - Vector m_vecTarget = m_hEnemy->EyePosition() - EyePosition(); - //Are we too close? - if (m_vecTarget.Length() <= AttackProximity) - return; - } - - CMSMonster::Jump(); - - if (m_Activity == ACT_HOP && OldActivity != m_Activity) - { - UTIL_MakeVectors(pev->angles); - bCanChangeVel = FALSE; - //pev->velocity = -gpGlobals->v_forward * 40; - } -} -int CBludgeon::IRelationship(CBaseEntity *pTarget) -{ - if (pTarget->pev->classname == pev->classname) - return R_AL; - return CMSMonster::IRelationship(pTarget); -} -void CBludgeon::Growl() -{ - if (!IsAlive()) - return; - int iTemp; - - if ((iTemp = RANDOM_LONG(0, 3)) == 0) - EMIT_SOUND_DYN(edict(), CHAN_VOICE, BLUDGEON_GROWL1, RANDOM_FLOAT(0.85, 1.0), ATTN_NORM, 0, 85 + RANDOM_FLOAT(0, 20)); - else if (iTemp == 1) - EMIT_SOUND_DYN(edict(), CHAN_VOICE, BLUDGEON_GROWL2, RANDOM_FLOAT(0.85, 1.0), ATTN_NORM, 0, 85 + RANDOM_FLOAT(0, 20)); - else if (iTemp == 2) - EMIT_SOUND_DYN(edict(), CHAN_VOICE, BLUDGEON_GROWL3, RANDOM_FLOAT(0.85, 1.0), ATTN_NORM, 0, 85 + RANDOM_FLOAT(0, 20)); -} -void CBludgeon::DeathSound() -{ - int iTemp; - - if ((iTemp = RANDOM_LONG(0, 1)) == 0) - EMIT_SOUND_DYN(edict(), CHAN_VOICE, BLUDGEON_DIE1, RANDOM_FLOAT(0.85, 1.0), ATTN_NORM, 0, 85 + RANDOM_FLOAT(0, 20)); - else if (iTemp == 1) - EMIT_SOUND_DYN(edict(), CHAN_VOICE, BLUDGEON_DIE2, RANDOM_FLOAT(0.85, 1.0), ATTN_NORM, 0, 85 + RANDOM_FLOAT(0, 20)); -} diff --git a/dlls/Monsters/MonsterList.cpp b/dlls/Monsters/MonsterList.cpp deleted file mode 100644 index a36c2810..00000000 --- a/dlls/Monsters/MonsterList.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#define VALVE_DLL 1 - -#include "MonsterList.h" - -scriptres_t g_ScriptFiles[] = - { - "monsters/bat.script", - "bat", - "monsters/boar.script", - "boar", - "monsters/giantbat.script", - "giantbat", - "monsters/giantrat.script", - "giantrat", - "monsters/giantspider.script", - "giantspider", - "monsters/gspider.script", - "gspider", - "monsters/hawk.script", - "hawk", - "monsters/minispider.script", - "minispider", - "monsters/orcarcher.script", - "orcarcher", - "monsters/orcberserker.script", - "orcberserker", - "monsters/orcranger.script", - "orcranger", - "monsters/orcwarrior.script", - "orcwarrior", - "monsters/skeleton.script", - "skeleton", - "monsters/skeleton2.script", - "skeleton2", - "monsters/spider.script", - "spider", - "dq/findlebind.script", - "findlebind", - "dq/murmur.script", - "murmur", - "dq/voldar.script", - "voldar", - "dq/voldarwarrior.script", - "voldarwarrior", -}; -int g_iScriptFilesSize = sizeof(g_ScriptFiles) / sizeof(g_ScriptFiles[0]); \ No newline at end of file diff --git a/dlls/Monsters/zombie.cpp b/dlls/Monsters/zombie.cpp deleted file mode 100644 index e6d65ab9..00000000 --- a/dlls/Monsters/zombie.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/*** -* -* Copyright (c) 1999, 2000 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. -* -****/ -//========================================================= -// Zombie -//========================================================= - -// UNDONE: Don't flinch every time you get hit - -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" -#include "schedule.h" - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define ZOMBIE_AE_ATTACK_RIGHT 0x01 -#define ZOMBIE_AE_ATTACK_LEFT 0x02 -#define ZOMBIE_AE_ATTACK_BOTH 0x03 - -#define ZOMBIE_FLINCH_DELAY 2 // at most one flinch every n secs - -class CZombie : public CBaseMonster -{ -public: - void Spawn(void); - void Precache(void); - void SetYawSpeed(void); - int Classify(void); - void HandleAnimEvent(MonsterEvent_t *pEvent); - int IgnoreConditions(void); - - float m_flNextFlinch; - - void PainSound(void); - void AlertSound(void); - void IdleSound(void); - void AttackSound(void); - - static const char *pAttackSounds[]; - static const char *pIdleSounds[]; - static const char *pAlertSounds[]; - static const char *pPainSounds[]; - static const char *pAttackHitSounds[]; - static const char *pAttackMissSounds[]; - - // No range attacks - BOOL CheckRangeAttack1(float flDot, float flDist) { return FALSE; } - BOOL CheckRangeAttack2(float flDot, float flDist) { return FALSE; } - int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); -}; - -LINK_ENTITY_TO_CLASS(monster_zombie, CZombie); - -const char *CZombie::pAttackHitSounds[] = - { - "zombie/claw_strike1.wav", - "zombie/claw_strike2.wav", - "zombie/claw_strike3.wav", -}; - -const char *CZombie::pAttackMissSounds[] = - { - "zombie/claw_miss1.wav", - "zombie/claw_miss2.wav", -}; - -const char *CZombie::pAttackSounds[] = - { - "zombie/zo_attack1.wav", - "zombie/zo_attack2.wav", -}; - -const char *CZombie::pIdleSounds[] = - { - "zombie/zo_idle1.wav", - "zombie/zo_idle2.wav", - "zombie/zo_idle3.wav", - "zombie/zo_idle4.wav", -}; - -const char *CZombie::pAlertSounds[] = - { - "zombie/zo_alert10.wav", - "zombie/zo_alert20.wav", - "zombie/zo_alert30.wav", -}; - -const char *CZombie::pPainSounds[] = - { - "zombie/zo_pain1.wav", - "zombie/zo_pain2.wav", -}; - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -int CZombie ::Classify(void) -{ - return CLASS_ALIEN_MONSTER; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -void CZombie ::SetYawSpeed(void) -{ - int ys; - - ys = 120; - -#if 0 - switch ( m_Activity ) - { - } -#endif - - pev->yaw_speed = ys; -} - -int CZombie ::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) -{ - // Take 30% damage from bullets - if (bitsDamageType == DMG_BULLET) - { - Vector vecDir = pev->origin - (pevInflictor->absmin + pevInflictor->absmax) * 0.5; - vecDir = vecDir.Normalize(); - float flForce = DamageForce(flDamage); - pev->velocity = pev->velocity + vecDir * flForce; - flDamage *= 0.3; - } - - // HACK HACK -- until we fix this. - if (IsAlive()) - PainSound(); - return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); -} - -void CZombie ::PainSound(void) -{ - int pitch = 95 + RANDOM_LONG(0, 9); - - if (RANDOM_LONG(0, 5) < 2) - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, pPainSounds[RANDOM_LONG(0, ARRAYSIZE(pPainSounds) - 1)], 1.0, ATTN_NORM, 0, pitch); -} - -void CZombie ::AlertSound(void) -{ - int pitch = 95 + RANDOM_LONG(0, 9); - - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, pAlertSounds[RANDOM_LONG(0, ARRAYSIZE(pAlertSounds) - 1)], 1.0, ATTN_NORM, 0, pitch); -} - -void CZombie ::IdleSound(void) -{ - int pitch = 95 + RANDOM_LONG(0, 9); - - // Play a random idle sound - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, pIdleSounds[RANDOM_LONG(0, ARRAYSIZE(pIdleSounds) - 1)], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); -} - -void CZombie ::AttackSound(void) -{ - // Play a random attack sound - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, pAttackSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackSounds) - 1)], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CZombie ::HandleAnimEvent(MonsterEvent_t *pEvent) -{ - switch (pEvent->event) - { - case ZOMBIE_AE_ATTACK_RIGHT: - { - // do stuff for this event. - // ALERT( at_console, "Slash right!\n" ); - CBaseEntity *pHurt = CheckTraceHullAttack(70, gSkillData.zombieDmgOneSlash, DMG_SLASH); - if (pHurt) - { - if (pHurt->pev->flags & (FL_MONSTER | FL_CLIENT)) - { - pHurt->pev->punchangle.z = -18; - pHurt->pev->punchangle.x = 5; - pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_right * 100; - } - // Play a random attack hit sound - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pAttackHitSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackHitSounds) - 1)], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); - } - else // Play a random attack miss sound - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pAttackMissSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackMissSounds) - 1)], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); - - if (RANDOM_LONG(0, 1)) - AttackSound(); - } - break; - - case ZOMBIE_AE_ATTACK_LEFT: - { - // do stuff for this event. - // ALERT( at_console, "Slash left!\n" ); - CBaseEntity *pHurt = CheckTraceHullAttack(70, gSkillData.zombieDmgOneSlash, DMG_SLASH); - if (pHurt) - { - if (pHurt->pev->flags & (FL_MONSTER | FL_CLIENT)) - { - pHurt->pev->punchangle.z = 18; - pHurt->pev->punchangle.x = 5; - pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_right * 100; - } - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pAttackHitSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackHitSounds) - 1)], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); - } - else - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pAttackMissSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackMissSounds) - 1)], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); - - if (RANDOM_LONG(0, 1)) - AttackSound(); - } - break; - - case ZOMBIE_AE_ATTACK_BOTH: - { - // do stuff for this event. - CBaseEntity *pHurt = CheckTraceHullAttack(70, gSkillData.zombieDmgBothSlash, DMG_SLASH); - if (pHurt) - { - if (pHurt->pev->flags & (FL_MONSTER | FL_CLIENT)) - { - pHurt->pev->punchangle.x = 5; - pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * -100; - } - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pAttackHitSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackHitSounds) - 1)], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); - } - else - EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, pAttackMissSounds[RANDOM_LONG(0, ARRAYSIZE(pAttackMissSounds) - 1)], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); - - if (RANDOM_LONG(0, 1)) - AttackSound(); - } - break; - - default: - CBaseMonster::HandleAnimEvent(pEvent); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CZombie ::Spawn() -{ - Precache(); - - SET_MODEL(ENT(pev), "models/zombie.mdl"); - UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); - - pev->solid = SOLID_SLIDEBOX; - pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_GREEN; - pev->health = gSkillData.zombieHealth; - pev->view_ofs = VEC_VIEW; // position of the eyes relative to monster's origin. - m_flFieldOfView = 0.5; // indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_MonsterState = MONSTERSTATE_NONE; - m_afCapability = bits_CAP_DOORS_GROUP; - - MonsterInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CZombie ::Precache() -{ - int i; - - PRECACHE_MODEL("models/zombie.mdl"); - - for (i = 0; i < ARRAYSIZE(pAttackHitSounds); i++) - PRECACHE_SOUND((char *)pAttackHitSounds[i]); - - for (i = 0; i < ARRAYSIZE(pAttackMissSounds); i++) - PRECACHE_SOUND((char *)pAttackMissSounds[i]); - - for (i = 0; i < ARRAYSIZE(pAttackSounds); i++) - PRECACHE_SOUND((char *)pAttackSounds[i]); - - for (i = 0; i < ARRAYSIZE(pIdleSounds); i++) - PRECACHE_SOUND((char *)pIdleSounds[i]); - - for (i = 0; i < ARRAYSIZE(pAlertSounds); i++) - PRECACHE_SOUND((char *)pAlertSounds[i]); - - for (i = 0; i < ARRAYSIZE(pPainSounds); i++) - PRECACHE_SOUND((char *)pPainSounds[i]); -} - -//========================================================= -// AI Schedules Specific to this monster -//========================================================= - -int CZombie::IgnoreConditions(void) -{ - int iIgnore = CBaseMonster::IgnoreConditions(); - - if ((m_Activity == ACT_MELEE_ATTACK1) || (m_Activity == ACT_MELEE_ATTACK1)) - { -#if 0 - if (pev->health < 20) - iIgnore |= (bits_COND_LIGHT_DAMAGE|bits_COND_HEAVY_DAMAGE); - else -#endif - if (m_flNextFlinch >= gpGlobals->time) - iIgnore |= (bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE); - } - - if ((m_Activity == ACT_SMALL_FLINCH) || (m_Activity == ACT_BIG_FLINCH)) - { - if (m_flNextFlinch < gpGlobals->time) - m_flNextFlinch = gpGlobals->time + ZOMBIE_FLINCH_DELAY; - } - - return iIgnore; -} \ No newline at end of file diff --git a/dlls/Weapons/giattack.cpp b/dlls/Weapons/giattack.cpp index bcd56c25..f2495764 100644 --- a/dlls/Weapons/giattack.cpp +++ b/dlls/Weapons/giattack.cpp @@ -21,7 +21,6 @@ #include "logfile.h" #ifdef VALVE_DLL -#include "Items/Shields/shieldglobal.h" #include "Items/Shields/Shield.h" #include "soundent.h" #endif