2013-08-30 13:34:05 -07:00
|
|
|
/***
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
****/
|
|
|
|
/*
|
|
|
|
|
|
|
|
===== world.cpp ========================================================
|
|
|
|
|
|
|
|
precaches and defs for entities and other data that must always be available.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "extdll.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "cbase.h"
|
|
|
|
#include "nodes.h"
|
|
|
|
#include "soundent.h"
|
|
|
|
#include "client.h"
|
|
|
|
#include "decals.h"
|
|
|
|
#include "skill.h"
|
|
|
|
#include "effects.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "weapons.h"
|
|
|
|
#include "gamerules.h"
|
|
|
|
#include "teamplay_gamerules.h"
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
CGlobalState gGlobalState;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-03-05 20:54:33 +01:00
|
|
|
extern void W_Precache();
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
//
|
|
|
|
// This must match the list in util.h
|
|
|
|
//
|
|
|
|
DLL_DECALLIST gDecals[] = {
|
2021-11-28 16:54:48 +01:00
|
|
|
{"{shot1", 0}, // DECAL_GUNSHOT1
|
|
|
|
{"{shot2", 0}, // DECAL_GUNSHOT2
|
|
|
|
{"{shot3", 0}, // DECAL_GUNSHOT3
|
|
|
|
{"{shot4", 0}, // DECAL_GUNSHOT4
|
|
|
|
{"{shot5", 0}, // DECAL_GUNSHOT5
|
|
|
|
{"{lambda01", 0}, // DECAL_LAMBDA1
|
|
|
|
{"{lambda02", 0}, // DECAL_LAMBDA2
|
|
|
|
{"{lambda03", 0}, // DECAL_LAMBDA3
|
|
|
|
{"{lambda04", 0}, // DECAL_LAMBDA4
|
|
|
|
{"{lambda05", 0}, // DECAL_LAMBDA5
|
|
|
|
{"{lambda06", 0}, // DECAL_LAMBDA6
|
|
|
|
{"{scorch1", 0}, // DECAL_SCORCH1
|
|
|
|
{"{scorch2", 0}, // DECAL_SCORCH2
|
|
|
|
{"{blood1", 0}, // DECAL_BLOOD1
|
|
|
|
{"{blood2", 0}, // DECAL_BLOOD2
|
|
|
|
{"{blood3", 0}, // DECAL_BLOOD3
|
|
|
|
{"{blood4", 0}, // DECAL_BLOOD4
|
|
|
|
{"{blood5", 0}, // DECAL_BLOOD5
|
|
|
|
{"{blood6", 0}, // DECAL_BLOOD6
|
|
|
|
{"{yblood1", 0}, // DECAL_YBLOOD1
|
|
|
|
{"{yblood2", 0}, // DECAL_YBLOOD2
|
|
|
|
{"{yblood3", 0}, // DECAL_YBLOOD3
|
|
|
|
{"{yblood4", 0}, // DECAL_YBLOOD4
|
|
|
|
{"{yblood5", 0}, // DECAL_YBLOOD5
|
|
|
|
{"{yblood6", 0}, // DECAL_YBLOOD6
|
|
|
|
{"{break1", 0}, // DECAL_GLASSBREAK1
|
|
|
|
{"{break2", 0}, // DECAL_GLASSBREAK2
|
|
|
|
{"{break3", 0}, // DECAL_GLASSBREAK3
|
|
|
|
{"{bigshot1", 0}, // DECAL_BIGSHOT1
|
|
|
|
{"{bigshot2", 0}, // DECAL_BIGSHOT2
|
|
|
|
{"{bigshot3", 0}, // DECAL_BIGSHOT3
|
|
|
|
{"{bigshot4", 0}, // DECAL_BIGSHOT4
|
|
|
|
{"{bigshot5", 0}, // DECAL_BIGSHOT5
|
|
|
|
{"{spit1", 0}, // DECAL_SPIT1
|
|
|
|
{"{spit2", 0}, // DECAL_SPIT2
|
|
|
|
{"{bproof1", 0}, // DECAL_BPROOF1
|
|
|
|
{"{gargstomp", 0}, // DECAL_GARGSTOMP1, // Gargantua stomp crack
|
|
|
|
{"{smscorch1", 0}, // DECAL_SMALLSCORCH1, // Small scorch mark
|
|
|
|
{"{smscorch2", 0}, // DECAL_SMALLSCORCH2, // Small scorch mark
|
|
|
|
{"{smscorch3", 0}, // DECAL_SMALLSCORCH3, // Small scorch mark
|
|
|
|
{"{mommablob", 0}, // DECAL_MOMMABIRTH // BM Birth spray
|
|
|
|
{"{mommablob", 0}, // DECAL_MOMMASPLAT // BM Mortar spray?? need decal
|
2013-08-30 13:34:05 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============================================================================
|
|
|
|
|
|
|
|
BODY QUE
|
|
|
|
|
|
|
|
==============================================================================
|
|
|
|
*/
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
#define SF_DECAL_NOTINDEATHMATCH 2048
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
class CDecal : public CBaseEntity
|
|
|
|
{
|
|
|
|
public:
|
2021-11-28 16:54:48 +01:00
|
|
|
void Spawn() override;
|
|
|
|
bool KeyValue(KeyValueData* pkvd) override;
|
|
|
|
void EXPORT StaticDecal();
|
|
|
|
void EXPORT TriggerDecal(CBaseEntity* pActivator, CBaseEntity* pCaller, USE_TYPE useType, float value);
|
2013-08-30 13:34:05 -07:00
|
|
|
};
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
LINK_ENTITY_TO_CLASS(infodecal, CDecal);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// UNDONE: These won't get sent to joining players in multi-player
|
2021-11-29 20:31:17 +01:00
|
|
|
void CDecal::Spawn()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pev->skin < 0 || (0 != gpGlobals->deathmatch && FBitSet(pev->spawnflags, SF_DECAL_NOTINDEATHMATCH)))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
REMOVE_ENTITY(ENT(pev));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (FStringNull(pev->targetname))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
SetThink(&CDecal::StaticDecal);
|
2013-08-30 13:34:05 -07:00
|
|
|
// if there's no targetname, the decal will spray itself on as soon as the world is done spawning.
|
|
|
|
pev->nextthink = gpGlobals->time;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// if there IS a targetname, the decal sprays itself on when it is triggered.
|
2021-11-28 16:54:48 +01:00
|
|
|
SetThink(&CDecal::SUB_DoNothing);
|
|
|
|
SetUse(&CDecal::TriggerDecal);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CDecal::TriggerDecal(CBaseEntity* pActivator, CBaseEntity* pCaller, USE_TYPE useType, float value)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// this is set up as a USE function for infodecals that have targetnames, so that the
|
|
|
|
// decal doesn't get applied until it is fired. (usually by a scripted sequence)
|
|
|
|
TraceResult trace;
|
2021-11-28 16:54:48 +01:00
|
|
|
int entityIndex;
|
|
|
|
|
|
|
|
UTIL_TraceLine(pev->origin - Vector(5, 5, 5), pev->origin + Vector(5, 5, 5), ignore_monsters, ENT(pev), &trace);
|
|
|
|
|
|
|
|
MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY);
|
|
|
|
WRITE_BYTE(TE_BSPDECAL);
|
|
|
|
WRITE_COORD(pev->origin.x);
|
|
|
|
WRITE_COORD(pev->origin.y);
|
|
|
|
WRITE_COORD(pev->origin.z);
|
|
|
|
WRITE_SHORT((int)pev->skin);
|
|
|
|
entityIndex = (short)ENTINDEX(trace.pHit);
|
|
|
|
WRITE_SHORT(entityIndex);
|
|
|
|
if (0 != entityIndex)
|
|
|
|
WRITE_SHORT((int)VARS(trace.pHit)->modelindex);
|
2013-08-30 13:34:05 -07:00
|
|
|
MESSAGE_END();
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
SetThink(&CDecal::SUB_Remove);
|
2013-08-30 13:34:05 -07:00
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CDecal::StaticDecal()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
TraceResult trace;
|
2021-11-28 16:54:48 +01:00
|
|
|
int entityIndex, modelIndex;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
UTIL_TraceLine(pev->origin - Vector(5, 5, 5), pev->origin + Vector(5, 5, 5), ignore_monsters, ENT(pev), &trace);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
entityIndex = (short)ENTINDEX(trace.pHit);
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != entityIndex)
|
2013-08-30 13:34:05 -07:00
|
|
|
modelIndex = (int)VARS(trace.pHit)->modelindex;
|
|
|
|
else
|
|
|
|
modelIndex = 0;
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
g_engfuncs.pfnStaticDecal(pev->origin, (int)pev->skin, entityIndex, modelIndex);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
SUB_Remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
bool CDecal::KeyValue(KeyValueData* pkvd)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
if (FStrEq(pkvd->szKeyName, "texture"))
|
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
pev->skin = DECAL_INDEX(pkvd->szValue);
|
|
|
|
|
2021-11-28 15:32:26 +01:00
|
|
|
if (pev->skin < 0)
|
|
|
|
{
|
|
|
|
ALERT(at_console, "Can't find decal %s\n", pkvd->szValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 15:32:26 +01:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
return CBaseEntity::KeyValue(pkvd);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Body queue class here.... It's really just CBaseEntity
|
|
|
|
class CCorpse : public CBaseEntity
|
|
|
|
{
|
2021-03-05 23:07:22 +01:00
|
|
|
int ObjectCaps() override { return FCAP_DONT_SAVE; }
|
2013-08-30 13:34:05 -07:00
|
|
|
};
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
LINK_ENTITY_TO_CLASS(bodyque, CCorpse);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-03-05 20:54:33 +01:00
|
|
|
static void InitBodyQue()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
string_t istrClassname = MAKE_STRING("bodyque");
|
|
|
|
|
|
|
|
g_pBodyQueueHead = CREATE_NAMED_ENTITY(istrClassname);
|
|
|
|
entvars_t* pev = VARS(g_pBodyQueueHead);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// Reserve 3 more slots for dead bodies
|
2021-11-28 16:54:48 +01:00
|
|
|
for (int i = 0; i < 3; i++)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
pev->owner = CREATE_NAMED_ENTITY(istrClassname);
|
2013-08-30 13:34:05 -07:00
|
|
|
pev = VARS(pev->owner);
|
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
pev->owner = g_pBodyQueueHead;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// make a body que entry for the given ent so the ent can be respawned elsewhere
|
|
|
|
//
|
|
|
|
// GLOBALS ASSUMED SET: g_eoBodyQueueHead
|
|
|
|
//
|
2021-11-28 16:54:48 +01:00
|
|
|
void CopyToBodyQue(entvars_t* pev)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 15:32:26 +01:00
|
|
|
if ((pev->effects & EF_NODRAW) != 0)
|
2013-08-30 13:34:05 -07:00
|
|
|
return;
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
entvars_t* pevHead = VARS(g_pBodyQueueHead);
|
|
|
|
|
|
|
|
pevHead->angles = pev->angles;
|
|
|
|
pevHead->model = pev->model;
|
|
|
|
pevHead->modelindex = pev->modelindex;
|
|
|
|
pevHead->frame = pev->frame;
|
|
|
|
pevHead->colormap = pev->colormap;
|
|
|
|
pevHead->movetype = MOVETYPE_TOSS;
|
|
|
|
pevHead->velocity = pev->velocity;
|
|
|
|
pevHead->flags = 0;
|
|
|
|
pevHead->deadflag = pev->deadflag;
|
|
|
|
pevHead->renderfx = kRenderFxDeadPlayer;
|
|
|
|
pevHead->renderamt = ENTINDEX(ENT(pev));
|
|
|
|
|
|
|
|
pevHead->effects = pev->effects | EF_NOINTERP;
|
2013-08-30 13:34:05 -07:00
|
|
|
//pevHead->goalstarttime = pev->goalstarttime;
|
|
|
|
//pevHead->goalframe = pev->goalframe;
|
|
|
|
//pevHead->goalendtime = pev->goalendtime ;
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
pevHead->sequence = pev->sequence;
|
|
|
|
pevHead->animtime = pev->animtime;
|
|
|
|
|
|
|
|
UTIL_SetOrigin(pevHead, pev->origin);
|
|
|
|
UTIL_SetSize(pevHead, pev->mins, pev->maxs);
|
|
|
|
g_pBodyQueueHead = pevHead->owner;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-05 20:54:33 +01:00
|
|
|
CGlobalState::CGlobalState()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
Reset();
|
|
|
|
}
|
|
|
|
|
2021-03-05 20:54:33 +01:00
|
|
|
void CGlobalState::Reset()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
m_pList = NULL;
|
2013-08-30 13:34:05 -07:00
|
|
|
m_listCount = 0;
|
|
|
|
}
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
globalentity_t* CGlobalState::Find(string_t globalname)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (FStringNull(globalname))
|
2013-08-30 13:34:05 -07:00
|
|
|
return NULL;
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
globalentity_t* pTest;
|
|
|
|
const char* pEntityName = STRING(globalname);
|
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
pTest = m_pList;
|
2021-11-28 16:54:48 +01:00
|
|
|
while (pTest)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (FStrEq(pEntityName, pTest->name))
|
2013-08-30 13:34:05 -07:00
|
|
|
break;
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
pTest = pTest->pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pTest;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This is available all the time now on impulse 104, remove later
|
|
|
|
//#ifdef _DEBUG
|
2021-11-29 20:31:17 +01:00
|
|
|
void CGlobalState::DumpGlobals()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
static const char* estates[] = {"Off", "On", "Dead"};
|
|
|
|
globalentity_t* pTest;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
ALERT(at_console, "-- Globals --\n");
|
2013-08-30 13:34:05 -07:00
|
|
|
pTest = m_pList;
|
2021-11-28 16:54:48 +01:00
|
|
|
while (pTest)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
ALERT(at_console, "%s: %s (%s)\n", pTest->name, pTest->levelName, estates[pTest->state]);
|
2013-08-30 13:34:05 -07:00
|
|
|
pTest = pTest->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//#endif
|
|
|
|
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CGlobalState::EntityAdd(string_t globalname, string_t mapName, GLOBALESTATE state)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
ASSERT(!Find(globalname));
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
globalentity_t* pNewEntity = (globalentity_t*)calloc(sizeof(globalentity_t), 1);
|
|
|
|
ASSERT(pNewEntity != NULL);
|
2013-08-30 13:34:05 -07:00
|
|
|
pNewEntity->pNext = m_pList;
|
|
|
|
m_pList = pNewEntity;
|
2021-11-28 16:54:48 +01:00
|
|
|
strcpy(pNewEntity->name, STRING(globalname));
|
|
|
|
strcpy(pNewEntity->levelName, STRING(mapName));
|
2013-08-30 13:34:05 -07:00
|
|
|
pNewEntity->state = state;
|
|
|
|
m_listCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CGlobalState::EntitySetState(string_t globalname, GLOBALESTATE state)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
globalentity_t* pEnt = Find(globalname);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pEnt)
|
2013-08-30 13:34:05 -07:00
|
|
|
pEnt->state = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
const globalentity_t* CGlobalState::EntityFromTable(string_t globalname)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
globalentity_t* pEnt = Find(globalname);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
return pEnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
GLOBALESTATE CGlobalState::EntityGetState(string_t globalname)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
globalentity_t* pEnt = Find(globalname);
|
|
|
|
if (pEnt)
|
2013-08-30 13:34:05 -07:00
|
|
|
return pEnt->state;
|
|
|
|
|
|
|
|
return GLOBAL_OFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Global Savedata for Delay
|
2021-11-28 16:54:48 +01:00
|
|
|
TYPEDESCRIPTION CGlobalState::m_SaveData[] =
|
|
|
|
{
|
|
|
|
DEFINE_FIELD(CGlobalState, m_listCount, FIELD_INTEGER),
|
2013-08-30 13:34:05 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
// Global Savedata for Delay
|
2021-11-28 16:54:48 +01:00
|
|
|
TYPEDESCRIPTION gGlobalEntitySaveData[] =
|
|
|
|
{
|
|
|
|
DEFINE_ARRAY(globalentity_t, name, FIELD_CHARACTER, 64),
|
|
|
|
DEFINE_ARRAY(globalentity_t, levelName, FIELD_CHARACTER, 32),
|
|
|
|
DEFINE_FIELD(globalentity_t, state, FIELD_INTEGER),
|
2013-08-30 13:34:05 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
bool CGlobalState::Save(CSave& save)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
int i;
|
2021-11-28 16:54:48 +01:00
|
|
|
globalentity_t* pEntity;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!save.WriteFields("GLOBAL", this, m_SaveData, ARRAYSIZE(m_SaveData)))
|
2021-11-28 15:32:26 +01:00
|
|
|
return false;
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
pEntity = m_pList;
|
2021-11-28 16:54:48 +01:00
|
|
|
for (i = 0; i < m_listCount && pEntity; i++)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!save.WriteFields("GENT", pEntity, gGlobalEntitySaveData, ARRAYSIZE(gGlobalEntitySaveData)))
|
2021-11-28 15:32:26 +01:00
|
|
|
return false;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
pEntity = pEntity->pNext;
|
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
bool CGlobalState::Restore(CRestore& restore)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
int i, listCount;
|
|
|
|
globalentity_t tmpEntity;
|
|
|
|
|
|
|
|
|
|
|
|
ClearStates();
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!restore.ReadFields("GLOBAL", this, m_SaveData, ARRAYSIZE(m_SaveData)))
|
2021-11-28 15:32:26 +01:00
|
|
|
return false;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
listCount = m_listCount; // Get new list count
|
|
|
|
m_listCount = 0; // Clear loaded data
|
|
|
|
|
|
|
|
for (i = 0; i < listCount; i++)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!restore.ReadFields("GENT", &tmpEntity, gGlobalEntitySaveData, ARRAYSIZE(gGlobalEntitySaveData)))
|
2021-11-28 15:32:26 +01:00
|
|
|
return false;
|
2021-11-28 16:54:48 +01:00
|
|
|
EntityAdd(MAKE_STRING(tmpEntity.name), MAKE_STRING(tmpEntity.levelName), tmpEntity.state);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
void CGlobalState::EntityUpdate(string_t globalname, string_t mapname)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
globalentity_t* pEnt = Find(globalname);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pEnt)
|
|
|
|
strcpy(pEnt->levelName, STRING(mapname));
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-05 20:54:33 +01:00
|
|
|
void CGlobalState::ClearStates()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
globalentity_t* pFree = m_pList;
|
|
|
|
while (pFree)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
globalentity_t* pNext = pFree->pNext;
|
|
|
|
free(pFree);
|
2013-08-30 13:34:05 -07:00
|
|
|
pFree = pNext;
|
|
|
|
}
|
|
|
|
Reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
void SaveGlobalState(SAVERESTOREDATA* pSaveData)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-29 19:48:37 +01:00
|
|
|
if (!CSaveRestoreBuffer::IsValidSaveRestoreData(pSaveData))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CSave saveHelper(*pSaveData);
|
2021-11-28 16:54:48 +01:00
|
|
|
gGlobalState.Save(saveHelper);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
void RestoreGlobalState(SAVERESTOREDATA* pSaveData)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-29 19:48:37 +01:00
|
|
|
if (!CSaveRestoreBuffer::IsValidSaveRestoreData(pSaveData))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CRestore restoreHelper(*pSaveData);
|
2021-11-28 16:54:48 +01:00
|
|
|
gGlobalState.Restore(restoreHelper);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-05 20:54:33 +01:00
|
|
|
void ResetGlobalState()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
gGlobalState.ClearStates();
|
2021-11-28 16:54:48 +01:00
|
|
|
gInitHUD = true; // Init the HUD on a new game / load game
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// moved CWorld class definition to cbase.h
|
|
|
|
//=======================
|
|
|
|
// CWorld
|
|
|
|
//
|
|
|
|
// This spawns first when each level begins.
|
|
|
|
//=======================
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
LINK_ENTITY_TO_CLASS(worldspawn, CWorld);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
#define SF_WORLD_DARK 0x0001 // Fade from black at startup
|
|
|
|
#define SF_WORLD_TITLE 0x0002 // Display game title at startup
|
|
|
|
#define SF_WORLD_FORCETEAM 0x0004 // Force teams
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CWorld::Spawn()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-19 13:43:33 +01:00
|
|
|
g_fGameOver = false;
|
2021-11-28 16:54:48 +01:00
|
|
|
Precache();
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CWorld::Precache()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
g_pLastSpawn = NULL;
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
#if 1
|
|
|
|
CVAR_SET_STRING("sv_gravity", "800"); // 67ft/sec
|
|
|
|
CVAR_SET_STRING("sv_stepsize", "18");
|
|
|
|
#else
|
|
|
|
CVAR_SET_STRING("sv_gravity", "384"); // 32ft/sec
|
|
|
|
CVAR_SET_STRING("sv_stepsize", "24");
|
|
|
|
#endif
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
CVAR_SET_STRING("room_type", "0"); // clear DSP
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// Set up game rules
|
2021-11-30 00:20:27 +01:00
|
|
|
delete g_pGameRules;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
g_pGameRules = InstallGameRules();
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
//!!!UNDONE why is there so much Spawn code in the Precache function? I'll just keep it here
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
///!!!LATER - do we want a sound ent in deathmatch? (sjb)
|
|
|
|
//pSoundEnt = CBaseEntity::Create( "soundent", g_vecZero, g_vecZero, edict() );
|
2021-11-28 16:54:48 +01:00
|
|
|
pSoundEnt = GetClassPtr((CSoundEnt*)NULL);
|
2013-08-30 13:34:05 -07:00
|
|
|
pSoundEnt->Spawn();
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!pSoundEnt)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
ALERT(at_console, "**COULD NOT CREATE SOUNDENT**\n");
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
InitBodyQue();
|
2021-11-28 16:54:48 +01:00
|
|
|
|
|
|
|
// init sentence group playback stuff from sentences.txt.
|
|
|
|
// ok to call this multiple times, calls after first are ignored.
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
SENTENCEG_Init();
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
// init texture type array from materials.txt
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
TEXTURETYPE_Init();
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
// the area based ambient sounds MUST be the first precache_sounds
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
// player precaches
|
|
|
|
W_Precache(); // get weapon precaches
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
ClientPrecache();
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
// sounds used from C physics code
|
|
|
|
PRECACHE_SOUND("common/null.wav"); // clears sound channels
|
|
|
|
|
|
|
|
PRECACHE_SOUND("items/suitchargeok1.wav"); //!!! temporary sound for respawning weapons.
|
|
|
|
PRECACHE_SOUND("items/gunpickup2.wav"); // player picks up a gun.
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
PRECACHE_SOUND("common/bodydrop3.wav"); // dead bodies hitting the ground (animation events)
|
|
|
|
PRECACHE_SOUND("common/bodydrop4.wav");
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
g_Language = (int)CVAR_GET_FLOAT("sv_language");
|
|
|
|
if (g_Language == LANGUAGE_GERMAN)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
PRECACHE_MODEL("models/germangibs.mdl");
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
PRECACHE_MODEL("models/hgibs.mdl");
|
|
|
|
PRECACHE_MODEL("models/agibs.mdl");
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
PRECACHE_SOUND("weapons/ric1.wav");
|
|
|
|
PRECACHE_SOUND("weapons/ric2.wav");
|
|
|
|
PRECACHE_SOUND("weapons/ric3.wav");
|
|
|
|
PRECACHE_SOUND("weapons/ric4.wav");
|
|
|
|
PRECACHE_SOUND("weapons/ric5.wav");
|
|
|
|
//
|
|
|
|
// Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
|
|
|
|
//
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// 0 normal
|
|
|
|
LIGHT_STYLE(0, "m");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 1 FLICKER (first variety)
|
|
|
|
LIGHT_STYLE(1, "mmnmmommommnonmmonqnmmo");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 2 SLOW STRONG PULSE
|
|
|
|
LIGHT_STYLE(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 3 CANDLE (first variety)
|
|
|
|
LIGHT_STYLE(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 4 FAST STROBE
|
|
|
|
LIGHT_STYLE(4, "mamamamamama");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 5 GENTLE PULSE 1
|
2021-11-28 16:54:48 +01:00
|
|
|
LIGHT_STYLE(5, "jklmnopqrstuvwxyzyxwvutsrqponmlkj");
|
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 6 FLICKER (second variety)
|
|
|
|
LIGHT_STYLE(6, "nmonqnmomnmomomno");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 7 CANDLE (second variety)
|
|
|
|
LIGHT_STYLE(7, "mmmaaaabcdefgmmmmaaaammmaamm");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 8 CANDLE (third variety)
|
|
|
|
LIGHT_STYLE(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 9 SLOW STROBE (fourth variety)
|
|
|
|
LIGHT_STYLE(9, "aaaaaaaazzzzzzzz");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 10 FLUORESCENT FLICKER
|
|
|
|
LIGHT_STYLE(10, "mmamammmmammamamaaamammma");
|
|
|
|
|
|
|
|
// 11 SLOW PULSE NOT FADE TO BLACK
|
|
|
|
LIGHT_STYLE(11, "abcdefghijklmnopqrrqponmlkjihgfedcba");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// 12 UNDERWATER LIGHT MUTATION
|
|
|
|
// this light only distorts the lightmap - no contribution
|
|
|
|
// is made to the brightness of affected surfaces
|
|
|
|
LIGHT_STYLE(12, "mmnnmmnnnmmnn");
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
// styles 32-62 are assigned by the light program for switchable lights
|
|
|
|
|
|
|
|
// 63 testing
|
|
|
|
LIGHT_STYLE(63, "a");
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
for (int i = 0; i < ARRAYSIZE(gDecals); i++)
|
|
|
|
gDecals[i].index = DECAL_INDEX(gDecals[i].name);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
// init the WorldGraph.
|
2013-08-30 13:34:05 -07:00
|
|
|
WorldGraph.InitGraph();
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
// make sure the .NOD file is newer than the .BSP file.
|
|
|
|
if (!WorldGraph.CheckNODFile((char*)STRING(gpGlobals->mapname)))
|
|
|
|
{ // NOD file is not present, or is older than the BSP file.
|
|
|
|
WorldGraph.AllocNodes();
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
else
|
2021-11-28 16:54:48 +01:00
|
|
|
{ // Load the node graph for this level
|
|
|
|
if (!WorldGraph.FLoadGraph((char*)STRING(gpGlobals->mapname)))
|
|
|
|
{ // couldn't load, so alloc and prepare to build a graph.
|
|
|
|
ALERT(at_console, "*Error opening .NOD file\n");
|
|
|
|
WorldGraph.AllocNodes();
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
ALERT(at_console, "\n*Graph Loaded!\n");
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pev->speed > 0)
|
|
|
|
CVAR_SET_FLOAT("sv_zmax", pev->speed);
|
2013-08-30 13:34:05 -07:00
|
|
|
else
|
2021-11-28 16:54:48 +01:00
|
|
|
CVAR_SET_FLOAT("sv_zmax", 4096);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!FStringNull(pev->netname))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
ALERT(at_aiconsole, "Chapter title: %s\n", STRING(pev->netname));
|
|
|
|
CBaseEntity* pEntity = CBaseEntity::Create("env_message", g_vecZero, g_vecZero, NULL);
|
|
|
|
if (pEntity)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
pEntity->SetThink(&CBaseEntity::SUB_CallUseToggle);
|
2013-08-30 13:34:05 -07:00
|
|
|
pEntity->pev->message = pev->netname;
|
|
|
|
pev->netname = 0;
|
|
|
|
pEntity->pev->nextthink = gpGlobals->time + 0.3;
|
|
|
|
pEntity->pev->spawnflags = SF_MESSAGE_ONCE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if ((pev->spawnflags & SF_WORLD_DARK) != 0)
|
|
|
|
CVAR_SET_FLOAT("v_dark", 1.0);
|
2013-08-30 13:34:05 -07:00
|
|
|
else
|
2021-11-28 16:54:48 +01:00
|
|
|
CVAR_SET_FLOAT("v_dark", 0.0);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 20:40:56 +01:00
|
|
|
gDisplayTitle = (pev->spawnflags & SF_WORLD_TITLE) != 0;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if ((pev->spawnflags & SF_WORLD_FORCETEAM) != 0)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
CVAR_SET_FLOAT("mp_defaultteam", 1);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
CVAR_SET_FLOAT("mp_defaultteam", 0);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Just to ignore the "wad" field.
|
|
|
|
//
|
2021-11-29 20:31:17 +01:00
|
|
|
bool CWorld::KeyValue(KeyValueData* pkvd)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (FStrEq(pkvd->szKeyName, "skyname"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// Sent over net now.
|
2021-11-28 16:54:48 +01:00
|
|
|
CVAR_SET_STRING("sv_skyname", pkvd->szValue);
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
else if (FStrEq(pkvd->szKeyName, "sounds"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
gpGlobals->cdAudioTrack = atoi(pkvd->szValue);
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
else if (FStrEq(pkvd->szKeyName, "WaveHeight"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// Sent over net now.
|
2021-11-28 16:54:48 +01:00
|
|
|
pev->scale = atof(pkvd->szValue) * (1.0 / 8.0);
|
|
|
|
CVAR_SET_FLOAT("sv_wateramp", pev->scale);
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
else if (FStrEq(pkvd->szKeyName, "MaxRange"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
pev->speed = atof(pkvd->szValue);
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
else if (FStrEq(pkvd->szKeyName, "chaptertitle"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
pev->netname = ALLOC_STRING(pkvd->szValue);
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
else if (FStrEq(pkvd->szKeyName, "startdark"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// UNDONE: This is a gross hack!!! The CVAR is NOT sent over the client/sever link
|
|
|
|
// but it will work for single player
|
|
|
|
int flag = atoi(pkvd->szValue);
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != flag)
|
2013-08-30 13:34:05 -07:00
|
|
|
pev->spawnflags |= SF_WORLD_DARK;
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
else if (FStrEq(pkvd->szKeyName, "newunit"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// Single player only. Clear save directory if set
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != atoi(pkvd->szValue))
|
|
|
|
CVAR_SET_FLOAT("sv_newunit", 1);
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
else if (FStrEq(pkvd->szKeyName, "gametitle"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != atoi(pkvd->szValue))
|
2013-08-30 13:34:05 -07:00
|
|
|
pev->spawnflags |= SF_WORLD_TITLE;
|
|
|
|
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
else if (FStrEq(pkvd->szKeyName, "mapteams"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
pev->team = ALLOC_STRING(pkvd->szValue);
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
else if (FStrEq(pkvd->szKeyName, "defaultteam"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != atoi(pkvd->szValue))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
pev->spawnflags |= SF_WORLD_FORCETEAM;
|
|
|
|
}
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2021-11-28 15:32:26 +01:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
return CBaseEntity::KeyValue(pkvd);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|