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
Something I Had Been Asking In The QS-Spiked Thread 
I am trying to make a kind of countdown timer display for powerups in CSQC (for Quakespasm-Spiked). The idea is to have five transparent overlay images for the powerup icons (Quad, Ring of Shadows etc) which cover more and more of the icon when a powerup moves towards expiration.

One of the many things I tried:

if (autocvar(cl_pwrtime, 1) == 1)
PowerupTimer();

I added this function above it:

static void PowerupTimer()
{
entity ptimer = spawn();
ptimer.nextthink = time + 5;
ptimer.think = PowerGFX1;
ptimer.nextthink = time + 5;
ptimer.think = PowerGFX2;
ptimer.nextthink = time + 5;
ptimer.think = PowerGFX3;
ptimer.nextthink = time + 5;
ptimer.think = PowerGFX4;
ptimer.nextthink = time + 5;
ptimer.think = PowerGFX5;
remove(self);
};

And before that (I am not listing all functions, just the first, and only for one powerup):

static void PowerGFX1()
{
if (sitems & IT_QUAD)
drawpic(pos+'272 8 0', "gfx/sba1_quad", '16 16 0', '1 1 1', 0.5, 0);
};

There are two problems here:
- The replacement image doesn't show up ingame. Tried with text (drawstring) and it also won't work.
- I don't know how to port over the vector "pos" (it's used in the function that draws the itembar on top of the statusbar). 
NightFright : 
I don't know anything about QCSC, but my default assumption is you'd need to call drawpic every frame, rather than the pic staying on screen until the next time you call drawpic with a different image. Second, can entities call drawpic? A quick google search makes it seem like you have to draw all images from within Hud_Draw. 
Different Approach 
Yeah, seems it's possible you can't draw images with entities. What about reading the powerup timer and switching the image instead of taking a break, then? Something like this in the item bar drawing function, right after powerup icons are drawn:

if ((sitems <= 25) && (sitems > 20)) drawpic(pos+ppos, "gfx/sba1_quad", '16 16 0', '1 1 1', 0.7, 0);
else if ((sitems <= 20) && (sitems > 15)) drawpic(pos+ppos, "gfx/sba2_quad", '16 16 0', '1 1 1', 0.7, 0);
else if ((sitems <= 15) && (sitems > 10)) drawpic(pos+ppos, "gfx/sba3_quad", '16 16 0', '1 1 1', 0.7, 0);
else if ((sitems <= 10) && (sitems > 5)) drawpic(pos+ppos, "gfx/sba4_quad", '16 16 0', '1 1 1', 0.7, 0);
else if (sitems <= 5) drawpic(pos+ppos, "gfx/sba5_quad", '16 16 0', '1 1 1', 0.7, 0);

(This doesn't work right now, ofc.) 
 
2d drawing requires specific ordering.
draw it before the renderscene() call and it'll just get drawn over. draw it before the sbar's background and it'll still be covered up by said sbar.

doing it inside an entity's think function will draw it one frame in a thousand... AND behind the 3d view so you'll never see it anyway. trying to do it inside a touch function is pure insanity.

even making your own .draw event and manually looping through all entities via nextent will mean that respective ordering will not be well-defined.
you may wish to use linked lists instead - ones you can control the order of.
Or just insert extra conditions into the relevant places, with any timers using globals or statics (besides, doing it each frame means you can get smooth colour/alpha changes instead of abrupt). 
How To Get At It? 
Unfortunately, my CSQC knowledge is kinda limited. If I wanted to have these timers using globals, what would that have to look like?

I basically need two timers, one lasting 30 secs (with stuff to do after 5, 10, 15, 20 and 25 secs) and another one 45 secs (same with 7.5 sec intervals), starting count for each of the powerups available in Quake, SoA and DoE. 
Kinda Got It Working 
It seems to work with this code:

static float poweruptime;

[...]

static void PowerupTimer(vector ppos)
{
poweruptime = (time - 5)*10;
if ((poweruptime >= 200) && (poweruptime < 250)) drawpic(ppos, "gfx/sba1_quad", '16 16 0', '1 1 1', 0.7, 0);
else if ((poweruptime >=250) && (poweruptime < 300)) drawpic(ppos, "gfx/sba2_quad", '16 16 0', '1 1 1', 0.7, 0);
else if ((poweruptime >=300) && (poweruptime < 350)) drawpic(ppos, "gfx/sba3_quad", '16 16 0', '1 1 1', 0.7, 0);
else if ((poweruptime >=350) && (poweruptime < 400)) drawpic(ppos, "gfx/sba4_quad", '16 16 0', '1 1 1', 0.7, 0);
else if (poweruptime >=400) drawpic(ppos, "gfx/sba5_quad", '16 16 0', '1 1 1', 0.7, 0);
};

And later on I call the function in the HUD drawing function for the item bar, like this:

if (autocvar(cl_pwrtimer, 1) == 1)
{
if (sitems & IT_INVISIBILITY) PowerupTimer(pos+'224 8 0');
else if (sitems & IT_INVULNERABILITY) PowerupTimer(pos+'240 8 0');
else if (sitems & IT_SUIT) PowerupTimer(pos+'256 8 0');
else if (sitems & IT_QUAD) PowerupTimer(pos+'272 8 0');
}

Remaining question:
Did I get the timing right with the 30 seconds in the "poweruptime" calculations? 
 
Hey, NightFright!

Since you are working with HUD, maybe you can help me.

Do you know how to change a weapon's pic in the same HUD slot? Like in the Rogue's mission pack, you can select the nailgun and the lava-nailgun, and the pic changes.

Keep in mind that my CSQC knowledge is none. I only know how to work with QCs :P 
Cheered Too Early 
@ Spike:
While it works in general, there's definitely something wrong with the timer(s). Looks like if I save a game and reload, the timer seems to go out of sinc, plus collecting more than one powerup at once completely screws up everything (first powerup is reset and second one is shown almost depleted).

@ Tribal:
I am actually a newbie regarding HUD programming as well. I can identify certain parts in QSS's CSQC code and alter them, but writing code on my own is kinda tricky. 
 
OK, it seems like the timer the way I have written it right now is actually based on how much time passes BEFORE instead of AFTER picking up the item. The longer I wait with picking up something, the more it will deduct from my powerup counter. 
 
CSQC doesn't get saved. if you want things to be correct after saved games then you need to ensure things re-replicate properly.

ssqc (worldspawn or so):
clientstat(STAT_QUADFINISHED, EV_FLOAT, super_damage_finished);

csqc:
float timetillquadexpires = getstatf(STAT_QUADFINISHED) - time;
float timesincequadstarted = time - (getstatf(STAT_QUADFINISHED)-QUADDURATION);


whereas if you're trying to avoid ssqc changes, you can just compare your stats against the last frame, and if quad is obtained then `quadstarted=time;`, then you can use `float timesincequadstarted=time-savedtime;` in your draw code.
Just be aware of the issues that can result if you saved the game while holding quad, or switch spectator tracking, or die etc. 
 
The behavior is like this:

I save while standing in front of a quad. Then, I pick up the powerup immediately. Timer image progresses (seemingly) correctly.

After reloading, I wait before picking up the item. The longer I wait, the more the timer image has already progressed. That means it's counting time without me actually picking up the powerup.

Would this be fixed with that code, then? 
 
@NightFright

Thanks for your reply :)

