/*** * * 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. * ****/ #include "stdafx.h" #include "cbase.h" #include "saverestore.h" #include "client.h" #include "decals.h" #include "gamerules.h" #include "game.h" #include "MemPool.h" void EntvarsKeyvalue(entvars_t *pev, KeyValueData *pkvd); extern "C" void PM_Move(struct playermove_s *ppmove, int server); extern "C" void PM_Init(struct playermove_s *ppmove); extern "C" char PM_FindTextureType(char *name); Vector VecBModelOrigin(entvars_t *pevBModel); extern DLL_GLOBAL Vector g_vecAttackDir; extern DLL_GLOBAL int g_iSkillLevel; CUtlVector stringsHashTable; CMemoryPool hashItemMemPool(sizeof(hash_item_t), 64); int CaseInsensitiveHash(const char *string, int iBounds) { unsigned int hash = 0; if (!*string) return 0; while (*string) { if (*string < 'A' || *string > 'Z') hash = *string + 2 * hash; else hash = *string + 2 * hash + ' '; string++; } return (hash % iBounds); } void EmptyEntityHashTable(void) { int i; hash_item_t *item; hash_item_t *temp; hash_item_t *free; for (i = 0; i < stringsHashTable.Count(); i++) { item = &stringsHashTable[i]; temp = item->next; item->pev = NULL; item->pevIndex = 0; item->lastHash = NULL; item->next = NULL; while (temp) { free = temp; temp = temp->next; hashItemMemPool.Free(free); } } } void AddEntityHashValue(struct entvars_s *pev, const char *value, hash_types_e fieldType) { int count; hash_item_t *item; hash_item_t *next; hash_item_t *temp; hash_item_t *newp; unsigned int hash = 0; int pevIndex; entvars_t *pevtemp; if (fieldType == CLASSNAME) { if (!FStringNull(pev->classname)) { count = stringsHashTable.Count(); hash = CaseInsensitiveHash(value, count); pevIndex = ENTINDEX(ENT(pev)); item = &stringsHashTable[hash]; while (item->pev) { if (!strcmp(STRING(item->pev->classname), STRING(pev->classname))) break; hash = (hash + 1) % count; item = &stringsHashTable[hash]; } if (item->pev) { next = item->next; while (next) { if (item->pev == pev) break; if (item->pevIndex >= pevIndex) break; item = next; next = next->next; } if (pevIndex < item->pevIndex) { pevtemp = item->pev; item->pev = pev; item->lastHash = NULL; item->pevIndex = pevIndex; pevIndex = ENTINDEX(ENT(pevtemp)); } else pevtemp = pev; if (item->pev != pevtemp) { temp = item->next; newp = (hash_item_t *)hashItemMemPool.Alloc(sizeof(hash_item_t)); item->next = newp; newp->pev = pevtemp; newp->lastHash = NULL; newp->pevIndex = pevIndex; if (temp) newp->next = temp; else newp->next = NULL; } } else { item->pev = pev; item->lastHash = NULL; item->pevIndex = ENTINDEX(ENT(pev)); } } } } void RemoveEntityHashValue(struct entvars_s *pev, const char *value, hash_types_e fieldType) { int hash = 0; hash_item_t *item; hash_item_t *last; int pevIndex; int count; count = stringsHashTable.Count(); hash = CaseInsensitiveHash(value, count); pevIndex = ENTINDEX(ENT(pev)); if (fieldType == CLASSNAME) { hash = hash % count; item = &stringsHashTable[hash]; while (item->pev) { if (!strcmp(STRING(item->pev->classname), STRING(pev->classname))) break; hash = (hash + 1) % count; item = &stringsHashTable[hash]; } if (item->pev) { last = item; while (item->next) { if (item->pev == pev) break; last = item; item = item->next; } if (item->pev == pev) { if (last == item) { if (item->next) { item->pev = item->next->pev; item->pevIndex = item->next->pevIndex; item->lastHash = NULL; item->next = item->next->next; } else { item->pev = NULL; item->lastHash = NULL; item->pevIndex = 0; } } else { if (stringsHashTable[hash].lastHash == item) stringsHashTable[hash].lastHash = NULL; last->next = item->next; hashItemMemPool.Free(item); } } } } } void printEntities(void) { int i; hash_item_t *item; for (i = 0; i < stringsHashTable.Count(); i++) { item = &stringsHashTable[i]; if (item->pev) UTIL_LogPrintf("Print: %s %i %p\n", STRING(stringsHashTable[i].pev->classname), ENTINDEX(ENT(item->pev)), item->pev); for (item = stringsHashTable[i].next; item; item = item->next) UTIL_LogPrintf("Print: %s %i %p\n", STRING(item->pev->classname), ENTINDEX(ENT(item->pev)), item->pev); } } edict_t *CREATE_NAMED_ENTITY(int iClass) { edict_t *named = g_engfuncs.pfnCreateNamedEntity(iClass); if (named) AddEntityHashValue(&named->v, STRING(iClass), CLASSNAME); return named; } void REMOVE_ENTITY(edict_t *e) { if (e) g_engfuncs.pfnRemoveEntity(e); } #include "perf_counter.h" void loopPerformance(void) { CPerformanceCounter loopCounter; loopCounter.InitializePerformanceCounter(); float start = loopCounter.GetCurTime(); CBaseEntity *i; for (i = UTIL_FindEntityByString_Old(NULL, "classname", "info_player_start"); i; i = UTIL_FindEntityByString_Old(i, "classname", "info_player_start")) {} for (i = UTIL_FindEntityByString_Old(NULL, "classname", "info_player_deathmatch"); i; i = UTIL_FindEntityByString_Old(i, "classname", "info_player_deathmatch")) {} for (i = UTIL_FindEntityByString_Old(NULL, "classname", "player"); i; i = UTIL_FindEntityByString_Old(i, "classname", "player")) {} float end = loopCounter.GetCurTime(); CONSOLE_ECHO(" Time in old search loop %.4f\n", (end - start) * 1000); start = loopCounter.GetCurTime(); for (i = UTIL_FindEntityByString(NULL, "classname", "info_player_start"); i; i = UTIL_FindEntityByString(i, "classname", "info_player_start")) {} for (i = UTIL_FindEntityByString(NULL, "classname", "info_player_deathmatch"); i; i = UTIL_FindEntityByString(i, "classname", "info_player_deathmatch")) {} for (i = UTIL_FindEntityByString(NULL, "classname", "player"); i; i = UTIL_FindEntityByString(i, "classname", "player")) {} end = loopCounter.GetCurTime(); CONSOLE_ECHO(" Time in new search loop %.4f\n", (end - start) * 1000); } void CONSOLE_ECHO(char *pszMsg, ...) { va_list argptr; static char szStr[1024]; va_start(argptr, pszMsg); vsprintf(szStr, pszMsg, argptr); va_end(argptr); g_engfuncs.pfnServerPrint(szStr); } void CONSOLE_ECHO_LOGGED(char *pszMsg, ...) { va_list argptr; static char szStr[1024]; va_start(argptr, pszMsg); vsprintf(szStr, pszMsg, argptr); va_end(argptr); g_engfuncs.pfnServerPrint(szStr); UTIL_LogPrintf(szStr); } static DLL_FUNCTIONS gFunctionTable = { GameDLLInit, DispatchSpawn, DispatchThink, DispatchUse, DispatchTouch, DispatchBlocked, DispatchKeyValue, DispatchSave, DispatchRestore, DispatchObjectCollsionBox, SaveWriteFields, SaveReadFields, SaveGlobalState, RestoreGlobalState, ResetGlobalState, ClientConnect, ClientDisconnect, ClientKill, ClientPutInServer, ClientCommand, ClientUserInfoChanged, ServerActivate, ServerDeactivate, PlayerPreThink, PlayerPostThink, StartFrame, ParmsNewLevel, ParmsChangeLevel, GetGameDescription, PlayerCustomization, SpectatorConnect, SpectatorDisconnect, SpectatorThink, Sys_Error, PM_Move, PM_Init, PM_FindTextureType, SetupVisibility, UpdateClientData, AddToFullPack, CreateBaseline, RegisterEncoders, GetWeaponData, CmdStart, CmdEnd, ConnectionlessPacket, GetHullBounds, CreateInstancedBaselines, InconsistentFile, AllowLagCompensation }; int GetEntityAPI(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion) { if (!pFunctionTable || interfaceVersion != INTERFACE_VERSION) return 0; memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS)); stringsHashTable.SetSize(2048); for (int i = 0; i < stringsHashTable.Count(); i++) stringsHashTable[i].next = NULL; EmptyEntityHashTable(); return 1; } void OnFreeEntPrivateData(edict_t *pEnt) { CBaseEntity *pEntity = CBaseEntity::Instance(pEnt); if (!pEntity) return; pEntity->UpdateOnRemove(); RemoveEntityHashValue(pEntity->pev, STRING(pEntity->pev->classname), CLASSNAME); } void OnGameShutdown() { //ALERT(at_logged, "Shutting down\n"); } static NEW_DLL_FUNCTIONS gNewDLLFunctions = { OnFreeEntPrivateData, OnGameShutdown, NULL }; int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { if (!pFunctionTable || *interfaceVersion != NEW_DLL_FUNCTIONS_VERSION) { *interfaceVersion = NEW_DLL_FUNCTIONS_VERSION; return 0; } pFunctionTable->pfnOnFreeEntPrivateData = gNewDLLFunctions.pfnOnFreeEntPrivateData; pFunctionTable->pfnGameShutdown = gNewDLLFunctions.pfnGameShutdown; pFunctionTable->pfnShouldCollide = gNewDLLFunctions.pfnShouldCollide; return 1; } int DispatchSpawn(edict_t *pent) { CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent); if (pEntity) { pEntity->pev->absmin = pEntity->pev->origin - Vector(1, 1, 1); pEntity->pev->absmax = pEntity->pev->origin + Vector(1, 1, 1); pEntity->Spawn(); pEntity = (CBaseEntity *)GET_PRIVATE(pent); if (pEntity) { if (g_pGameRules && !g_pGameRules->IsAllowedToSpawn(pEntity)) { ALERT(at_logged, "Trying to spawn invalid ent(IsAllowedToSpawn)\n"); return -1; } if (pEntity->pev->flags & FL_KILLME) { ALERT(at_logged, "Trying to spawn invalid ent(FL_KILLME)\n"); return -1; } if (pEntity->pev->globalname) { const globalentity_t *pGlobal = gGlobalState.EntityFromTable(pEntity->pev->globalname); if (pGlobal) { if (pGlobal->state == GLOBAL_DEAD) { ALERT(at_logged, "Trying to spawn invalid ent(FL_KILLME)\n"); return -1; } if (strcmp(STRING(gpGlobals->mapname), pGlobal->levelName)) pEntity->MakeDormant(); } else gGlobalState.EntityAdd(pEntity->pev->globalname, gpGlobals->mapname, GLOBAL_ON); } } } else { ALERT(at_logged, "Trying to spawn invalid ent\n"); } return 0; } void DispatchKeyValue(edict_t *pentKeyvalue, KeyValueData *pkvd) { if (!pkvd || !pentKeyvalue) return; EntvarsKeyvalue(VARS(pentKeyvalue), pkvd); if (pkvd->fHandled || !pkvd->szClassName) return; CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pentKeyvalue); if (pEntity) pEntity->KeyValue(pkvd); } BOOL gTouchDisabled = FALSE; void DispatchTouch(edict_t *pentTouched, edict_t *pentOther) { if (gTouchDisabled) return; CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pentTouched); CBaseEntity *pOther = (CBaseEntity *)GET_PRIVATE(pentOther); if (pEntity && pOther && !((pEntity->pev->flags | pOther->pev->flags) & FL_KILLME)) { //ALERT(at_logged, "%s touched %s\n", STRING(pEntity->pev->classname), STRING(pOther->pev->classname)); pEntity->Touch(pOther); } } void DispatchUse(edict_t *pentUsed, edict_t *pentOther) { CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pentUsed); CBaseEntity *pOther = (CBaseEntity *)GET_PRIVATE(pentOther); if (pEntity && !(pEntity->pev->flags & FL_KILLME)) pEntity->Use(pOther, pOther, USE_TOGGLE, 0); } void DispatchThink(edict_t *pent) { CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent); if (pEntity) { if (pEntity->pev->flags & FL_DORMANT) ALERT(at_console, "Dormant entity %s is trying to think (ignoring think)!!\n", STRING(pEntity->pev->classname)); else pEntity->Think(); } } void DispatchBlocked(edict_t *pentBlocked, edict_t *pentOther) { CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pentBlocked); CBaseEntity *pOther = (CBaseEntity *)GET_PRIVATE(pentOther); if (pEntity) pEntity->Blocked(pOther); } void DispatchSave(edict_t *pent, SAVERESTOREDATA *pSaveData) { CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent); if (pEntity && pSaveData) { ENTITYTABLE *pTable = &pSaveData->pTable[pSaveData->currentIndex]; if (pTable->pent != pent) ALERT(at_error, "ENTITY TABLE OR INDEX IS WRONG!!!!\n"); if (pEntity->ObjectCaps() & FCAP_DONT_SAVE) return; if (pEntity->pev->movetype == MOVETYPE_PUSH) { float delta = pEntity->pev->nextthink - pEntity->pev->ltime; pEntity->pev->ltime = gpGlobals->time; pEntity->pev->nextthink = pEntity->pev->ltime + delta; } pTable->location = pSaveData->size; pTable->classname = pEntity->pev->classname; CSave saveHelper(pSaveData); pEntity->Save(saveHelper); pTable->size = pSaveData->size - pTable->location; } } CBaseEntity *FindGlobalEntity(string_t classname, string_t globalname) { edict_t *pent = FIND_ENTITY_BY_STRING(NULL, "globalname", STRING(globalname)); CBaseEntity *pReturn = CBaseEntity::Instance(pent); if (!pReturn) return NULL; if (strcmp(STRING(pReturn->pev->classname), STRING(classname))) { ALERT(at_console, "Global entity found %s, wrong class %s\n", STRING(globalname), STRING(pReturn->pev->classname)); return NULL; } return pReturn; } int DispatchRestore(edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity) { CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent); if (pEntity && pSaveData) { Vector oldOffset; CRestore restoreHelper(pSaveData); if (globalEntity) { entvars_t tmpVars; CRestore tmpRestore(pSaveData); tmpRestore.PrecacheMode(0); tmpRestore.ReadEntVars("ENTVARS", &tmpVars); pSaveData->size = pSaveData->pTable[pSaveData->currentIndex].location; pSaveData->pCurrentData = pSaveData->pBaseData + pSaveData->size; const globalentity_t *pGlobal = gGlobalState.EntityFromTable(tmpVars.globalname); if (strcmp(pSaveData->szCurrentMapName, pGlobal->levelName)) return 0; oldOffset = pSaveData->vecLandmarkOffset; CBaseEntity *pNewEntity = FindGlobalEntity(tmpVars.classname, tmpVars.globalname); if (!pNewEntity) return 0; restoreHelper.SetGlobalMode(1); pSaveData->vecLandmarkOffset = (pSaveData->vecLandmarkOffset - pNewEntity->pev->mins) + tmpVars.mins; pEntity = pNewEntity; pent = ENT(pEntity->pev); gGlobalState.EntityUpdate(pEntity->pev->globalname, gpGlobals->mapname); } if (pEntity->ObjectCaps() & FCAP_MUST_SPAWN) { pEntity->Restore(restoreHelper); pEntity->Spawn(); } else { pEntity->Restore(restoreHelper); pEntity->Precache(); } pEntity = (CBaseEntity *)GET_PRIVATE(pent); if (globalEntity) { pSaveData->vecLandmarkOffset = oldOffset; if (pEntity) { UTIL_SetOrigin(pEntity->pev, pEntity->pev->origin); pEntity->OverrideReset(); } } else if (pEntity && pEntity->pev->globalname) { const globalentity_t *pGlobal = gGlobalState.EntityFromTable(pEntity->pev->globalname); if (pGlobal) { if (pGlobal->state == GLOBAL_DEAD) return -1; if (strcmp(STRING(gpGlobals->mapname), pGlobal->levelName)) pEntity->MakeDormant(); } else { ALERT(at_error, "Global Entity %s (%s) not in table!!!\n", STRING(pEntity->pev->globalname), STRING(pEntity->pev->classname)); gGlobalState.EntityAdd(pEntity->pev->globalname, gpGlobals->mapname, GLOBAL_ON); } } } return 0; } void SetObjectCollisionBox(entvars_t *pev); void DispatchObjectCollsionBox(edict_t *pent) { CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent); if (pEntity) pEntity->SetObjectCollisionBox(); else SetObjectCollisionBox(&pent->v); } void SaveWriteFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount) { CSave saveHelper(pSaveData); saveHelper.WriteFields(pname, pBaseData, pFields, fieldCount); } void SaveReadFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount) { CRestore restoreHelper(pSaveData); restoreHelper.ReadFields(pname, pBaseData, pFields, fieldCount); } edict_t *EHANDLE::Get(void) { if (!m_pent) return NULL; if (m_pent->serialnumber != m_serialnumber) return NULL; return m_pent; } edict_t *EHANDLE::Set(edict_t *pent) { m_pent = pent; if (pent) m_serialnumber = m_pent->serialnumber; return pent; } EHANDLE::operator CBaseEntity *(void) { return (CBaseEntity *)GET_PRIVATE(Get()); } CBaseEntity *EHANDLE::operator = (CBaseEntity *pEntity) { if (pEntity) { m_pent = ENT(pEntity->pev); if (m_pent) m_serialnumber = m_pent->serialnumber; } else { m_pent = NULL; m_serialnumber = 0; } return pEntity; } EHANDLE::operator int(void) { return Get() != NULL; } CBaseEntity *EHANDLE::operator ->(void) { return (CBaseEntity *)GET_PRIVATE(Get()); } int CBaseEntity::TakeHealth(float flHealth, int bitsDamageType) { if (!pev->takedamage) return 0; if (pev->health >= pev->max_health) return 0; pev->health += flHealth; if (pev->health > pev->max_health) pev->health = pev->max_health; return 1; } int CBaseEntity::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) { if (!pev->takedamage) return 0; g_vecAttackDir = (pevInflictor->origin - VecBModelOrigin(pev)).Normalize(); 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).Normalize(); float flForce = flDamage * ((32 * 32 * 72.0) / (pev->size.x * pev->size.y * pev->size.z)) * 5; if (flForce > 1000) flForce = 1000; pev->velocity = pev->velocity + vecDir * flForce; } pev->health -= flDamage; if (pev->health <= 0) { Killed(pevAttacker, GIB_NORMAL); return 0; } return 1; } void CBaseEntity::Killed(entvars_t *pevAttacker, int iGib) { pev->takedamage = DAMAGE_NO; pev->deadflag = DEAD_DEAD; UTIL_Remove(this); } CBaseEntity *CBaseEntity::GetNextTarget(void) { if (FStringNull(pev->target)) return NULL; edict_t *pTarget = FIND_ENTITY_BY_TARGETNAME(NULL, STRING(pev->target)); if (FNullEnt(pTarget)) return NULL; return Instance(pTarget); } TYPEDESCRIPTION CBaseEntity::m_SaveData[] = { DEFINE_FIELD(CBaseEntity, m_pGoalEnt, FIELD_CLASSPTR), DEFINE_FIELD(CBaseEntity, m_pfnThink, FIELD_FUNCTION), DEFINE_FIELD(CBaseEntity, m_pfnTouch, FIELD_FUNCTION), DEFINE_FIELD(CBaseEntity, m_pfnUse, FIELD_FUNCTION), DEFINE_FIELD(CBaseEntity, m_pfnBlocked, FIELD_FUNCTION) }; int CBaseEntity::Save(CSave &save) { if (save.WriteEntVars("ENTVARS", pev)) return save.WriteFields("BASE", this, m_SaveData, ARRAYSIZE(m_SaveData)); return 0; } int CBaseEntity::Restore(CRestore &restore) { int status = restore.ReadEntVars("ENTVARS", pev); if (status) status = restore.ReadFields("BASE", this, m_SaveData, ARRAYSIZE(m_SaveData)); if (pev->modelindex != 0 && !FStringNull(pev->model)) { Vector mins = pev->mins; Vector maxs = pev->maxs; PRECACHE_MODEL((char *)STRING(pev->model)); SET_MODEL(ENT(pev), STRING(pev->model)); UTIL_SetSize(pev, mins, maxs); } return status; } void SetObjectCollisionBox(entvars_t *pev) { if (pev->solid == SOLID_BSP && (pev->angles.x || pev->angles.y || pev->angles.z)) { float v, max = 0; int i; 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 CBaseEntity::SetObjectCollisionBox(void) { ::SetObjectCollisionBox(pev); } int CBaseEntity::Intersects(CBaseEntity *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 CBaseEntity::MakeDormant(void) { pev->flags |= FL_DORMANT; pev->solid = SOLID_NOT; pev->movetype = MOVETYPE_NONE; pev->effects |= EF_NODRAW; pev->nextthink = 0; UTIL_SetOrigin(pev, pev->origin); } int CBaseEntity::IsDormant(void) { return pev->flags & FL_DORMANT; } BOOL CBaseEntity::IsInWorld(void) { if (pev->origin.x >= 4096 || pev->origin.y >= 4096 || pev->origin.z >= 4096) return FALSE; if (pev->origin.x <= -4096 || pev->origin.y <= -4096 || pev->origin.z <= -4096) return FALSE; if (pev->velocity.x >= 2000 || pev->velocity.y >= 2000 || pev->velocity.z >= 2000) return FALSE; if (pev->velocity.x <= -2000 || pev->velocity.y <= -2000 || pev->velocity.z <= -2000) return FALSE; return TRUE; } int CBaseEntity::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 CBaseEntity::DamageDecal(int bitsDamageType) { if (pev->rendermode == kRenderTransAlpha) return -1; if (pev->rendermode != kRenderNormal) return DECAL_BPROOF1; return RANDOM_LONG(DECAL_GUNSHOT4, DECAL_GUNSHOT5); } CBaseEntity *CBaseEntity::Create(char *szName, const Vector &vecOrigin, const Vector &vecAngles, edict_t *pentOwner) { edict_t *pent = CREATE_NAMED_ENTITY(MAKE_STRING(szName)); if (FNullEnt(pent)) { ALERT(at_console, "NULL Ent in Create!\n"); return NULL; } CBaseEntity *pEntity = Instance(pent); pEntity->pev->owner = pentOwner; pEntity->pev->origin = vecOrigin; pEntity->pev->angles = vecAngles; DispatchSpawn(pEntity->edict()); return pEntity; }