News | Forum | People | FAQ | Links | Search | Register | Log in
Coding Help
This is a counterpart to the "Mapping Help" thread. If you need help with QuakeC coding, or questions about how to do some engine modification, this is the place for you! We've got a few coders here on the forum and hopefully someone knows the answer.
First | Previous | Next | Last
 
ohh bizarre, i just noticed that. i think that is the only (or one of the very few?) variables that, when changed, prints text to the console.

whelp, you can try mfx's suggestion of just adding 3 extra '/n's to push that output away, but they'd have to be on the NEXT frame, so you couldn't just do localcmd("sv_gravity 100\n\n\n\n\n");

you'd need to track when you changed the gravity, and then next frame run the newlines on stuffcmd for EACH client. ugh..... 
 
I tried setting it up so it would think 0.1 seconds later, jam 3 newlines in but it seems to ignore those for whatever reason. Nothing happens.

Unless there's an elegant solution, I'll just live with it. Chalk it up to Quake being Quake... 
 
Try setting .gravity on every entity individually? 
 
How does quake do it for e1m8? 
 
E1M8 is a QuakeC hack ...

cvar_set ("sv_gravity", "100");

I guess they don't care that it spams the message out. Or maybe you just don't notice it during the level load, I dunno ...

It's right at the very top of "void() worldspawn" ... 
 
yeah, i think at the time that command is run, the player isn't spawned in yet, so they never receive the message.

try using metl's suggestion of setting .gravity while cycling through every entity in the map with find()... it's goofy, but it'd work quietly. 
 
Some time recently, either in this thread or modeling help (I think), someone (probably preach) talked about ways to make an entity out of more than one alias model, and have them move in sync via quakec trickery.

It's not a hard problem at all - unless the entity is an AI being moved around by the navigation code. then movetogoal might not succeed for all parts of the collective entity because some of it will collide with something and the rest won't, and you'll get a discontinuity. Constant setorigin()s are laborious and not fully reliable, especially in the above case, and polling/setting velocity will lead to weird one-think lags after direction changes. Maintaining yaw is just as bad.

It might actually have been some CSQC or FTEQW extension? Nobody documents anything over there so it's impossible to just look it up.

My parameters are that I'm okay with one entity being the collision master and all the rest being nonsolid, but if the 'master' is still being driven by ai_forward()s and all that the 'slave' has to react accordingly. 
 
A better way to ask (with some forethought put into it):

movetogoal() in quakeC is called during the think cycle, but it's evaluated during physics/touching, correct? So if the master does an ai_forward(20) at an enemy 10 units away, physics will move it 10 units (until the boxes touch). If the slave is thinking in tandem (and it should be if it's also trying to match frames) then it will already have thunk by the time physics gets around to the master's SV_MoveToGoal(). It can't see that little bit into the future physics cycle to know how far its master is going to move. So, is it impossible? Or have I got this wrong? 
 
no, the 'physics' of the ai moves are done as they are called. this is how you can use walkmove and get a return value on if the walkmove was successful or not.

this means you can recursively or iteratively solve walkmoves in a single frame and you don't need to rely on child entities to think for themselves. you can have the master run all the thinking on its children so make sure everything is synchronized. 
 
btw: movetogoal does not return anything, but you can just check if the origin of the entity after you called the method is the same as before. if they are, then it failed... 
 
How do movetogoal and walkmove interact with model lerping? 
 
only seems to matter where the monster is at the end of the frame, not matter on how many times any of those methods were called. 
Setorigin Stuff 
If you do decide to go down the setorigin route, I recommend use the EndFrame function from

https://tomeofpreach.wordpress.com/2014/05/24/easily-fixing-the-endframe-function/

This ensures no QC which runs later in the frame can desync your models. 
 
