/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * * This product contains software technology licensed from Id * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * * 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 "cmbase.h" #include "decals.h" extern Vector VecBModelOrigin( entvars_t* pevBModel ); extern DLL_GLOBAL Vector g_vecAttackDir; edict_t * EHANDLE::Get( void ) { if (m_pent) { if (m_pent->serialnumber == m_serialnumber) return m_pent; else return NULL; } return NULL; }; edict_t * EHANDLE::Set( edict_t *pent ) { m_pent = pent; if (pent) m_serialnumber = m_pent->serialnumber; return pent; }; EHANDLE :: operator edict_t *() { return Get( ); }; edict_t * EHANDLE :: operator = (edict_t *pEntity) { if (pEntity) { m_pent = pEntity; if (m_pent) m_serialnumber = m_pent->serialnumber; } else { m_pent = NULL; m_serialnumber = 0; } return pEntity; } edict_t * EHANDLE :: operator -> () { return Get( ); } void *CMBaseEntity::operator new( size_t stAllocateBlock ) { void *mem = ::operator new( stAllocateBlock ); memset( mem, 0, stAllocateBlock ); return mem; } edict_t *CMBaseEntity::CreateEntity(char *classname) { int istr = MAKE_STRING(classname); edict_t *pent = CREATE_NAMED_ENTITY(istr); if ( FNullEnt( pent ) ) return NULL; pev = VARS(pent); pev->movetype = MOVETYPE_NONE; pev->solid = SOLID_NOT; pev->flags = 0; m_pfnThink = NULL; m_pfnTouch = NULL; m_pfnUse = NULL; m_pfnBlocked = NULL; pev->euser4 = (edict_t *)this; return pent; } // give health int CMBaseEntity :: TakeHealth( float flHealth, int bitsDamageType ) { if (!pev->takedamage) return 0; // heal if ( pev->health >= pev->max_health ) return 0; pev->health += flHealth; if (pev->health > pev->max_health) pev->health = pev->max_health; return 1; } // inflict damage on this entity. bitsDamageType indicates type of damage inflicted, ie: DMG_CRUSH int CMBaseEntity :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType ) { Vector vecTemp; if (!pev->takedamage) return 0; // UNDONE: some entity types may be immune or resistant to some bitsDamageType // if Attacker == Inflictor, the attack was a melee or other instant-hit attack. // (that is, no actual entity projectile was involved in the attack so use the shooter's origin). if ( pevAttacker == pevInflictor ) { vecTemp = pevInflictor->origin - ( VecBModelOrigin(pev) ); } else // an actual missile was involved. { vecTemp = pevInflictor->origin - ( VecBModelOrigin(pev) ); } // this global is still used for glass and other non-monster killables, along with decals. g_vecAttackDir = vecTemp.Normalize(); // save damage based on the target's armor level // figure momentum add (don't let hurt brushes or other triggers move player) if ((!FNullEnt(pevInflictor)) && (pev->movetype == MOVETYPE_WALK || pev->movetype == MOVETYPE_STEP) && (pevAttacker->solid != SOLID_TRIGGER) ) { Vector vecDir = pev->origin - (pevInflictor->absmin + pevInflictor->absmax) * 0.5; vecDir = vecDir.Normalize(); float flForce = flDamage * ((32 * 32 * 72.0) / (pev->size.x * pev->size.y * pev->size.z)) * 5; if (flForce > 1000.0) flForce = 1000.0; pev->velocity = pev->velocity + vecDir * flForce; } // do the damage pev->health -= flDamage; if (pev->health <= 0) { Killed( pevAttacker, GIB_NORMAL ); return 0; } return 1; } void CMBaseEntity :: Killed( entvars_t *pevAttacker, int iGib ) { pev->takedamage = DAMAGE_NO; pev->deadflag = DEAD_DEAD; UTIL_Remove( this->edict() ); } // Initialize absmin & absmax to the appropriate box void SetObjectCollisionBox( entvars_t *pev ) { if ( (pev->solid == SOLID_BSP) && (pev->angles.x || pev->angles.y|| pev->angles.z) ) { // expand for rotation float max, v; int i; max = 0; for (i=0 ; i<3 ; i++) { v = fabs( ((float *)pev->mins)[i]); if (v > max) max = v; v = fabs( ((float *)pev->maxs)[i]); if (v > max) max = v; } for (i=0 ; i<3 ; i++) { ((float *)pev->absmin)[i] = ((float *)pev->origin)[i] - max; ((float *)pev->absmax)[i] = ((float *)pev->origin)[i] + max; } } else { pev->absmin = pev->origin + pev->mins; pev->absmax = pev->origin + pev->maxs; } pev->absmin.x -= 1; pev->absmin.y -= 1; pev->absmin.z -= 1; pev->absmax.x += 1; pev->absmax.y += 1; pev->absmax.z += 1; } void CMBaseEntity::SetObjectCollisionBox( void ) { ::SetObjectCollisionBox( pev ); } int CMBaseEntity :: Intersects( CMBaseEntity *pOther ) { if ( pOther->pev->absmin.x > pev->absmax.x || pOther->pev->absmin.y > pev->absmax.y || pOther->pev->absmin.z > pev->absmax.z || pOther->pev->absmax.x < pev->absmin.x || pOther->pev->absmax.y < pev->absmin.y || pOther->pev->absmax.z < pev->absmin.z ) return 0; return 1; } void CMBaseEntity :: MakeDormant( void ) { SetBits( pev->flags, FL_DORMANT ); // Don't touch pev->solid = SOLID_NOT; // Don't move pev->movetype = MOVETYPE_NONE; // Don't draw SetBits( pev->effects, EF_NODRAW ); // Don't think pev->nextthink = 0; // Relink UTIL_SetOrigin( pev, pev->origin ); } int CMBaseEntity :: IsDormant( void ) { return FBitSet( pev->flags, FL_DORMANT ); } BOOL CMBaseEntity :: IsInWorld( void ) { // position if (pev->origin.x >= 4096) return FALSE; if (pev->origin.y >= 4096) return FALSE; if (pev->origin.z >= 4096) return FALSE; if (pev->origin.x <= -4096) return FALSE; if (pev->origin.y <= -4096) return FALSE; if (pev->origin.z <= -4096) return FALSE; // speed if (pev->velocity.x >= 2000) return FALSE; if (pev->velocity.y >= 2000) return FALSE; if (pev->velocity.z >= 2000) return FALSE; if (pev->velocity.x <= -2000) return FALSE; if (pev->velocity.y <= -2000) return FALSE; if (pev->velocity.z <= -2000) return FALSE; return TRUE; } int CMBaseEntity::ShouldToggle( USE_TYPE useType, BOOL currentState ) { if ( useType != USE_TOGGLE && useType != USE_SET ) { if ( (currentState && useType == USE_ON) || (!currentState && useType == USE_OFF) ) return 0; } return 1; } int CMBaseEntity :: DamageDecal( int bitsDamageType ) { if ( pev->rendermode == kRenderTransAlpha ) return -1; if ( pev->rendermode != kRenderNormal ) return DECAL_BPROOF1; return DECAL_GUNSHOT1 + RANDOM_LONG(0,4); }