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
 
You don't need to modify the sprite, you just need to remove the animations you coded in the QC code.

If you don't use makestatic() in your torches, they will consume more network bandwidth and can generate packet overflows. And if you use makestatic(), your QC animation code will not work. Framegroups solves this problem, by making their animations client-side.

Also, from Fimg's help:
The sprite format used by Quake is the first game sprite format supported by Fimg. However, some of the design ideals of Fimg and a few aspects of the Quake Sprite Format are in conflict. As a result there may be a few things you need to know about Quake sprites before you use Fimg to edit them.


Quake sprites are composed of a number of frames. Each frame either consists of a single, unpaletted image or can be in a 'framegroup' where it is then composed of 1 or more unpaletted images. If the sprite contains no framegroups, Fimg will load the sprite as a simple animation sequence under a Fimg group titled "[no group]".


Fimg was designed to support a more general method of grouping frames where each group is an named animation sequence composed of a number of frames. As a result, if a Quake sprite has any framegroups, it will be loaded differently than previously described, where each 'frame' of the image is treated as a seperate animation sequence group. Each frame will in turn be named "Group X". where X represents the original frame number of the animation.


If Fimg loaded the sprite as a simple animation sequence, the only group will be named "[no group]". The Quake sprite saving routines look for the name "[no group]", and if found and it is the only group present, the animation will not be grouped. Therefore, if you'd like to group the frames for the animation, simply choose Groups->Rename from the menu.


When in a framegroup, each frame has a "Duration" key that indicates the delay for the frame. See the Properties Editor for more details. In addition, all frames have Origin values. See the origin tool for more details about this.


In addition, there are global properties for the file. For clarification, they are:
· Beamlength = Appears to be unused within the engine and is related to Doom style upright sprites.
· Radius = Is normally auto-calculated. If the size of the sprite changes, it is recommended you delete this property so Fimg will auto-regenerate it.
· Synchronous = When auto animating in a grouped frame, should the engine synchronize all instances of this sprite? If, for example the sprite is a fire, having all fire sprites start on the same frame would look ugly and obvious.
· Orientation = How the sprite will orient in game. The only two modes supported by GLQuake are "Oriented" which means the sprite will obey it's orientation and will appear as a flat plane, and VP Parallel, which means the sprite will appear as always facing the viewport.


These can be found by clicking the File Properties button or by clicking File->File Properties.
 
Thanks! 
That clears up a lot. I'll see through it.

I exported all frames from the sprite back into FimG and it was declared as (nogroups).
All flames turn into one frame, but no warnings,
:P 
Flight 
Hello, I would like to make flight physics for player in quake. I mean gliding in the air while player is falling, so it shouldn’t be just slowing down while falling, it should be something like paraplane or paraglider physics.
What I want to realise:
https://youtu.be/vJouxKs7T9c
How it can be done in games:
https://youtu.be/w5Es-kXif7k

I use sv_player.qc for working with player physics. Also, I am using dpextensions.qc as I am trying to make that on darkplaces engine.

I found some information and documentation about QuakeC on insideqc but still nothing helped me.

Does anybody knows how to realize gliding physics on quake? 
 
Maybe one chance for something similar is to find Zerstorer QuakeC devkit and see what the "wings" powerup does.

I tried it once but can't remember what it was like to use it. Is it in any of the Zersteror single player maps? I can't recall, but I'm not too much of a "find every secret" type. 
@-Reyond 
There are Parachutes and Skateboards in the Malice code.
Maybe a good chance to start.

Malice-QuakeC-master 
Wrong Link 
 
i think basically, every frame the player is airborne you want to reduce negative z velocity to a target falling speed, and accelerate forwards up to a max forwards speed.

if you look at the ladder code in rubicon 2 you can see that i'm modifying player velocity whenever player is on a ladder. You can remove the ladder check and add check for onground, and then do your velocity modifications the same way. 
 