I think i'll try to mess around with the code until I give up =D 
 
I still wasn't able to pull it off. While it is progress that the timer graphics now show up ingame, getting the timer to work in general has turned into the challenge. It would be a lot easier with involving SSQC. In client.qc, there are conditions for what to do when a powerup expires, e.g. if (self.super_damage_finished < time + 3). It would be cool to use this, just with time+25, time+20, time+15 etc. But I guess it's not that easy.

However, I want to avoid SSQC edits. As soon as you have to supply a specific progs.dat, the hud would break as soon as a mod comes with its own, which is the case quite often. On the other hand, csprogs.dat files are still rather rare, so the mod would work most of the time. 
Now With Source File 
Maybe it helps to get a look at the actual code I am using. Here is what I have so far - it's not the entire thing, but it contains the HUD draw code, which is most likely where all the changes need to be applied.

HUD draw code CSQC

If someone were able to tell me at least roughly what needs to be put where, at least for the example of the Quad powerup, I might be able to figure out the rest on my own. 
 
Hi, there! o/

Today i discovered the viewmodelforclient's trick to show transparent weapons while using the invisibility ring.

It's working, but the weapons animation aren't interpolated. How can i turn on the interpolation for viewmodelforclient? 
 
It's me again... i'm trying to make the fish's corpse float in the water.

Here is what my code looks like:

void () check_waterfish =
{
if (self.watertype != CONTENT_WATER) //check if the fish is still in the water
{
self.velocity_z = 0; //if the fish is not in the water just stop the corpse
self.movetype = MOVETYPE_NONE;
return;
}

//if the fish is still in the water make him float up
self.velocity_z = 15;
self.movetype = MOVETYPE_FLY;

self.nextthink = time + 0.1;
self.think = check_waterfish; //check again if the fish is still in the water

};


... but the corpse keeps floating up out of the water. It never stops. What am i doing wrong? :( 
Tribal: 
seems reasonable, so maybe the assumptions are wrong. What is the actual self.watertype of the fish? try printing it to see. 
@metlslime 
I told the code to print the fish's corpse self.watertype, and "-3" show up in the console. I don't know what "-3" means, but it was printed just one time, like the code is ignoring the self.think and not checking again if the fish is still in the water :P 
Darkplaces Engine Bug 
in the darkplaces engine, fiends get stuck on geometry all the time. Does anyone know specifically what is happening? I'd like to fix or attempt a workaround. 
 
Some dark places differences can be toggled using cvars. Usually they start with “sv_gameplayfix_” so take a look at those to see if any of them fix it. 
Darkplaces Engine Bug 
Nope doesn't appear to be a relevant fix. 
 
That's just how Darkplaces do, as far as I know. Its physics code has been changed for various reasons. 
Darkplaces Engine Bug 
Sorry to be rude but I'm looking for a technical response or even a guess, rather than that non-answer.
Engines are extremely complicated so "That's just how it do" is an understandable response though :D 
Darkplaces Engine Bug 
Even a basic idea like are they literally getting stuck in geometry, or failing to navigate around it? Is it a bug in pathing code or collision code? Something else? 
Darkplaces Engine Bug 
Or perhaps someone can help with detection of if they are stuck or not from within QuakeC to apply some hackery.
Currently I am storing their coordinates in one animation frame and comparing with coordinates in the next frame:

autocvar_DemonLoc = self.origin_x;
autocvar_DemonLoc2 = self.origin_y;
};
void() demon1_jump5 =[ $leap5, demon1_jump6 ] {self.nextthink = ((time + 0.1) - autocvar_monster_rangedattack_animation_speed_factor * 0.001);
if (autocvar_DemonLoc == self.origin_x && autocvar_DemonLoc2 == self.origin_y)
{

But I am hoping I can do much better than this. 
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.