View previous topic :: View next topic |
Author |
Message |
OneManClan
Joined: 28 Feb 2009 Posts: 62
|
Posted: Tue May 19, 2009 7:11 am Post subject: Programming a 'SkinBlind' effect |
|
|
Hi Guys,
I've just realised that it's possible that the Quake C Gurus here don't check out other sections of this forum, and so may not be aware of my post regarding the 'SkinBlind' effect.
Could I get a confirmation from the Quake C Gurus that this effect (where hallucinating players see a different set of skins to everyone else) cannot be achieved in Quake C, and must be done via the engine.
thanks,
OneManClan |
|
Back to top |
|
 |
Error Inside3D Staff

Joined: 05 Nov 2004 Posts: 558 Location: VA, USA
|
|
Back to top |
|
 |
OneManClan
Joined: 28 Feb 2009 Posts: 62
|
Posted: Tue May 19, 2009 8:54 am Post subject: |
|
|
Error wrote: | can customize entity for client be used here? |
Sorry (still a newbie), I don't know what 'customize entity for client' means.
Note: As I said in my other post, CustomTF runs on a server called cpqwsv.exe which (apparently) can't make one player see a different set of skins to another.
Obviously if it's just easier to port the whole mod into MVDSV (which I'm told CAN do it) then that would make more sense, so we can record entire games !!
OneManClan
ps. I've been informed that QuakeForge can run the CustomTF .dat... (!!) looking into it... |
|
Back to top |
|
 |
avirox
Joined: 16 Aug 2006 Posts: 109
|
Posted: Tue May 19, 2009 2:09 pm Post subject: |
|
|
I assume customtf does it by writebyte hacks and such. This CAN be done in the QC, but I believe prozac's server executable (CP) does something on the side to make sure connecting players don't see things screwed up (I forget the specifics). As phrosty or Often about it. |
|
Back to top |
|
 |
MauveBib

Joined: 04 Nov 2004 Posts: 602
|
Posted: Tue May 19, 2009 5:19 pm Post subject: |
|
|
Didn't spike already post a qc solution?
Essentially there's no tidy way to do it, and as Avirox says many servers will automatically filter out the hacks used to manage it. _________________ Apathy Now! |
|
Back to top |
|
 |