Sure, I heard of Parachute in Malice, but that is not really what I need. I also should work with horizontal velocity and vertical velocity to make dependence between them like in real glider. I don’t need just to “slow down falling” 
I Thought Wings 
...thought wings were in Nehahra. Every time you tapped jump you lurched up a bit and you slowly drifted back down. Kind of like an infinite double jump. 
 
You could also set player .gravity to something like 0.4 or 0.5. 
 
What you want is a MOVETYPE_FLY that's slightly affected by gravity, and with lower friction.

I don't know if sv_friction affects MOVETYPE_FLY, or if the aerial friction is hardcoded. 
 
I thought about things that should be realized so it could work:
1. I should make flight vector. This vector should follow view angle vector but with a small delay. That makes our flight more realistic. Also it allows to set maneuvering.
2. When player falls down he accelerate, when he looks forward he slows down.


I have some suggestions how it can be done:
1. vector fly_direction, float m;
makevectors(fly_direction);
makevectors(self.v_angle);
if(fly_direction != self.v_angle)
{
if(fly_direction_x != self.v_angle_x)
{
fly_direction_x += (self.v_angle_x - fly_direction_x)/m;
}
if(fly_direction_y != self.v_angle_y)
{
fly_direction_y += (self.v_angle_y - fly_direction_x)/m;
}
}

//acceleration
float coef;
//fly acceleration coefficient
coef = ((self.v_angle_x-45)/90);
velocity=acceleration*coef; 
 
Please help me to translate that into quakeC properly 
Possible Version 
Here's what I'd do, roughly:

//convert current velocity into speed and direction
speed = vlen(self.velocity);
olddir = normalise(self.velocity);

//convert angles into a normalised heading
makevectors(self.y_angle);

//add a small amount of the heading to the current direction of travel
newdir = normalise( v_forward*frametime + olddir*(1-frametime));

//preserve the speed we had, but change the direction
self.velocity = newdir * speed;

//reduce the strength of gravity based on how level we are currently flying
self.gravity = 0.1 + 0.9*abs(v_forward*'0 0 1');


