tracemaxs[2] = max(start[2], end[2]);
// look for embedded bmodels
- for (n = 0;n < MAX_EDICTS;n++)
+ for (n = 0;n < cl_num_entities;n++)
{
if (!cl_entities_active[n])
continue;
cl_num_brushmodel_entities = 0;
// tweak these if the game runs out
- cl_max_entities = MAX_EDICTS;
+ cl_max_entities = 256;
cl_max_static_entities = 256;
cl_max_temp_entities = 512;
cl_max_effects = 256;
cl_lightstyle = Mem_Alloc(cl_entities_mempool, cl_max_lightstyle * sizeof(lightstyle_t));
cl_brushmodel_entities = Mem_Alloc(cl_entities_mempool, cl_max_brushmodel_entities * sizeof(entity_render_t *));
- CL_Screen_NewMap();
-
- CL_Particles_Clear();
-
// LordHavoc: have to set up the baseline info for alpha and other stuff
for (i = 0;i < cl_max_entities;i++)
{
cl_entities[i].state_current = defaultstate;
}
+ CL_Screen_NewMap();
+ CL_Particles_Clear();
CL_CGVM_Clear();
}
+void CL_ExpandEntities(int num)
+{
+ int i, oldmaxentities;
+ entity_t *oldentities;
+ if (num >= cl_max_entities)
+ {
+ if (num >= MAX_EDICTS)
+ Host_Error("CL_ExpandEntities: num %i >= %i\n", num, MAX_EDICTS);
+ oldmaxentities = cl_max_entities;
+ oldentities = cl_entities;
+ cl_max_entities = (num & ~255) + 256;
+ cl_entities = Mem_Alloc(cl_entities_mempool, cl_max_entities * sizeof(entity_t));
+ memcpy(cl_entities, oldentities, oldmaxentities * sizeof(entity_t));
+ Mem_Free(oldentities);
+ for (i = oldmaxentities;i < cl_max_entities;i++)
+ {
+ cl_entities[i].state_baseline = defaultstate;
+ cl_entities[i].state_previous = defaultstate;
+ cl_entities[i].state_current = defaultstate;
+ }
+ }
+}
+
/*
=====================
CL_Disconnect
if (cl.viewentity)
CL_LinkNetworkEntity(cl_entities + cl.viewentity);
matrix = &viewmodelmatrix;
- if (e == &cl.viewent && cl.viewentity >= 0 && cl.viewentity < MAX_EDICTS && cl_entities[cl.viewentity].state_current.active)
+ if (e == &cl.viewent && cl_entities[cl.viewentity].state_current.active)
{
e->state_current.alpha = cl_entities[cl.viewentity].state_current.alpha;
e->state_current.effects = EF_NOSHADOW | (cl_entities[cl.viewentity].state_current.effects & (EF_ADDITIVE | EF_REFLECTIVE | EF_FULLBRIGHT | EF_NODEPTHTEST));
}
else
{
+ // if the tag entity is currently impossible, skip it
+ if (e->state_current.tagentity >= cl_num_entities)
+ return;
t = cl_entities + e->state_current.tagentity;
+ // if the tag entity is inactive, skip it
if (!t->state_current.active)
return;
// note: this can link to world
// entities which have a modelindex that resolved to a NULL model)
if (e->render.model && !(e->render.effects & EF_NODRAW) && r_refdef.numentities < r_refdef.maxentities)
r_refdef.entities[r_refdef.numentities++] = &e->render;
- if (cl_num_entities < e->state_current.number + 1)
- cl_num_entities = e->state_current.number + 1;
//if (cl.viewentity && e - cl_entities == cl.viewentity)
// Matrix4x4_Print(&e->render.matrix);
}
void CL_RelinkWorld(void)
{
entity_t *ent = &cl_entities[0];
- if (cl_num_entities < 1)
- cl_num_entities = 1;
cl_brushmodel_entities[cl_num_brushmodel_entities++] = &ent->render;
// FIXME: this should be done at load
Matrix4x4_CreateIdentity(&ent->render.matrix);
// start on the entity after the world
entitylinkframenumber++;
- for (i = 1;i < MAX_EDICTS;i++)
+ for (i = 1;i < cl_num_entities;i++)
{
if (cl_entities_active[i])
{
r_refdef.time = cl.time;
r_refdef.extraupdate = !r_speeds.integer;
r_refdef.numentities = 0;
- cl_num_entities = 0;
cl_num_brushmodel_entities = 0;
if (cls.state == ca_connected && cls.signon == SIGNONS)
else
sound_num = MSG_ReadByte ();
- if (sound_num >= MAX_SOUNDS)
- Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
+ MSG_ReadVector(pos, cl.protocol);
+ if (sound_num >= MAX_SOUNDS)
+ {
+ Con_Printf("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
+ return;
+ }
if (ent >= MAX_EDICTS)
- Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
-
- MSG_ReadVector(pos, cl.protocol);
+ {
+ Con_Printf("CL_ParseStartSoundPacket: ent = %i", ent);
+ return;
+ }
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0f, attenuation);
}
ent = 0;
}
+ if (ent >= cl_max_entities)
+ CL_ExpandEntities(ent);
+
// override any beam with the same entity
for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
{
cl.viewentity = (unsigned short)MSG_ReadShort ();
if (cl.viewentity >= MAX_EDICTS)
Host_Error("svc_setview >= MAX_EDICTS\n");
+ if (cl.viewentity >= cl_max_entities)
+ CL_ExpandEntities(cl.viewentity);
// LordHavoc: assume first setview recieved is the real player entity
if (!cl.playerentity)
cl.playerentity = cl.viewentity;
i = (unsigned short) MSG_ReadShort ();
if (i < 0 || i >= MAX_EDICTS)
Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
+ if (i >= cl_max_entities)
+ CL_ExpandEntities(i);
CL_ParseBaseline (cl_entities + i, false);
break;
case svc_spawnbaseline2:
i = (unsigned short) MSG_ReadShort ();
if (i < 0 || i >= MAX_EDICTS)
Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
+ if (i >= cl_max_entities)
+ CL_ExpandEntities(i);
CL_ParseBaseline (cl_entities + i, true);
break;
case svc_spawnstatic:
void CL_Effect(vec3_t org, int modelindex, int startframe, int framecount, float framerate);
void CL_ClearState (void);
+void CL_ExpandEntities(int num);
int CL_ReadFromServer (void);
time2 = Sys_DoubleTime();
// update audio
- if (cls.signon == SIGNONS && cl.viewentity >= 0 && cl.viewentity < MAX_EDICTS && cl_entities[cl.viewentity].state_current.active)
+ if (cls.signon == SIGNONS && cl_entities[cl.viewentity].state_current.active)
{
// LordHavoc: this used to use renderer variables (eww)
S_Update(&cl_entities[cl.viewentity].render.matrix);
if (num < 1)
Host_Error("EntityFrameQuake_ReadEntity: invalid entity number (%i)\n", num);
+ if (cl_num_entities <= num)
+ {
+ cl_num_entities = num + 1;
+ if (num >= cl_max_entities)
+ CL_ExpandEntities(num);
+ }
+
ent = cl_entities + num;
// note: this inherits the 'active' state of the baseline chosen
Con_Printf(" E_GLOWSIZE %i", e->glowsize * 4);
if (bits & E_GLOWCOLOR)
Con_Printf(" E_GLOWCOLOR %i", e->glowcolor);
-
+
if (bits & E_LIGHT)
Con_Printf(" E_LIGHT %i:%i:%i:%i", e->light[0], e->light[1], e->light[2], e->light[3]);
- if (bits & E_LIGHTPFLAGS)
+ if (bits & E_LIGHTPFLAGS)
Con_Printf(" E_LIGHTPFLAGS %i", e->lightpflags);
if (bits & E_TAGATTACHMENT)
*e = defaultstate;
}
+ if (cl_num_entities <= number)
+ {
+ cl_num_entities = number + 1;
+ if (number >= cl_max_entities)
+ CL_ExpandEntities(number);
+ }
cl_entities_active[number] = true;
e->active = true;
e->time = cl.mtime[0];
}
EntityFrame_AddFrame(d, f->eye, f->framenum, f->numentities, f->entitydata);
- memset(cl_entities_active, 0, cl_max_entities * sizeof(qbyte));
+ memset(cl_entities_active, 0, cl_num_entities * sizeof(qbyte));
number = 1;
for (i = 0;i < f->numentities;i++)
{
- for (;number < f->entitydata[i].number;number++)
+ for (;number < f->entitydata[i].number && number < cl_num_entities;number++)
{
if (cl_entities_active[number])
{
cl_entities[number].state_current.active = false;
}
}
+ if (number >= cl_num_entities)
+ break;
// update the entity
ent = &cl_entities[number];
ent->state_previous = ent->state_current;
cl_entities_active[number] = true;
number++;
}
- for (;number < cl_max_entities;number++)
+ for (;number < cl_num_entities;number++)
{
if (cl_entities_active[number])
{
}
// high bit means it's a remove message
cnumber = n & 0x7FFF;
+ // if this is a live entity we may need to expand the array
+ if (cl_num_entities <= cnumber && !(n & 0x8000))
+ {
+ cl_num_entities = cnumber + 1;
+ if (cnumber >= cl_max_entities)
+ CL_ExpandEntities(cnumber);
+ }
// add one (the changed one) if not done
stopnumber = cnumber + !done;
// process entities in range from the last one to the changed one
for (;enumber < stopnumber;enumber++)
{
- if (skip)
+ if (skip || enumber >= cl_num_entities)
{
if (enumber == cnumber && (n & 0x8000) == 0)
{
{
if (bits & E5_ANGLES16)
{
- s->angles[0] = MSG_ReadAngle16i();
- s->angles[1] = MSG_ReadAngle16i();
- s->angles[2] = MSG_ReadAngle16i();
+ s->angles[0] = MSG_ReadAngle16i();
+ s->angles[1] = MSG_ReadAngle16i();
+ s->angles[2] = MSG_ReadAngle16i();
}
else
{
- s->angles[0] = MSG_ReadAngle8i();
- s->angles[1] = MSG_ReadAngle8i();
- s->angles[2] = MSG_ReadAngle8i();
+ s->angles[0] = MSG_ReadAngle8i();
+ s->angles[1] = MSG_ReadAngle8i();
+ s->angles[2] = MSG_ReadAngle8i();
}
}
if (bits & E5_MODEL)
// (which would be remove world entity, but is actually a terminator)
while ((n = (unsigned short)MSG_ReadShort()) != 0x8000 && !msg_badread)
{
- // get the entity number and look it up
+ // get the entity number
enumber = n & 0x7FFF;
+ // we may need to expand the array
+ if (cl_num_entities <= enumber)
+ {
+ cl_num_entities = enumber + 1;
+ if (enumber >= cl_max_entities)
+ CL_ExpandEntities(enumber);
+ }
+ // look up the entity
ent = cl_entities + enumber;
// slide the current into the previous slot
ent->state_previous = ent->state_current;
int i, j, k, l, bits;
entityframe5_changestate_t *s, *s2;
entityframe5_packetlog_t *p, *p2;
- qbyte statsdeltabits[(MAX_CL_STATS+7)/8];
+ qbyte statsdeltabits[(MAX_CL_STATS+7)/8];
// scan for packets that were lost
for (i = 0, p = d->packetlog;i < ENTITYFRAME5_MAXPACKETLOGS;i++, p++)
{
num++;
}
// all remaining entities are dead
- for (;num < MAX_EDICTS;num++)
+ for (;num < sv.num_edicts;num++)
{
if (CHECKPVSBIT(d->visiblebits, num))
{
// build lists of entities by priority level
memset(entityframe5_prioritychaincounts, 0, sizeof(entityframe5_prioritychaincounts));
l = 0;
- for (num = 0;num < MAX_EDICTS;num++)
+ for (num = 0;num < sv.num_edicts;num++)
{
if (d->priorities[num])
{
// calculate lit surfaces and clusters
R_Shadow_EnlargeClusterBuffer(r_refdef.worldmodel->brush.num_pvsclusters);
R_Shadow_EnlargeSurfaceBuffer(r_refdef.worldmodel->nummodelsurfaces);
- r_refdef.worldmodel->GetLightInfo(&cl_entities[0].render, rtlight->shadoworigin, rtlight->radius, cullmins, cullmaxs, r_shadow_buffer_clusterlist, r_shadow_buffer_clusterpvs, &numclusters, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces);
+ r_refdef.worldmodel->GetLightInfo(r_refdef.worldentity, rtlight->shadoworigin, rtlight->radius, cullmins, cullmaxs, r_shadow_buffer_clusterlist, r_shadow_buffer_clusterpvs, &numclusters, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces);
clusterlist = r_shadow_buffer_clusterlist;
clusterpvs = r_shadow_buffer_clusterpvs;
surfacelist = r_shadow_buffer_surfacelist;
R_Shadow_Stage_ShadowVolumes();
usestencil = true;
}
- ent = &cl_entities[0].render;
+ ent = r_refdef.worldentity;
if (r_shadow_staticworldlights.integer && rtlight->compiled)
{
memset(&m, 0, sizeof(m));
{
R_Shadow_Stage_Light(usestencil);
- ent = &cl_entities[0].render;
+ ent = r_refdef.worldentity;
if (ent->model && ent->model->DrawLight && (ent->flags & RENDER_LIGHT))
{
lightcolor2[0] = lightcolor[0] * ent->colormod[0] * ent->alpha;
return -1;
}
+ if (entnum >= cl_max_entities)
+ CL_ExpandEntities(entnum);
+
// Pick a channel to play on
target_chan = SND_PickChannel(entnum, entchannel);
if (!target_chan)
}
// calculate view angle kicks
- if (cl.viewentity >= 0 && cl.viewentity < MAX_EDICTS && cl_entities[cl.viewentity].state_current.active)
+ if (cl_entities[cl.viewentity].state_current.active)
{
ent = &cl_entities[cl.viewentity];
Matrix4x4_Transform(&ent->render.inversematrix, from, localfrom);