So my approach should be
- give each model the same origin for sanity's sake
- make sure the attachment thinks second, presumably by having the master itself spawn() the attachment so it's a higher numbered entity
- have the master be aware of how far it actually moved each think and notify its slave(s)
- maintain the same ideal_yaw and yawspeed on all parts
- do a final setorigin() in an end of frame function if necessary (wouldn't having the master setorigin() the slaves at the start of its own think have the same outcome?)

didn't ijed do something like this in RRP? with destroyable gun arms or something? 
Nope 
Those were just more animation frames with the arms hidden inside the body and a value keeping track of the destruction state. 
 
I've only used multiple entities for a single enemy when I wanted them to move independently - to help with navigation, provide effects of one type or another or not move locked to the master monster's origin.

FTEQCC allows you to have multiple meshes used by a single monster if needs be, removing that blocker.

What are you aiming for? 
 
Mostly saving vert precision on the important core of a model without sacrificing any to its giant tentacles.

FTEQCC allows you to have multiple meshes used by a single monster if needs be

Yeah, how? It's not documented anywhere. 
 
FTEQCC doesn't really provide anything that couldn't otherwise be achieved with perverse unreadable QC (like arrays).

the qcc really doesn't have anything to do with multiple meshes - anything along those lines are engine extensions rather than qcc ones.

in order for an entity's interpolation to match another, it should (depending on the client in question) update its origin at the same times, its movetype, its angles, its .frame, and its onground flag. If any of these differ at the end of a frame (this includes independant player physics partial frames) then a client may see a desync.
the client may also see a desync caused by packet overflows (or equivelent) also (although often that would just manifest as completely invisible ents).
MOVETYPE_FOLLOW(if the follower has a higher entity number which is fine if you manually spawn the second entity within the first entity's own spawn function), customizeentityforclient, setattachment, or csqc can all be used to easily keep a 'sub' entity tracking a parent. you could also give the follower a nextthink=time for a similar effect and limitation as movetype_follow. or you can use EndFrame (either the extension or preach's hack).
In QuakeWorld, other players are predicted. There is no way to guarentee that an entity can exactly follow a player other than with setattachment or csqc with quakeworld protocols (non-players are not affected by this limitation, and in fact vanilla qw has no non-player interpolation at all, but that's just vanilla being lame).

setattachment is the easiest and most reliable, but requires dp or fteqw in order to work (on the plus side, it can also work with md3/iqm tags - use an empty tagname for formats with no tags/bones and it'll attach to the entity itself). It was made for this sort of thing.
Note that the subentity's origin is typically set to '0 0 0', which can be a little weird. 
Well 
To use multiple different meshes from the same creature, back in RMQ/Schism, I added this:

$framevalue 0

After each listing of animations as $frame for each model.

They still need precaching of course and setting to self.model = thenewone when you want to swap things about.

Here's the Ogre Qc from back then as reference:
http://pastebin.com/JiDMsbSL 
As To 
The whys and wherefores, I bow to Spike's superior knowledge - and Gb who figured out how to use this back in the day.

If memory serves, it was that other compilers would explode when trying to parse the additional animations rather than spit out a usable progs.dat 
Bump Around 
I'm forced to confront an issue I've noticed out of the corner of my eye a lot - monsters whose yaw angles will seem to spaz back and forth while meleeing, specifically on melee frames that use ai_charge().

ai_charge leads to SV_MoveToGoal() in sv_move.c, which eventually winds up calling SV_NewChaseDir() under certain conditions. SV_NewChaseDir() rounds ideal_yaw to the nearest 45, tries some navigation stuff, and if none of it is successful, overwrites the entity's ideal_yaw with the rounded value. I can't really tell why.

The outcome of this is that if a monster is in melee frames (when it's really close to the player) which call ai_charge() (which they nearly all do, since most monsters' melee attacks have some forward movement to keep the player close), every couple of frames its yaw is pulled hard to one side or the other, then immediately lerps back as the monster yaws back to its enemy. I've verified this is the case with shotgun bprint debugging, and I've verified it happens in id progs 1.06 too.

What can I do? I'd rather not disable a monster's ability to yaw by taking out the ai_charge()s. Can anyone who understands SV_MoveToGoal() better than I do suggest anything brilliant? 
Dull Idea 
To me it seems that the original intention there is to just have the monster stay close, so why not stick with that.

The method of aiming the monster at the player and then pushing it forward makes it wobble, as you say, so why not add a new ai_propel(); which does it the opposite way round - move the monster along the shortest point between it and the player and then give it the ideal yaw.

Potentially this could make it move sideways if something weird happens but that's nothing you couldn't account for by testing the facing beforehand and discounting the propel if the yaw is too wacky - possibly reverting to good 'ol ai_charge(); if that's the case.

There are probably better, coder ideas to be had, but this could be an interesting thing to mess about with. 
 
That doesn't solve the problem. c changes the yaw to something and the model renders and you see it twerk left or right for a few render frames, regardless of what order the qc moves and yaws before or after that happens. 
Lazy Idea 
Adding

self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);

straight after movetogoal (d); in ai_charge is certainly a straightforward way to eliminate the wobble. What you might ask is how much difference it makes elsewhere. I mean, we're overwriting the change SV_NewChaseDir makes, and while we've identified a case where it makes an irritating change, does it sometimes make a beneficial change instead? You might imagine that on occasions when it finds a direction the monster can walk in, we may want to retain that information.

I'd argue that no, almost every time it makes no difference besides the visual glitch. My reason is that the preceding line in ai_charge is ai_face ();. This actually resets ideal_yaw in the same way our added line of code does (I straight copy-pasted it from ai_face). So any time an ai_charge is followed by another ai_charge next frame*, the information from SV_NewChaseDir is discarded without being used. Keeping it will make little to no difference.

Ah, if only they could all be one-liners...

*Here by "next frame" I mean next monster animation frame, not engine frame. 
Duh 
I guess that's kind of what ijed was getting at too. Just reset it immediately. i'm tired. :p

Will test soon. 
First | Previous | Next | Last
You must be logged in to post in this thread.
Website copyright © 2002-2024 John Fitzgibbons. All posts are copyright their respective authors.