Real time combat?

Orochi

New Adventurer
MSS Developer
MSC Developer
Joined
Jun 12, 2006
Messages
790
Reaction score
0
Age
35
Location
On a Bus
Of course they were programmed by the same Dev team, MiB, but I didn't expect them to be *quite* that similar, you know what I mean?
 

FER

New Adventurer
MSC Developer
RiP
Joined
Sep 16, 2006
Messages
2,758
Reaction score
0
Age
37
Location
on Belser's army
At least post a link to that goblin, I bet It wouldnt look half bad if it was less boxy and has a different face texture, plus its original content (or is it?... )
 

The Man In Black

Administrator
Staff member
Administrator
Moderator
RiP
Joined
Jul 9, 2006
Messages
6,904
Reaction score
71
I'm sure there are large chunks of code that they just copied out of laziness
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Large swaths of the Source SDK are the same Quake 1.5 code that Goldsrc uses. Pretty much all the primary functions are copy pasta'd. In most cases, there's no real reason for it to be otherwise (eg. angle calcs are angle calcs, regardless of time). Even where there are major changes, such as in model animations, the Goldsrc code remains, just with new stuff stacked on. Most of the heavy changes are in the rendering engine itself, and that's where you get your night-and-day difference effect.

The Man in Black said:
Oh, I know the code. Datas I would need to rewrite would be the contents of submodel arrays, essentially.
What, exactly, do you need? :\
 

The Man In Black

Administrator
Staff member
Administrator
Moderator
RiP
Joined
Jul 9, 2006
Messages
6,904
Reaction score
71
Submodels are stored in one giant single-dimension array, wherein the elements represent every possible combination of the parts. Essentially, the array would look something like:

{ {Head1,Body1,Arms1,Legs1}, {Head2,Body1,Arms1,Legs1}, {Head3 (...) {HeadN,BodyN,ArmsN,LegsN} }

Point is, the model file has compressed it all into something very difficult, thus the complicated equation for finding out the new array location whenever you change a small part. What I would need is to know HOW the model is compressing the submodels into the array. I doubt it's something that one would be able to get the code to spit out. It'd likely take some research hitting buttons ingame.

And as I said, this would all be on the basis that the calculations for finding the right submodel are incorrect, and would do absolutely nothing if the engine was just having trouble displaying the proper one, despite the right index. I'd have to think on how to test which side is buggering without rewriting the calculations anew...
 

Orochi

New Adventurer
MSS Developer
MSC Developer
Joined
Jun 12, 2006
Messages
790
Reaction score
0
Age
35
Location
On a Bus
Let me know if you figure it out, MiB. This is the code from Source:

Code:
void SetBodygroup( CStudioHdr *pstudiohdr, int& body, int iGroup, int iValue )
{
	if (! pstudiohdr)
		return;

	if (iGroup >= pstudiohdr->numbodyparts())
		return;

	mstudiobodyparts_t *pbodypart = pstudiohdr->pBodypart( iGroup );

	if (iValue >= pbodypart->nummodels)
		return;

	int iCurrent = (body / pbodypart->base) % pbodypart->nummodels;

	body = (body - (iCurrent * pbodypart->base) + (iValue * pbodypart->base));
}

Since it's mostly the same, this also means we may potentially run into the same bug, and I'd like to nip it in the bud before it happens.
 

Tigerkev

New Adventurer
The Dragonknights
Heroes of Dawn
Joined
Aug 18, 2010
Messages
214
Reaction score
0
Age
34
Damn guys, you really want me to go and code. I should just put my lazy azz down and start coding for MS:C which i really should've done a while ago already. I shall go and look into little stuff first and work myself into the code mess before starting on bigger things, given the version i have doesn't have any major lack of stuff (like polearms).
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
The Man In Black said:
Submodels are stored in one giant single-dimension array, wherein the elements represent every possible combination of the parts. Essentially, the array would look something like:

{ {Head1,Body1,Arms1,Legs1}, {Head2,Body1,Arms1,Legs1}, {Head3 (...) {HeadN,BodyN,ArmsN,LegsN} }

Point is, the model file has compressed it all into something very difficult, thus the complicated equation for finding out the new array location whenever you change a small part. What I would need is to know HOW the model is compressing the submodels into the array. I doubt it's something that one would be able to get the code to spit out. It'd likely take some research hitting buttons ingame.

And as I said, this would all be on the basis that the calculations for finding the right submodel are incorrect, and would do absolutely nothing if the engine was just having trouble displaying the proper one, despite the right index. I'd have to think on how to test which side is buggering without rewriting the calculations anew...
Hrmm... If you mean the actual model data... I might be able to find out the bit where it stores it in the model compiler code. (Although, IIRC, I can't make a functional compiler with said code, so...)

edit: I take that back, the compiler I compiled works (winces), it's just dated. Doesn't support commands like $texturerendermode, but still stores submodel sets just fine.

The usual format is to have a group name, with a series of submodels ("eg. heads:1,2,3,4 armor:1,2,3 weapons:1,2,3,4,5"). Judging by the formula (and the setmodelbody command syntax), it uses indexes, instead of looking up by string header, in game - though the group names are still stored in the model.


This may or may not be the info you are looking for:
Code:
 void WriteModel( )
{
	int i, j, k;

	mstudiobodyparts_t	*pbodypart;
	mstudiomodel_t	*pmodel;
	// vec3_t			*bbox;
	byte			*pbone;
	vec3_t			*pvert;
	vec3_t			*pnorm;
	mstudiomesh_t	*pmesh;
	s_trianglevert_t *psrctri;
	int				cur;
	int				total_tris = 0;
	int				total_strips = 0;

	pbodypart = (mstudiobodyparts_t *)pData;
	phdr->numbodyparts = numbodyparts;
	phdr->bodypartindex = (pData - pStart);
	pData += numbodyparts * sizeof( mstudiobodyparts_t );

	pmodel = (mstudiomodel_t *)pData;
	pData += nummodels * sizeof( mstudiomodel_t );

	for (i = 0, j = 0; i < numbodyparts; i++)
	{
		strcpy( pbodypart[i].name, bodypart[i].name );
		pbodypart[i].nummodels		= bodypart[i].nummodels;
		pbodypart[i].base			= bodypart[i].base;
		pbodypart[i].modelindex		= ((byte *)&pmodel[j]) - pStart;
		j += bodypart[i].nummodels;
	}
	ALIGN( pData );

	cur = (int)pData;
	for (i = 0; i < nummodels; i++) 
	{
		int normmap[MAXSTUDIOVERTS];
		int normimap[MAXSTUDIOVERTS];
		int n = 0;

		strcpy( pmodel[i].name, model[i]->name );

		// save bbox info

		// remap normals to be sorted by skin reference
		for (j = 0; j < model[i]->nummesh; j++)
		{
			for (k = 0; k < model[i]->numnorms; k++)
			{
				if (model[i]->normal[k].skinref == model[i]->pmesh[j]->skinref)
				{
					normmap[k] = n;
					normimap[n] = k;
					n++;
					model[i]->pmesh[j]->numnorms++;
				}
			}
		}
		
		// save vertice bones
		pbone = pData;
		pmodel[i].numverts	= model[i]->numverts;
		pmodel[i].vertinfoindex = (pData - pStart);
		for (j = 0; j < pmodel[i].numverts; j++)
		{
			*pbone++ = model[i]->vert[j].bone;
		}
		ALIGN( pbone );

		// save normal bones
		pmodel[i].numnorms	= model[i]->numnorms;
		pmodel[i].norminfoindex = ((byte *)pbone - pStart);
		for (j = 0; j < pmodel[i].numnorms; j++)
		{
			*pbone++ = model[i]->normal[normimap[j]].bone;
		}
		ALIGN( pbone );

		pData = pbone;

		// save group info
		pvert = (vec3_t *)pData;
		pData += model[i]->numverts * sizeof( vec3_t );
		pmodel[i].vertindex		= ((byte *)pvert - pStart); 
		ALIGN( pData );			

		pnorm = (vec3_t *)pData;
		pData += model[i]->numnorms * sizeof( vec3_t );
		pmodel[i].normindex		= ((byte *)pnorm - pStart); 
		ALIGN( pData );

		for (j = 0; j < model[i]->numverts; j++)
		{
			VectorCopy( model[i]->vert[j].org, pvert[j] );
		}

		for (j = 0; j < model[i]->numnorms; j++)
		{
			VectorCopy( model[i]->normal[normimap[j]].org, pnorm[j] );
		}
		printf("vertices  %6d bytes (%d vertices, %d normals)\n", pData - cur, model[i]->numverts, model[i]->numnorms);
		cur = (int)pData;

		// save mesh info
		pmesh = (mstudiomesh_t *)pData;
		pmodel[i].nummesh		= model[i]->nummesh;
		pmodel[i].meshindex		= (pData - pStart);
		pData += pmodel[i].nummesh * sizeof( mstudiomesh_t );
		ALIGN( pData );

		total_tris = 0;
		total_strips = 0;
		for (j = 0; j < model[i]->nummesh; j++)
		{
			int numCmdBytes;
			byte *pCmdSrc;

			pmesh[j].numtris	= model[i]->pmesh[j]->numtris;
			pmesh[j].skinref	= model[i]->pmesh[j]->skinref;
			pmesh[j].numnorms	= model[i]->pmesh[j]->numnorms;

			psrctri				= (s_trianglevert_t *)(model[i]->pmesh[j]->triangle);
			for (k = 0; k < pmesh[j].numtris * 3; k++) 
			{
				psrctri->normindex	= normmap[psrctri->normindex];
				psrctri++;
			}

			numCmdBytes = BuildTris( model[i]->pmesh[j]->triangle, model[i]->pmesh[j], &pCmdSrc );

			pmesh[j].triindex	= (pData - pStart);
			memcpy( pData, pCmdSrc, numCmdBytes );
			pData += numCmdBytes;
			ALIGN( pData );
			total_tris += pmesh[j].numtris;
			total_strips += numcommandnodes;
		}
		printf("mesh      %6d bytes (%d tris, %d strips)\n", pData - cur, total_tris, total_strips);
		cur = (int)pData;
	}	
}

Also, the whole studiomdl source:
http://www.thothie.com/msc_dev3/hlsdk2.3_studiomdl.rar
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
FER said:
At least post a link to that goblin, I bet It wouldnt look half bad if it was less boxy and has a different face texture, plus its original content (or is it?... )
You're... Serious, aren't you?

Why would you want to replace the current texture with that inflatable balloon texture? :\
current_goblin.jpg vs. inflatable_goblin.jpg

I mean, aside from being one of the few "cute" monsters, the cell shader style texture would be a lot less congruent with the rest of the artwork than the current one.

I think, at some point, Ewok was proposing converting to a cell-shaded style of artwork, which is why we see things like this in the archives:
cartoon_troll.jpg
...and while I'd be willing to provide a cell-shaded model set (assuming someone made one), for those who like that sort of thing, I just don't really see the point in swapping out a model or two with the outlandish style.

Personally, I think we can leave that style to Land of Legends. (Though it does make both mapping and modeling a hell of a lot easier, when everything is Nintendo 64 style quality or below.)
 

FER

New Adventurer
MSC Developer
RiP
Joined
Sep 16, 2006
Messages
2,758
Reaction score
0
Age
37
Location
on Belser's army
Why would you want to replace the current texture with that inflatable balloon texture? :\

To number down the amount of stolen content?
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
F*ck that! :p This game wouldn't exist if not for all the recycled content that no one's making any cash on and would otherwise just be rotting somewhere anyways. Certainly don't intend to turn all our models into balloon animals just to sake someone's misplaced sense of righteousness. ;)

Plan is to be introduce a whole slew of new models from Gunman next patch anyways. We just don't have the army of professional modelers, who actually fulfill requests, required to have all original quality content, and it's better than letting all this old artwork go to waste.
 

FER

New Adventurer
MSC Developer
RiP
Joined
Sep 16, 2006
Messages
2,758
Reaction score
0
Age
37
Location
on Belser's army
The goblin model is not exaclty from a dead HL mod, more like an HP game that comes with some PCs, and you have to pay to play it without trial.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
It's from a dead retail game, that has since been replaced by a flurry of more popular sequels where it is no longer used (most recently, Torchlight). Same could be said of about a third of all the artwork in the MSC. Again, just don't have enough reliable crew to keep this up otherwise. How many years have we gone without an original elf model now? And how many years did we go through before we even went through on the threat of using that "borrowed" set? Meh. Alas, this recycling is what keeps us afloat.

But at least our current golbin "fits" better than most of the models we've acquired over the years. Some of this stuff is just really out of whack. Can't do much about that without a slew of modelers who operate on a demand-by-demand basis though, all with a similar aesthetic eye to boot.
 

The Man In Black

Administrator
Staff member
Administrator
Moderator
RiP
Joined
Jul 9, 2006
Messages
6,904
Reaction score
71
99% sure I know the problem, now. Should have seen it before but I never thought about the math

As stated before, the submodels are all stored in a single array where every possible combination of submodels is represented. The index of the combination you're currently using is 'body', which is an int. Problem is, despite it being an int, somewhere between server and client it gets processed as a byte, which I discovered a long time ago, but was never able to fix.

Looking at the armor model, we have 3 sets of legs, 2 sets of heads, 2 sets of arms, 2 sets of bodies and 10 sets of armor. Thothie found that adding an extra armor causes the problem. Why? 3*2*2*2*11 == 264 > 256. He also told me the orc model used to do it as well, and I'm guessing it used to be slightly more complicated because it's also coming close to the total combination limit.

Orochi, if you can figure out how to make it go as an int and not just a byte, it'll probably solve it for both Source and Goldsrc. (And make sure to actually verify it. As I recall, it IS using WRITE/READ_BYTE, but changing that didn't solve the problem). If I get time, maybe I'll look into it as well, if Thoth sends the code my way.
 

Orochi

New Adventurer
MSS Developer
MSC Developer
Joined
Jun 12, 2006
Messages
790
Reaction score
0
Age
35
Location
On a Bus
I recall reading something about just this, MiB. I'll have to find it and dig it up. Something about the SendTables, if HL1 uses those as well. Try looking at the SendTables for the player class, see if "body" is sent as a byte or something.
 

The Man In Black

Administrator
Staff member
Administrator
Moderator
RiP
Joined
Jul 9, 2006
Messages
6,904
Reaction score
71
Oh. Right. Forgot Source and GoldSrc use different net code. Ours is slightly more archaic. Hopefully, yours will work properly. Just set 'body' to something above 255 on the server and see if it passes properly to the client.
 

Orochi

New Adventurer
MSS Developer
MSC Developer
Joined
Jun 12, 2006
Messages
790
Reaction score
0
Age
35
Location
On a Bus
Unless you have a model handy with that many subgroups, I won't be able to do that. :wink:
I'd have to build a model to test that, Source also has fail-safes; choose too high a number or something invalid and it just picks the first choice anyway.
 

The Man In Black

Administrator
Staff member
Administrator
Moderator
RiP
Joined
Jul 9, 2006
Messages
6,904
Reaction score
71
If you intercept it right on the client, you won't need to worry about it, theoretically. In any case, if you don't even have a model that complex, I wouldn't worry about it.
 

Orochi

New Adventurer
MSS Developer
MSC Developer
Joined
Jun 12, 2006
Messages
790
Reaction score
0
Age
35
Location
On a Bus
Well, we might eventually. I'll take a look at the MS:C code I have, I doubt it's changed enough in that area to be that different. Maybe I'll be able to dig up something.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Shouldn't need too complex a model... I think just one with 8 submodel groups and two a piece would do it, from the formula MiB mentions. Could easily be done with QC copypasta - only tricky bit would be coming up with enough different textures amongst the SMD components to identify the submodels in game.

But yeah, just a Print statement giving you the resulting submodel combination would probably tell you if it was working or not - could temporarily send a false bit of data larger than a byte and see what it spit out on the other side.

Code hasn't changed much since the last pack I sent ye, MiB, and certainly not in regards to this, but I'll get you the latest ASAP. Jail girl has me running a bit ragged at the moment.
 

FER

New Adventurer
MSC Developer
RiP
Joined
Sep 16, 2006
Messages
2,758
Reaction score
0
Age
37
Location
on Belser's army
BTW is it possible that bosses can have more than one hitbox? (eg: like the first boss in cry of fear who has it weakspot in its back but shooting it on anywhere else only stuns it)
 

Tigerkev

New Adventurer
The Dragonknights
Heroes of Dawn
Joined
Aug 18, 2010
Messages
214
Reaction score
0
Age
34
FER said:
BTW is it possible that bosses can have more than one hitbox? (eg: like the first boss in cry of fear who has it weakspot in its back but shooting it on anywhere else only stuns it)
Shouldn't it be already like this? I don't know if the models need to have that set but the HL engine should support this. (multiple hitboxes that is)
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
The HL engine supports multiple hitbox types... And I think the code is still there, it's just the hitbox types don't do anything in MSC. It maybe possible to switch it up so they do - call a script event based on the type of hitbox, or return the hitbox type in game_dodamage events...

Undamael, probably our most complicated monster, is actually made up of two NPCs, one for the body and one for the hitbox. The hitbox NPC is continuously adjusted to snap to his head. His unusual size and shape requires this (amongst other things that made coding him up "interesting").

One bugger up is, however, that melee weapons, and even a few of the ranged weapons (like the Neck Hunter), don't use hitboxes. They instead depend on the collision bounding box, defined by the script, and not the model.
 

Tigerkev

New Adventurer
The Dragonknights
Heroes of Dawn
Joined
Aug 18, 2010
Messages
214
Reaction score
0
Age
34
I think it would be nice if you would actually be able to do that in the script,
i.e: Be able to set the damage multiplicator given on the hitbox or if(izHit(HITBOX)) do something.
 
Top