Some of the values might need tuning here and there, but that should get you started. Player movetype should be left as default, because we want gravity to apply (subject to the last line reducing how fast we fall. Haven't tested this, so it may be rubbish... 
Correction 
makevectors(self.y_angle);

should of course be

makevectors(self.v_angle);
 
 
use dotproducts:
upspeed = self.velocity * v_up;
fwdspeed = self.velocity * v_forward;
rightspeed = self.velocity * v_right;
(vec*vec is a dotproduct).

You can then get back to the original velocity vector with:
self.velocity = v_up*upspeed + v_forward*fwdspeed + v_right*rightspeed;

Of course, if you change some fraction of the force exerted on the underside of your glider before reforming the velocity then you'll reduce the effects of gravity while horizontal, and return to normal when facing vertically down.
Of course, that energy should normally go somewhere - if you add to fwdspeed anything you subtract from upspeed then you should get something a bit glidery.
you'll also need to include some friction somewhere, in order to get some terminal velocity. and yeah, the conversion should probably also not be 100% efficient either, nor should it convert ALL the energy.

but yeah, dotproducts are great if you want to compare two directions. trying to do stuff like this without using them is just going to leave it feeling really hacky.
Unfortunately there's no real way to control the camera from ssqc, but csqc can override the camera angles without changing the client's 'desired' angles. you should be able to implement roll that way, somehow. 
Notes After Testing The Suggested Code 
Had a go with the code from my post on Saturday, it worked pretty well for a first attempt. I did find that it wasn't responsive enough until I doubled frametime everywhere it appeared. One big tip for testing it - use e1m8. Firstly because its one of the few ID maps with enough vertical and horizontal space to glide in properly, secondly because it's low gravity so it's much more fun!

It's got most of the effects you'd want to see in glider physics - you can dive down to gain speed then level off and carry the momentum forward, and if you look up you'll gain height but bleed forward speed. You can look straight up, and you'll quickly stall then crash to the ground. Also if you collide with walls etc your speed is lost which tends to end the flight pretty quick.

One advanced trick: you can accelerate in Quake while in the air. If you're gliding, strafe left while turning in an anticlockwise circle and you'll gain speed (same principle as bunnyhopping works on). You can use this to offset the loss of speed while climbing, and gain height by moving in a big spiral. 
Preach’s Code Test 
Hi Preach, yesterday I arrived to my PC and I got an error after compiling your code. May be I have done something wrong. Could you please post a full file with your code so I could test it out? I think that would be useful for all the community. 
 
Maybe if you post the error you're getting we can help you out ... 
Skeleton Code 
I tried to post it as skeleton code so that you'd get some practice hooking it up. One thing I did unintentionally was to misspell (well, anglicize) a built-in function name, so make sure you change the spelling to normalize. If that wasn't the error that's stopped you, post it like c0burn says and we can suggest fixes. 
 
Still no result. I try to use this code if no flag on_ground is false but nothing works. 
New Issue 
Hi Reyond. It sounds like it's a bit further on if the compiler error has gone away. What function are you running the code in? I ran it in PlayerPreThink so that it would happen every frame. You're right to disable the code when the player is on the ground, but from your description I don't know whether the code you have is right.

I used: if(self.flags & FL_ONGROUND) to see if the player was on the ground. I also turned the code off while the player was in water using the check if(self.waterlevel) (although that's a detail to add once the basics work.

If that doesn't help, post the whole text of the code you're using and maybe we can spot what else it could be... 
Tut From InsideQc 
Found an old tutorial from Legion with an Xman version of a FlySimulator. Maybe helpfull as a guide. 
 
Allright, I found an error. Here is how I use the code:
else // airborn
{
vector fly_direction; vector new_dir; float fly_speed;
float fly_velocity; '
float koef;
/*
if (wishspeed < 30)
f = wishspeed - (self.velocity * wishdir);
else
f = 30 - (self.velocity * wishdir);
if (f > 0)
self.velocity - self.velocity + wishdir * (min(f, sv_accelerate) * wishspeed * frametime);
*/
fly_speed = vlen(self.velocity);
fly_direction = normalize(self.velocity);
makevectors(self.v_angle);
new_dir = normalize(v_forward*frametime +fly_direction*(1-frametime)); self.velocity = new_dir * speed;
 
Yes, actually it looks a little bit like gliding but I can’t understand how the code works. Why do I use frametime if this function works every frame? How this code affects the gravity (in-game gravity is 100 now). And how can I improve this code to make it work better?

Also, I would like to make it works without changing the standart “800” value of the sv_gravity variable. Is that possible?

Also, thanks to Preach and to everyone who helps me in making player gliding in quake. 
Try It Out 
Have a go with the second-to-last line changed to

new_dir = v_forward;

This leaves out the bits with frametime. What you should notice is that while gliding, you instantly start moving in exactly the direction you are facing. It's very easy to control, but it's not very realistic for a glider - you can 180 turn instantly at any time.

The idea behind the frametime code is to add the v_forward part more slowly, so that your direction of travel doesn't change instantly. Instead we add the v_forward in a bit at a time. Because the function runs every frame, we need the pieces we add to be smaller when the framerate is higher, otherwise people with higher framerates could execute tighter turns, which would be unfair.

I found that in practice the rate of change was too slow, and that it was better to change that line to:

new_dir = normalize(v_forward*2*frametime +fly_direction*(1-2*frametime));

By making the piece we add each frame twice as large, we get a better trade-off between smooth turning and reaction time.

In terms of making the glider float, I noticed that you don't have the last line from the code I posted:

self.gravity = 0.1 + 0.9*abs(v_forward*'0 0 1');

I expect you were getting a compiler error from this line that you didn't know how to fix. The secret is to add the following to the bottom of defs.qc:

.float gravity;

This warns the compiler that you'd like to be able to store a float called "gravity" on all the entities. The engine uses this to change the gravity just for that entity. So if you are flying in normal 800 strength gravity, but the player has self.gravity = 0.1, for that player gravity will be 80 instead (because 800 * 0.1 = 80). All other entities are unaffected, try firing a grenade while gliding and notice that it falls normally.

Give it a go, see what comes of it! Any more questions, just ask... 
 
Error: unknown value “abs”. 
To Reyond 
its fabs i think 
Yup 
Teach me to copy-paste from the sketchy untested post rather than the working code, use fabs and it'll work. 
 
Finally, we have a nice result!

Watch this:
https://youtu.be/vuXm64C_xso

Thanks to Preach for the code and to st1x51, Baker, madfox, metlslime, Qmaster, Spike, mankrip, c0burn and to all who helped me with this.

Here you can get progs.dat file to check it out:
https://drive.google.com/open?id=1U1Qb6nN3nTc9zwpRYZotGen_weFsBjIQ

And here is the source code (use dpextensions.qc or fteextensions.qc to compile it and add .float gravity in to the defs.qc):
https://drive.google.com/open?id=1Mck52dhvC7KKKOkC2N3QzGcgiBqQJtQU 
Reyond 
Tried in on E1M7 in FTE and it works nice.

Congrats! 
Improving The Code 
Is there any way to slow down flight? I have to make huge maps to make flight works properly.

And is there any way to change the value of horizontal speed loss?

Is there any way to make this work in standard quake without ising fork engines extensions? 
Improving The Code 
Is there any way to slow down flight? I have to make huge maps to make flight works properly.

And is there any way to change the value of horizontal speed loss?

Is there any way to make this work in standard quake without ising fork engines extensions? 
Generic Engines 
In theory, if you set the player's movetype to movetype_none in PlayerPostThink, and back to movetype_walk in PlayerPreThink, then you can insert a call to your (renamed) SV_PlayerPhysics at the start of PlayerPreThink and get a similar result.

In practice, doing so would leave you with no way to determine the user's intents (read: the .movement extension). You can work around this by using movetype_noclip instead of the movetype_none above, and to then try to guess the intents according to how the player's velocity accelerated between postthink->prethink (hint: dotproducts, see my earlier post). You'll also need to unwind those noclip-based velocity changes which will require some kind of shadow field, and clearing the velocity field in playerpostthink will make your .movement guessing logic more reliable.
Either way, it'll screw over prediction and get confused by knockbacks.

.gravity exists in all quake engines since hipnotic. You should be able to knock up a min/max function easily enough. I don't think there's anything else in there that's a problem. 
Engine Neutral 
My code runs fine in standard quake engines (once you define the .gravity field to enable that feature). You just run it in playerprethink, it uses standard player physics but then just rewrites the velocity each frame.

To slow it down, I guess you could do a number of things. One thing would be to reduce gravity further, even while facing down, so that you can't build up speed so well. Another would be to add a cap to fly_velocity after you calculate it:

if(fly_velocity > MAX_FLY_VELOCITY)
fly_velocity = MAX_FLY_VELOCITY;

Without this, the player can achieve speeds up to the global maximum speed an entity can reach, which defaults to 2000! 
Quake1_test 
On Quake Wiki I read the Trivial of the HellKnight.
The intention was to let Rangers spawn when the Hellknight is hit.

The same applies to the Axe_Ogre, which I managed to give some extra postures.
In this case, the Ogre should laugh when someone dies.
A more peculiar fact was pissing on the player's body.

If I were to start coding ... where should I start?
Something like pissing on the player would mean something to the player.qc and ai.qc.
Laughing when someone dies is a more general topic. 
Take A Leak 
PlayerDeathThink in client.qc, add a while loop that use

spot = find (world,classname,"monster_ogreaxe");
if ( spot ) {

spot.think = ai_leak1;
spot.leakentity = self;

}

Then set goalentity to the leakentity in ai_leak1 and self.enemy to self.leakentity. Do some ai_run()s inside your ai_leak1, 2, 3, etc. check for distance using vlen and start ai_leaking1 when close to player. In ai_leaking1, 2, 3 do your leak anim frames and play a sound effect maybe. 
Of Course 
You may need to add a .float to act as a bool so that you only check for axeogres in PlayerDeathThink once, something like

if(!foundleakers) {
foundkeakers = 1;
//while loop in here
}

And then in respawn() maybe add a foundleakers = 0; call. You might need to get fancy with coop though. 
I... 
...assumed the idea was that if the ogre killed the player then just that particular ogre would piss on the player, however...

Qmaster is making me think that if the player dies then all the ogres in the map would start making their way over to the player's corpse for a great big ogre gang-corpse-piss-party, and if I'm being totally honest with myself, that idea is too compelling to just pass up. 
Laughing Is A More General Topic. 
Let's assume the idea that if the ogre killed the player then all ogres would laugh.
The same a strange way when they're fighting between themselves and all start laughing when the player dies..

So these extra poses would concern the player only.

If I take PlayerDeathThink, and start adding code exact above respawn();
and under the self.button2 = 0;
the new code looks like:
self.button2 = 0;

}

spot = find (world,classname,"monster_ogreaxe");
if ( spot ) {

spot.think = ai_leak1;
spot.leakentity = self;

}

respawn();
};


client.qc:805: error: unknown value "spot".
I know I'm a geek what coding concerns,
no idea how to make a spot statement.

laughing Axe_Ogre
lapaz Axe_Ogre 
Christ On A Bike. 
 
Playing The Fiddle Onehanded 
 
 
Make some minor changes to the micturating ogre model to give it a more ejaculatory flavour, and boom - cool new projectile attack. 
 
local .entity spot; 
That Was A Bit Disturbing Actually 
 
 
The way the ogre's balls rhythmically scrunch up on each cycle suggests we're getting something a little bit extra, not just urine. 
Make It Happen Madfox 
 
I Regret Having Been A Part Of This. 
Don't forget to do a particle(self.leakentity.origin,'0 0 0',60,18); for added effect 
I Screwed Myself Almost Geek On Those Fucking Flies! 
I could have suspect these intimate subroutines would lead to hillaric reactions, but..,

my bike had a leak last christ, and I wonder who'll pay the fiddler off.
I suggest kinn giving it a good smile sound.

Thanks Qmaster, I didn't warn you before I asked your help with my q1test. But you're welcome. I tried your email, but it didn't work.
Right, so I'll start with
local .entity spot;
The extra effects, it's like knowing the name of the statement, but not where to paist it in. 
I Changed 
in PlayerDeathThink after the buttons:

self.button2 = 0;
respawn();

//===new code===

local float entity spot;

local .entity spot;

spot = find (world,classname,"monster_ogreaxe");
if ( spot ) {find (world,classname,"monster_ogreaxe");

spot.think = ai_leak1;
spot.leakentity = self;

}
};

