This is a multi-part message in MIME format.
--
[ Picked text/plain from multipart/alternative ]
This is my first post on here so go easy on me :).  I tried looking through the 
archives for a similar discussion on this but didn't find anything...

First let me try to give an abstract,

I've created a weapon that will need to rotate the impact decal it makes on 
entities from case to case.  I have run into the problem that there's no way of 
telling the engine to paint the impact decal with a given rotation.  Well ok, 
the engine will happily paint a decal with a rotation, the problem is the 
process the game uses to add an effect doesn't take rotation into account at 
all!  I see two solutions so far: A hackish rewrite involving a lot of 
duplicate code to pass the rotation value through the normal impact effect 
process, or a shorter rewrite (with minimal duplicate code) that makes a direct 
call to the engine as quickly as possible.   I'm wondering if there's a way to 
do this without the hack'ish rewrites, or skipping the process that's already 
set up.  Or if everyone's in agreement that I'll need to do one of the two 
former ways.  Or at least a i'm looking for some explanation of why i shouldn't 
try to shorten the code between the weapon hit and the engine call (since I 
know there's gotta be a reason for the process and shortening it could cause 
problems).

Ok, now with some code...

First off, here's the engine call to paint a decal:

DecalShoot( int textureIndex, int entity, const model_t *model, const Vector& 
model_origin,
                    const QAngle& model_angles, const Vector& position, const 
Vector *saxis, int flags) = 0;

The main thing to note is the Vector *saxis, that will rotate the decal and 
works fine.  The problem is out of every call ever made with this from the 
game, all but 2 pass 0 as the rotation value!  (The two exceptions are the left 
and right footprint decal calls).  Obviously I'm not going to be able to rely 
on the existing engine calls if i want to rotate a decal.

Ok, but something tells me that I *will* need to rely on the process of 
creating impact decals.  Take a look at the call stack when it tries to paint a 
decal to a brush entity, client-side:

* C_BaseAOCBludgeonWeapon::Hit(...)                        <-- Here's my weapon 
code where I just hit a wall and would determine the decal rotation
* C_BaseAOCBludgeonWeapon::ImpactEffect(...)          <-- (Actually, i could 
have it here too, either way)
* UTIL_ImpactTrace(...)
* C_BaseEntity::ImpactTrace(...)
* DispatchEffect(...)
* C_TempEntsSystem::DispatchEffect(...)
* TE_DispatchEffect(...)                                  <-- Here is where the 
client/server break would be if client didn't make the effect
* DispatchEffectToCallback(...)
* ImpactCallback(...)
* Impact(...)
* C_BaseEntity::AddDecal(...)
* C_BaseEntity::AddBrushModelDecal(...)                <-- Here is where the 
actual engine call is made, and passes 0 as the rotation variable

That's a lot of jumps!  My main conundrum is getting a rotation value from the 
top of that list to the bottom (sorry, I should probably rewrite the call stack 
going the other way as it's inverted, the IP would be the bottom line).  NONE 
of those calls pass a rotation value along  There's also no passed object I can 
sneak it into, since at the very least that would get lost when it hits the 
client/server messaging system.  So, my first solution (the hackish rewrite) 
would be something like this:

* C_BaseAOCBludgeonWeapon::Hit(...)
* C_BaseAOCBludgeonWeapon::ImpactEffect(..., Vector *saxis)            <-- Pass 
the rotaton along
* UTIL_ImpactTrace(..., Vector *saxis)                                          
      <-- Pass the rotaton along
* C_BaseEntity::ImpactTrace(..., Vector *saxis)                                
<-- Pass the rotaton along
etc...

ie. Just make a clone of all those calls with an extra Vector passed through 
(and of course add it to the messaging across client/server).  It would 
certainly work, but just feels like a bad way of doing it.  Copy, paste, add 
the variable.  Copy, paste, add the variable, etc.  I guess if it were only 1 
or 2 functions it was going through it would seem like a better option.

The other option would be a more direct route, trying to get to the engine call 
as soon as possible.  Now that I think about it though, this probably isn't a 
good idea, since we're going to have to put it through the messaging system 
anyway, might as well not walk around all the impact code.  But just for 
reference, my idea would be to shorten the chain to something like this (with 
better func names than "MyDecal" of course):

* C_BaseAOCBludgeonWeapon::ImpactEffect(..., Vector *saxis)    <-- first spot 
where we get the rotation
* TE_DispatchMyDecal(..., Vector *saxis)                                    <-- 
client/server split, custom function
* DispatchEffectToCallback(...)                                                 
   <-- client picking the msg up, same function with my callback added
* MyDecalCallback(..., Vector *saxis)                                          
<-- the callback, custom function
* effects->DecalShoot(...)                                                      
     <-- the engine has it now with the rotation

I would put necessary code into those functions that are needed (like probably 
recreating a CEffectData object, figuring out the decal index, etc).  I haven't 
looked at it closely enough, and that's the problem with this idea.  It doesn't 
overload a bunch of functions, but it's still a hackish rewrite in that I'm 
going from the weapon hitting to the decal being drawn in a lot fewer steps.  
There's a lot of ray traces and, i mean, even the big "Impact()" gets called to 
draw a decal that we already know where to draw.  In other words, I'm not 
familiar enough with why we're doing all this extra stuff before drawing a 
decal, and so I don't think it's a good idea to just shun it all and print a 
decal as soon as we know where to.  Can anyone give me an idea how this would 
be a problem?  My only guess is it's trying to account for network issues 
somehow, but even then, shouldn't the server be always right in that case?

Anyway, I hope that was descriptive enough to explain my trouble.  In short: my 
weapon code determines the decal rotation, and that rotation value needs to 
make it to the engine call.  I think the first way of doing it will be the 
best, but it just feels like a bad habit to be overloading all those functions 
for one single gain.  Maybe there's a better way about this (or a method I 
don't know about) for rotating a decal...

Thanks for listening, I'm open to any ideas

-Matt




--


_______________________________________________
To unsubscribe, edit your list preferences, or view the list archives, please 
visit:
http://list.valvesoftware.com/mailman/listinfo/hlcoders

Reply via email to