From the compile log, it seems that HLBSP just crashes at 15%:
1000...1500...
1000...1500...
"If your map lags - it is usually due to micro leaks your current compilers won't even detect. One more reason to use the compilers I recommended they got a very good detection system to find such micro leaks."I'm sorry, but this is stupid. If any sort of leak happened, HLVIS and HLRAD would likely crash. In fact, HLBSP could probably crash first because some of the coordinates in the .prt file would go to infinity.
"Ever wondered why you haven't seen a CS_superbowl map? I am not saying it can not be done, I am saying that the engine isn't up to it."The engine can be up to it if you do it right.
CLASS_PLAYER_ALLY
for example, into CLASS_HUMAN_MILITARY
, then compile the .dll files.-4096 to +4096
unit range. Regular entities will stop moving if they reach those boundaries.Truevision Targa - .tga
Tagged Image File Format - .tif
Gamecube Texture - .tpl
Unreal Texture - .utx
Quake 2 Texture - .wal
Valve Texture Format - .vtf
Oh, look at that, one can potentially implement Source texture support in a HL mod. GLint myNewTexture;
... // after some TGA parsing with DevIL and texture creation via gl functions
texture->gl_texturenum = myNewTexture;
As for resizing, i.e. updating the original texture, we'll see. I am definitely thinking of writing some tutorials about this.water
or !
, but I'm thinking of potential applications of this elsewhere too."Now i'm getting a "could not load library" ctd."Are you trying to run it on WON Half-Life or Steam Half-Life? If you got any pre-2013 Half-Life version, that ain't gonna work.
"Compiles but produces no .dll"Explain. How are you compiling? What are you using to compile? Are there any errors in the compile log? Etc.
// Raise monster off the floor one unit, then drop to floor
if ( pev->movetype != MOVETYPE_FLY && !FBitSet( pev->spawnflags, SF_MONSTER_FALL_TO_GROUND ) )
{
pev->origin.z += 1;
DROP_TO_FLOOR ( ENT(pev) );
// Try to move the monster to make sure it's not stuck in a brush.
if (!WALK_MOVE ( ENT(pev), 0, 0, WALKMOVE_NORMAL ) )
{
ALERT(at_error, "Monster %s stuck in wall--level design error", STRING(pev->classname));
pev->effects = EF_BRIGHTFIELD;
}
}
Around line 2085, in monsters.cpppev->effects = EF_BRIGHTFIELD;
and you should get rid of the yellow aura."using the Spirit engine"...
"engine"URBY!
"You are correctly: Blender is brilliantly. But Unity with Probuilder or CSG Shake too."I don't like Unity.
Mushrooms are nice. They're especially good on pizza. uwuWe're gonna have a fight about the mushrooms, thoughI'm afraid I'm gonna have to double down on this one. Mushrooms can fuck off forever.
studiohdr_t
pointer (header
in the example code), we can access the bodygroup, then the submodel of said bodygroup, and then the vertices of the submodel.
void StudioExampleStuff( studiohdr_t* header, mstudiobodyparts_t* bodygroup, mstudiomodel_t* submodel, Vector& vert, int cntr )
{
static float flWave = 0.0;
flWave += M_PI/240.0;
if ( flWave > M_PI )
flWave *= -1;
if ( header )
{
bodygroup = (mstudiobodyparts_t*)((byte*)header + header->bodypartindex);
if ( bodygroup )
{
submodel = (mstudiomodel_t*)((byte*)header + bodygroup->modelindex);
if ( submodel )
{
for ( int i = 0; i < submodel->numverts; i++ )
{
float* vertFl = (float*)((byte*)header + submodel->vertindex) + i;
float indexWave = (float)i / (float)submodel->numverts;
float indexOffset = (indexWave * 2.0) - 1.0;
indexWave *= 4.0 * M_PI;
vertFl[ 2 ] += sin(flWave + indexWave) * 0.004 * (indexOffset*2.0) + sin(flWave*4.0 + indexWave)*0.01;
}
}
}
}
}
So, they aren't read-only.models/something.mdl
and you change the vertices on it, you will change it on them all. Maybe some mods will have a use for this, where for example, if the player damages one object and its vertices bend, it affects basically every other object in the map.539
1330
4 0 123 (28672.000000 12288.000000 0.000000) (32768.000000 12288.000000 0.000000) (32768.000000 12288.000000 16384.000000) (28672.000000 12288.000000 16384.000000)
4 1 122 (28672.000000 12288.000000 16384.000000) (28672.000000 12288.000000 20480.000000) (20480.000000 12288.000000 20480.000000) (20480.000000 12288.000000 16384.000000)
4 1 28 (20480.000000 12288.000000 16384.000000) (20480.000000 12288.000000 20480.000000) (20480.000000 28672.000000 20480.000000) (20480.000000 28672.000000 16384.000000)
4 2 10 (26624.000000 28672.000000 1419.636364) (26624.000000 28672.000000 16384.000000) (26624.000000 30208.000000 16384.000000) (26624.000000 30208.000000 1280.000000)
mapname_viscache.prt:
539
1330
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
4 0 123 (28672.000000 12288.000000 0.000000) (32768.000000 12288.000000 0.000000) (32768.000000 12288.000000 16384.000000) (28672.000000 12288.000000 16384.000000)
4 1 122 (28672.000000 12288.000000 16384.000000) (28672.000000 12288.000000 20480.000000) (20480.000000 12288.000000 20480.000000) (20480.000000 12288.000000 16384.000000)
4 1 28 (20480.000000 12288.000000 16384.000000) (20480.000000 12288.000000 20480.000000) (20480.000000 28672.000000 20480.000000) (20480.000000 28672.000000 16384.000000)
4 2 10 (26624.000000 28672.000000 1419.636364) (26624.000000 28672.000000 16384.000000) (26624.000000 30208.000000 16384.000000) (26624.000000 30208.000000 1280.000000)
539 stands for the number of visleaves, 1330 is the number of visportals.BOLIDHINT
works. BOLIDHINT
is apparently the same as SOLIDHINT
. However, now let's look at the clipnode counts:NULL
- 7148 clipnodesBEVEL
- 4318 clipnodesSOLIDHINT
- 7158 clipnodesBOLIDHINT
- 4122 clipnodesNULL
and SOLIDHINT
aren't supposed to create the same number of clipnodes, considering the fact that SOLIDHINT
generally produces less wpolys. Keep that in mind.SOLIDHINT
and BOLIDHINT
compared to the other two."I remember trying to get the texture data for models or sprites but couldn't find a way."At that point I'd probably do a MDL and SPR parser, if I just wanted to read the texture data. It'd be easy too, there are several open-source apps doing that stuff, so, we can use it as a reference / steal the code.
if ( FClassnameIs( pEnemy->pev, "monster_something" ) )
This will work if the monster has already chosen an enemy and is about to attack it."entities would be read only but a lot of the others should be modifiable."Yes, but what do you exactly mean by "entities"? cl_entity_t, sending the modified data back to the server etc.?
char* entities;
for ( int i = 0; i < 120; i++ )
{
cl_entity_t *pEnt = gEngfuncs.GetEntityByIndex( i );
// this doesn't guarantee that the entity exists or doesn't exist
// but we needed something quick and dirty
if ( (pEnt->curstate.origin != Vector(0,0,0)) || i == 0 )
{
if ( pEnt->model )
gEngfuncs.Con_Printf( "\nEntindex %i - model->entities %s", i, pEnt->model->entities);
else
gEngfuncs.Con_Printf( "\nEntindex %i - no model here", i );
}
else
{
gEngfuncs.Con_Printf( "\nEntindex %i - no entity here", i );
}
}
And it looks like vertex manipulation just isn't gonna work on studio models. Can't even read, let alone write to it, LOL. It looks like model_t only provides all data for brush models. For sprites and studio models, it doesn't do much.BOGUS_RANGE
macro refers to g_iMaxEntityRange
instead of a hardcoded value. g_iMaxEntityRange
is, of course, set by the -maxentrange
param in HLCSG.For example, if you have two light entities with identical names and one is checked with "start dark", both the lights would start dark.This also makes sense to an extent, however, this is likely done on the compiler level. HLRAD probably works like a state machine when it's dealing with flags of lights. It treats one 'name' as a single entity, but radiates light for each of them individually. It associates the 'start dark' flag with that one name because one of the entities happens to have it.
"Hm, I wonder why it was software only."Because of graphics programming.
if ( texturePalette < 224 )
color = textureColor * lightmap;
else
color = textureColor;
This is the kind of 'control' that I'm talking about. We're basically modifying the texture before uploading it to draw the current wpoly. But, this isn't my area yet and I'm likely incorrect."And with the map coordinate bounds I thought that server to client messages 1 through 64 (or whatever is handled by the engine) might have clamped coordinates - is that right?"Well, it seems so. Any TE_ message has clamped coordinates. Hence explosions end up spawning at 0,0,0 if they're outside of the +-4096 range. :/
"Or you could use dynamic lights but I haven't played with them enough to know their limitations."God no. Dlights are horrible for performance. And there can't be many of them either at the same time.
"there is lighting data in the model_s struct in client.dll but I suspect it's read only (maybe?)"Speaking of model_s, after some brief experimentation with reading vertices from the map model (one way was getting the worldspawn entity with
gEngfuncs.GetEntityByIndex(0)
and the other was IEngineStudio.GetModelByIndex(1)
), I've come to a conclusion that some things are surprisingly not just read-only.
m_pWorld = gEngfuncs.GetEntityByIndex( 0 );
if ( m_pWorld )
{
m_pWorld->model->leafs[ 0 ].firstmarksurface[ 0 ]->polys[ 0 ].verts[ 0 ][ 2 ] += m_flWave;
// etc. etc.
This here is a really quick test to see if I can manipulate the Z position of the first vertex, of the first polygon, of the first marksurface, of the first leaf. // first vertex of the first edge in the map model
// NOT the same as pModel->vertexes[0].position.z
pModel->vertexes[ pModel->edges[ 0 ].v[ 0 ] ].position.z += m_flWave;
or something like that, it wouldn't change anything, at least visually. This seems like pretty dangerous stuff, to be honest.if ( m_pWorld )
{
msurface_t* surf = m_pWorld->model->leafs[ 0 ].firstmarksurface[ 0 ];
surf->polys[ 0 ].verts[ 0 ][ 2 ] += m_flWave;
for ( int i = 0; i < 64*64; i++ )
{
surf->samples[ i ].r += 1;
if ( surf->samples[ i ].r >= 255 )
surf->samples[ i ].r = 0;
}
}
"samples" is allegedly the actual lightmap data of a surface.