//===end code===


error: no spot value.

then I added to defs qc line 139 :

.float skin;
.float effects;

//===new code==
.float spot;
//===end code==


Client.qc:812: error: type mismatch = (FIELDTYPE and entity) 
 
local entity spot;
no extra dot
(you want an entity, and not a field reference[of sub-type entity]) 
 
my bike had a leak last christ, and I wonder who'll pay the fiddler off.
I suggest kinn giving it a good smile sound.


I...just...I...but...nothing. 
Stumbling Is A Kind Of Laugh 
Appoligize my passionated reaktion, as I'm stupid enough to write down my nonsense before my smart conclusion starts reasoning.:P

Thanks Spike. Now I'm back at start with:

//=========new code===========
local float entity spot;
local entity spot;

spot = find (world,classname,"monster_xogre");
if ( spot ) {find (world,classname,"monster_xogre");

spot.think = ai_leak1;
spot.leakentity = self;
}

};
//====================end code==

client.qc:808: error: local not a type
client.qc:808: error: spot not a type
client.qc:808: error: if not a type
client.qc:808: error: self not a type 
 
local entity spot;
just that.
not 'local float entity spot;' - that's meaningless conflicting keywords. 
 
yes, but as soon as I add a line in client.qc before ClientObituary I receive the error "local" and "spot not a type".
How do I make them to a right statement? 
Ah 
I changed some parms