Wazat
Joined: 15 Oct 2004 Posts: 732 Location: Middle 'o the desert, USA
|
Posted: Wed May 20, 2009 1:36 am Post subject: |
|
|
You can do this with QC if your engine supports .drawonlytoclient. If you want a pure QC solution then it gets ugly, as mentioned above.
The way to do with with .drawonlytoclient is to attach additional entities to all the players who should change colors for the hallucinating player. Each player has a different entity for each other player in the game, and that entity can only be seen by the player it's meant for. Then each such model mimics the velocity, frames, etc of the player it's attached to (either with QC follow code in playerprethink/postthink, or with an engine attachment method). Whenever a player connects/disconnects, models for that player to see are added/removed from all other players.
From there, you can change the skin, model, scale, alpha, etc of the model that the hallucinating player sees however you please. Presumably with the proper attachment code/feature you could keep client-side prediction issues from cropping up (engine-based model attachments would work best here, since that's all updated client-side).
That's one solution, anyway. _________________ When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work. |
|
Back to top |
|
 |
MauveBib

Joined: 04 Nov 2004 Posts: 602
|
Posted: Wed May 20, 2009 1:48 am Post subject: |
|
|
Wazat: This is for QW, with people using a variety of different clients. .drawonlytoclient isn't going to cut it I don't think. _________________ Apathy Now! |
|
Back to top |
|
 |
Wazat
Joined: 15 Oct 2004 Posts: 732 Location: Middle 'o the desert, USA
|
Posted: Wed May 20, 2009 4:17 am Post subject: |
|
|
Actually, isn't .drawonlytoclient a server-only feature? There's no need for it to send drawonlytoclient entities to other clients, so it should be all handled on the server end.
Now, things like movetype follow or attaching one entity to another via engine are maybe not so server-side. _________________ When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work. |
|
Back to top |
|
 |
OneManClan
Joined: 28 Feb 2009 Posts: 62
|
Posted: Thu May 21, 2009 3:25 am Post subject: |
|
|
avirox wrote: | I assume customtf does it by writebyte hacks and such. This CAN be done in the QC, but I believe prozac's server executable (CP) does something on the side to make sure connecting players don't see things screwed up (I forget the specifics). As phrosty or Often about it. |
Hi Avirox,
How far does your mod of MVDSV (XE) go in 'emulating' CPQWSV? Can it read the prozac.dat?
OneManClan
[EDIT: I just checked our your awesome gui menu tutorial!! Is this compatible with cpqwsv..??] |
|
Back to top |
|
 |
OneManClan
Joined: 28 Feb 2009 Posts: 62
|
Posted: Mon Jul 19, 2010 11:24 am Post subject: |
|
|
NOTE: I'll be using the term 'GasViewed' to refer to the player/entity being looked at by the hallucinating player.
UPDATE: Spikes code (thanks again Spike!) was/is indeed QuakeC (not C as I suspected in my last post). I got confused because the compiler I was using didn't recognise 'continue', and basically it took the conversion of AGR CustomTF to FTE (which is progressing nicely!!) for this to finally compile, and come together. I'm VERY happy to say that the SkinBlind function is (basically) now WORKING !! I am however still stumped as to HOW it works its' magic. My (updated) comments in the code below.
Note: I put my comments *after* the line in question because this makes more sense to me - (apologies if this is not 'proper' ):
Code: |
#define svc_setinfo 51 // setinfo on a client
local entity e;
local float n;
msg_entity = self;
while (n < 32)
{
n = n+1;
e = nextent(e);
if (e.classname == "") //only if the player is actually valid
/* I don't know exactly how the above line distinguishes *players* from other entities with defined classname strings. ie It seems to say 'if (this entity doesn't have a defined classname)', but plenty of 'things' in the world have a classname - monsters, sentries, grenades, etc.. The explanation for nextent() I RTFM'ed is:
"entity nextent(entity e)
Returns entity that is just after e in the entity list.
Useful to browse the list of entities, because it skips the undefined ones"
So it doesn't specify 'players', yet the iteration happens 32 times, so we clearly aren't processing all entities.. please explain */
continue;
/* 'continue' is recognised and compiles with the FTE compiler. btw i got confused, continue means 'stop this iteration, and start the next now, whereas I originally thought it means 'proceed with the rest of this iteration'. Now it all makes sense.*/
if (e == self) //only if the other player is not ourself.
continue;
/*
since the writebyte message is being sent only to ourselves, why is this line necessary? */
writebyte(MSG_ONE, svc_setinfo);
/* I still don't know exactly *how* this 'writebyte' command uses svc_setinfo to do what it does.... */
writebyte(MSG_ONE, n-1);
/*here we select what entity to change the skin of - the 'GasViewed' player */
writestring(MSG_ONE, "skin");
/* I (naively ) confused the writestring concept w stuffcmd, and mistakenly changed "skin" to "skin ". Wrong.*/
if (self.isgassed) //I dunno what your code is like
/* if (self.tfstate & #TFSTATE_HALLUCINATING) */
writestring(MSG_ONE, "default");
/* I'm currently using doomguy as the GasViewed players skin, might get a custom one made specifically for the effect. Psychadelia influenced maybe. */
else
writestring(MSG_ONE, ClassSkinForPlayer(e));
/* ok I assume ClassSkinForPlayer was pseudocode, so I replaced it with another function which returns a string with the correct skin used by the GasViewed players */
}
|
Spike wrote: | Note that if you're paranoid, you can clear out the team/bottomcolor/topcolor keys too. |
Well I'm currently using 'doomguy.pcx' as the Gasviewed player, and he doesn't have any team colours so i don't know if this is necessary or not, or whether not 'clearing' (not sure what this means in practice) will cause unforseen problems.
Finally, I'm still learning what's possible / not possible with Quake, so I'm curious about the following three (optional) ideas; again, I have no idea if these ideas are simple/easy, or impossible to implement:
1. Make it so that Grunties (ie monster_army bots ) ALSO appear with the same skin as the GasViewed players. I've looked at the code above, and can't see (since their .classname != "") why they would not be 'GasViewed'.
2. Make it so monsters (ie shammies, scrags, and fiends) AlSO have the same skin as the GasViewed players. eg a shamblers *actual* size stays the same, but he appears to the hallucinating player as a player. And yes, this means scrags will appear (to the hallucinating player) as players hovering midair.
3. Make it so that the GasViewed players appear twice as large. Ie suddenly they are giants - with parts of their bodies disappearing into walls etc.
Possible.... or not?
thanks,
OneManClan |
|
Back to top |
|
 |
Spike
Joined: 05 Nov 2004 Posts: 944 Location: UK
|
Posted: Mon Jul 19, 2010 12:21 pm Post subject: |
|
|
In both branches of Quake, the first X entity slots (after world) refer to player slots. A player entity will only ever be one of these first X slots. In QuakeWorld, there are _always_ 32 slots, regardless of what the max players is hence you can change it mid-map (don't forget spectators).
So those first 32 slots (after world) (so slots 1-32 inclusive) will only ever be player, spectator, or empty, and no other slot will ever hold a player or spectator.
nextent basically does ent = ent + 1;
Yes, it will skip over free entities. But here's the thing... Notice in the last paragraph I said 'empty', not 'free'. Player entities are always 'spawned' and never 'free'. So they never get skipped.
Thus nextent can be safely used to iterate over all player/spectator slots.
'continue' is a qc extension supported by fteqcc and frikqcc. It means the same as in C - jump to the start of the loop and continue with the next iteration (the break keyword breaks out of the loop).
The writebyte is sent to ourselves, but about other players. Skipping self means that we don't change our own skin, only everyone elses.
If this helps to explain...
type 'skin' at the console. Its a cvar, right?
type setinfo. You get lots of userinfo settings shown. handy, huh? perhaps not. moving on, change your skin. okay, type setinfo again.
Notice how your setinfo's skin changed too. The skin cvar is basically a wrapper (it is a proper cvar, it just sets your userinfo too).
Now do it on a server. Each userinfo setting you change gets sent to the server and broadcast to all clients, even back to yourself.
You can see this if you type 'users' and 'user $userid' to see other people's userinfos.
By sending an svc_setinfo from qc code, you're overriding the user's normal settings and focing their skin userinfo to one of your choosing - but *only* to the person you sent the message to. Everyone else retains their original setting, because you didn't broadcast it.
You can use the same trick to change the other fields of the user's userinfo, even protected fields like '*spectator', which can be used to trick the client into thinking its a spectator. Beware that it'll then try teleporting around, which the server won't like. :P
This will affect all ents with that player's colourmap.
setinfo affects only player's userinfo, not non-players. Other ents aren't users!
However, in FTE you can use customizeentityforclient and switch the model around as appropriate for the player that will receive it. This doesn't actually affect player entities due to me overlooking it, end even if it did, QW players don't send their colourmap field across the net, its hardcoded by slot in the client. I'll fix the fact that its not called some time, but can't really fix the fixed colourmap.
However, you can use customizeentityforclient to set a function to be called each network frame to... wait for it... customize... the entity... for... each client... yeah, obvious huh. :/
Anyway, its a field function. Set it to register your function to change the model/colourmap/origin/etc based on the attributes of the player.
You'll need to update your version of FTE before customizeentityforclient and mvd/qtv recording will work at the same time (mvd-watching clients cause the client argument to be world).
FTE does support a .scale field. It also supports scale origin functionality to scale models based upon their feet rather than their origin. But other clients do not. Use with caution. _________________ What's a signature? |
|
Back to top |
|
 |
OneManClan
Joined: 28 Feb 2009 Posts: 62
|
Posted: Tue Jul 20, 2010 2:48 am Post subject: |
|
|
Spike wrote: | In both branches of Quake, the first X entity slots (after world) refer to player slots. A player entity will only ever be one of these first X slots. |
Ahhhh, I see. And this is why the first iteration was n+1. Yes, yes, that makes sense now, thanks.
Spike wrote: |
'continue' is a qc extension supported by fteqcc and frikqcc. It means the same as in C - jump to the start of the loop and continue with the next iteration (the break keyword breaks out of the loop). |
Ok so the fteqcc compiler isn't just a 'compiler that makes a dat readable by the FTE server software', it also added to the list of statements that previous compilers of QuakeC didn't have. I found this description of QuakeC which includes some FTEQCC stuff, is there a definitive list somewhere of all the extra stuff?
Spike wrote: | The writebyte is sent to ourselves, but about other players. Skipping self means that we don't change our own skin, only everyone elses. |
But even if we *did* change our own skin, since the 'change this person skin' command is only sent to ourselves, no-one else would be affected...?
Spike wrote: | If this helps to explain...
setinfo affects only player's userinfo, not non-players. Other ents aren't users! |
Gotcha, so we need a different method for monsters..:
Spike wrote: | However, in FTE you can use customizeentityforclient and switch the model around as appropriate for the player that will receive it. |
I googled customizeentityforclient and found this bit of Nexuiz code. Where can I get more info/examples of its use?
Spike wrote: |
This doesn't actually affect player entities due to me overlooking it, end even if it did, QW players don't send their colourmap field across the net, its hardcoded by slot in the client. I'll fix the fact that its not called some time, but can't really fix the fixed colourmap. |
Ok, so I should use your existing SkinBlind function for GasViewed players, and make another using customizeentityforclient for monsters.
Re: the .colourmap field, I thought it referred to a players / items colours, and that the *server* enforced what colours entities are. ie a Red players Tesla will be told to use the Red colourmap by the server. I'm guessing I've misunderstood you here.
Spike wrote: |
However, you can use customizeentityforclient to set a function to be called each network frame ....
....Set it to register your function to change the model/colourmap/origin/etc based on the attributes of the player |
So wild newbie pseudocode:
(in player postphysics?) something like:
if (player.tfstate & #TFSTATE_HALLUCINATING)
player.customizeentityforclient = MonsterBlind;
void MonsterBlind ()
{
1. find all monster entities (is there a way to do this *once*, without having to do multiple 'find's for each type? eg
te = find(te, classname,"monster_army"); (use SkinBlind skin)
te = find(te, classname,"monster_demon1");(use SkinBlind skin)
te = find(te, classname,"monster_fish");(use SkinBlind skin)
te = find(te, classname,"monster_shambler");(use SkinBlind skin)
Is there some code I can have a look at which shows how to dynamically change the appearance of something? I remember there was a mod years ago where you (a player) would transform into a Shambler - so presumably the other players must have seen you change appearance. Since I assume a player.pcx skin isnt 'compatible' with a Shambler shape would I have to make the shambler invisible, and then spawn a temporary 'player' entity to mimic its moves?
}
Spike wrote: |
You'll need to update your version of FTE before customizeentityforclient and mvd/qtv recording will work at the same time (mvd-watching clients cause the client argument to be world). |
I noticed during testing that the mvd demo didn't record the SkinBlind effect, ie skins didn't change appearance for the hallucinating player.
Spike wrote: | FTE does support a .scale field. It also supports scale origin functionality to scale models based upon their feet rather than their origin. But other clients do not. Use with caution. |
Thanks Spike, I'll see if I can find snippets of code using .scale somewhere to give me a clue how to use it - a pity there doesn't seem to be a manual for any of this stuff - is there?
OneManClan
[EDIT: Just to help out any other newbs, I found some info on customizeentityforclient here (the ']' means I couldnt embed the link):
http://www.mancubus.net/svn/fsfps/?op=comp&compare[]=%2F@147&compare[]=%2F@146&manualorder=1 ] |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2004 phpBB Group
|