void() ai_leak =
{
local entity spot;
spot = find (world,classname,"monster_xogre");
if ( spot ) {find (world,classname,"monster_xogre");
{
spot.think = xogre_leak1;
// spot.leakentity = self;
return;
}
}
};


if I exclude spot.leakentity it compiles well,
warning that "Local "spot" not defined with a name of a global"

Wow, I've got an ai_leak!
What should be the next step? 
 
if ( spot ) {find (world,classname,"monster_xogre");
{
local entity pissee;
spot.think = xogre_leak1;
if ( pissee ) {find (world,classname,"monster_donaldjtrump")
spot.enemy = pissee; 
QuakeC Locals And Globals 
local makes that variable only work within the function--inside {} and ONLY after it has been declared (pretty sure about this second part).

Globals are any variable defined outside, e.g. in defs.qc (at the bottom of defs.qc anyways)

You need to define a .entity leakentity; somewhere outside a function and before you use it in client.qc.

E.g.

.entity leakentity; // entity to remember for later so the monster knows where to go take a leak

void ClientObituary() {
local entity spot; // entity to hold our axe ogre


//your find down here
...
};

I'll let you figure out how to make the monster hunt down the player location and then begin the actual taking a leak. 
Ho 
I'm back in PlayerDeathThink.

spot.think = xogre_leak1;

error: xogre_leak1 unknown value.

I can make a "void() xogre_leak;" at the top of the client.qc list,
but it keeps the error. 
Wait 
There is something I need to explain first. As I mentioned before I am working in the Q1Test environnement. Also I added the Dragon code, rubicon.qc as some other feathers. I also wanted to add a catapult in stead of an axe.

One thing I would like to keep original to the Q1test mod.
Sounds, conback, weapons, and monsters. Reason I add the Axe ogre and Serpent, Vormitus, as the Shalrath's queer apearance is, because that were the trivial things that were not implemented. The dragon form Megalol had a solution, but the mod from Patrick Martin I included has a more sensitive way.

So I started with the "poor" q1test src, and slowly tried to find a way through the queer qc that was forehand. No Axe, nowammu_cells plz, and other butheads, like no change_level, just the stripped down qc to deathmatch.

Now I'm at the point that I'm testing the monsters, but it gets a little tricky , when I would assume the errors I get involved in are not the ones that apear in normal vqcc106.

Enough, I've got ai_leak that compiles.

//=========================================
After ClientObituary:

local float rnum;
local string deathstring,deathstring2;

local entity spot; // entity to hold our axe ogre

if ( spot ) {find (world,classname,"monster_xogre");
{
local entity leak;
spot.think = xogre_leak1;
}
}

rnum = random();

if (targ.classname == "player")
//=========================================

I had to add a new statement at the top for xogre_leak1 as it was not a value.

How do I make it aware for the player's death? 
Queer Or Queen 
 
Um, Compile With Fteqccgui? 
 
Qmaster 
I use fteccgui as fteqccgui. I can compile the client.qc but I have no idea how to make it correspond the player's death. I think it needs some more code.

local entity spot; // entity to hold our axe ogre
if ( spot ) {find (world,classname,"player");
{
local entity leak;
spot.think = xogre_leak1;
}
}


I tried your email, but it faints. 
First | Previous | Next | Last
Post A Reply:
Name:
Title:
Body:
message
question
exclamation
idea
flame
noflame
error
skull
beer
moon
pent
rocket
sheep
pacman
pig
cheese
worldcraft
gauntlet
crate
pitfall
pimp
smile
cool
sad
frown
oi
yay
tongue
evil
wink
neutral
q1
q2
q3
ut
hl
cs
doom
dkt
serious
cube
Website copyright © 2002-2018 John Fitzgibbons. All posts are copyright their respective authors.