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
I'm fairly sure that's un-doable in vanilla.

you can absolutely mod progs.dat to do this though 
here is a quick and dirty proof of concept, no options just respawn in situ with 100 life 
Rubicon 2 has a resurrection cheat — impulse 666. You could look at that code. 
Really Helpful 
Thank you guys this is awesome! 
MapSearch & Inky's Hexen II Mapping Corner 
Hello everybody,

I answer to my own post #2802...
As said, I developed a very handy and powerful command line tool (supporting regexes and spawnflags search) to investigate map files and understand better how those at Raven & iD Software made their maps to learn from their example.

I'd be more than happy if it can be useful to some of you as it was for me :

I would like to take the opportunity to also introduce my newly born website 'Inky's Hexen II Mapping Corner' which has the ambition of becoming a reference for those mapping for Hexen II. Anybody's advice or contribution to make the site grow faster and improve in quality would be most welcome. :-)
Feel also free to backlink it, if you like it, to make it gain some audience and help the small Hexen II mapping community to reinforce its network.

Last, a more direct request to you: has anybody out there the math and programming skills to help me with finding the 'x y z' position of a brush's center of gravity, after the brush definition stored in a map file???

Thank you in advance for your feedback! :) 
QuakeC NOOb Needs Help 
Hello all - long time!

I'm working on a server mod that is a mashup of a few different things:

- Reincarnation base map (old server DM mod from Gen and others)
- Added FrikBots
- Added Map Rotation
- Added Multi-skin support

I had a few things I'd like to try and clean up and desperately need some QC help as I have little clue with that I'm doing.

Here's the things I want to achieve:

#1 - Add custom skins to bots

I have custom player skins working for players (you can cycle through up to 32 skins attached to the player model). FrikBots has 16 different bot profiles, and I'd like set each different bot to use one of the custom skins. How can this be done (like what Omicron Bots did)?

I tried this, but it doesn't work:

self.b_pants = 11;
self.b_shirt = 0;
return "Vincent"; = 1;

Let's take one question at a time. Any idea how I can assign skins to the bots? 
Taking The First Exit 
Hi Mezmorki. On the third line of your code you have

return "Vincent";

The return statement does two things. One is that it specifies the value which will be handed back to the code calling this function. But the other is that it ends the function and returns the value immediately. The code on line 4 which sets the skin is correct, but it never runs because the function exits on line 3.

If you swap the order of those two lines it should start working, but let us know if it doesn't... 
That Worked! 
Awesome - thanks for the help! It all worked fine.

Okay next topic. When players respawn a centerprint message pops up letting them know what skin they have active. I'd like to try and switch this message to an sprint (so it prints in the upper left corner instead of the center).

Here's the code:

// GeN >

player_stand1 ();

if (deathmatch)
spawn_tfog (self.origin + v_forward*20);

spawn_tdeath (self.origin, self);

if((teamplay || (deathmatch & D_HH)) && (self.genteam))
SetTeam(self, self.genteam);

// *************************************************************************
// ** **
// ** M U L T I S K I N 1.1 (start) **
// ** **
// *************************************************************************

if ( == 0) centerprint(self, "Respawning as... Quakeguy"); else
if ( == 1) centerprint(self, "Respawning as... Doomguy"); else
if ( == 2) centerprint(self, "Respawning as... Arnold the Terminator"); else
if ( == 3) centerprint(self, "Respawning as... Arnold the Conan (4)");


// *************************************************************************
// ** **
// ** M U L T I S K I N 1.1 (end) **
// ** **
// *************************************************************************


If I replace "centerprint" with "sprint" it compiles okay, but no messages ever appear.

Any ideas? 
I'd say check that you left the "self" part there - but you'll basically crash the whole server if you get that wrong when using sprint. Can you check to see if the message is getting logged in the console? Sometimes if there's a centerprint and a sprint happening at the same time, the one can wipe out the other. 
Not sure what you mean by "left the self part" in place or not.

A given line could look like this in how I have it:

if ( == 0) sprint(self, "Respawning as... Quakeguy\n"); else

I know most other sprint commands end with "\n" in the line to return?

Could there be something with the timing of respawning triggers that results in a different handling for sprint versus centerprint?

Seems like maybe I;m missing something obvious. 
The message is getting printed to the console if I have the console open when I die. 
You got the self part right, I was worried you might have done something like

if ( == 0) sprint("Respawning as... Quakeguy\n"); else

Is the change to sprint because you are centerprinting something else at the same time? If so, try disabling that for a moment and see if the sprint starts working. 
Dang Engine Issue 
turns out it was a quake engine issue of some sort. I was running and older version of qrack and I tried out a different engine and it worked. Updated Qrack and now it works in that too. :) 
Trigger_changemusic + Saves 
Alright. Thanks to Johnny Lew I have a trigger_changemusic in progs_dump however, I have no idea how to get this to work with savegames. Any guidance?

//thanks to Johnny Lew via changemusic.rar --dumptruck_ds

void() trigger_changemusic_touch =
if (!(other.flags & FL_CLIENT))
if (!self.sounds)
objerror("ERROR: trigger_changemusic needs valid track number in sounds field");
WriteByte(FL_SWIM, self.sounds);
WriteByte(FL_SWIM, self.sounds);
self.touch = SUB_Null;
self.nextthink = (time + 0.1);
self.think = SUB_Remove;

void() trigger_changemusic =
if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
self.touch = trigger_changemusic_touch;
con_logcenterprint 1 is the option to print centerprint messages to console. setting it to 0 obv turns that off.
you mean, you want to remember which music track was playing and restore that when the savegame loads?

Check out rubicon 2 source code, the function LoadSaveGameCallback, the logic to call in StartFrame, and the special variable loadsavegamecallback_done -- this setup allows you to do any necessary work after loading a save game, such as re-triggering client side looping sound effects.

In theory you can save the desired music track in some variable, and then when the game is reloaded, check that variable and re-trigger the music in your own version of LoadSaveGameCallback. 
yep. I was looking through other mods yesterday. I should've known to start with Rubicon 2! thanks. 
More Trigger_changemusic 
I'm posting this for those who come after. It should plug into mods easily. As I was looking over Rubicon 2 code and overheating my pea-brain, Spike posted this on Discord. It works well so far but I need to test in various source ports. This isn't as flexible as what metl posted above but it works for this implementation. NOTE the & and * are correct below

add this to worldspawn in world.qc
world_sounds = &world.sounds; //Spike not read-only yet...

add this to defs.qc
nosave float *world_sounds; //via Spike fun times! nosave=noclobber

add to bottom of triggers.qc
void(float newtrack) changemusic =
*world_sounds = newtrack; //changing the field via a pointer
//world.sounds has now been changed via our pointer, newly connecting players (like those connecting after the game is loaded) will get sent the new cd track's number.

//let everyone currently on the server know.
WriteByte(MSG_ALL, newtrack); //initial track
WriteByte(MSG_ALL, newtrack); //looped track... should generally be set the same as the initial track as most engines ignore it entirely so it might as well be sane for those that care.

//thanks to jleww via changemusic.rar --dumptruck_ds

void() trigger_changemusic_touch =
if (!(other.flags & FL_CLIENT))
self.touch = SUB_Null;
self.nextthink = (time + 0.1);
self.think = SUB_Remove;

void() trigger_changemusic =
if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
if (!self.sounds)
objerror("ERROR: trigger_changemusic needs valid track number in sounds field");
self.touch = trigger_changemusic_touch;
oops I just noticed

if (SUB_Inhibit ()) // new spawnflags for all entities -- iw

that is in progs_dump only - you won't need it elsewhere and it will cause an error on compile 
How Does Size Work? 
Hi everybody,

I'd like to put in some extra-large monsters to make usual lesser threats a far more scary danger.
From what I can see, seems the size is dealt with code looking like that:

setsize (self, '-32 -32 -24', '32 32 40');

where the 2nd and 3rd parameters correspond to VEC_HULL_MIN and VEC_HULL_MAX respectively.

Yet I can't figure out what the term "hull" actually refers to, nor how a size could possibly be "negative" (unless maybe it's lovecraftian non euclidean geometry brought in QuakeC by Shub-Niggurath herself???)

Your help to my comprehension would be extremely appreciated. Thank you a lot in advance ! :-) 
Tale Of Two Halves 
OK, so this is a bit complicated. For almost all purposes, you have exact control over the bounding box of an entity - but the one exception is really, really important!

The normal bounding box is a cuboid which doesn't ever rotate as the entity moves. The two vectors are relative offsets - they say how far the corners of the bounding box should be from the origin of the entity. The negative ones put the lower corner to the left, back and below the origin of the entity, the positive ones specify a position to the right/front/above the origin.

Interesting to note that those parameters mean the origin isn't dead centre of the cuboid, the bottom of the bounding box is 24 units below the origin, but the top is 40 units above it.

One place where the exact bounding box is used is when colliding with...another bounding box. The exact size of the bounding box is also tested to check if traces from e.g. shotguns have hit something.

However, the one place where the bounding box is (sorta) ignored is calculating collisions against BSP objects. To run faster on Pentium 90s, Quake only computes the spaces that three sizes of object can fit around BSP objects:
• point-sized
• man-sized
• shambler-sized
The precomputed spaces are called "hulls". If the bounding box isn't one of those three sizes, the Quake engine picks a "best-fit" from the available hulls. If you want to get consistent collision, you have to pick one of those three sizes, and the constants are there to make that easier. 
My Triviant 
r_drawviewmodel 1 makes a lot clear.

I try to make a monster launch an attack with three projectiles. One straight forward and two sideways parallel to the player. I studied Wiz_StartFast but I can't make the sideways parallel in line. The outside projectile always aims to the player, not aside.

Where should I start? 
Thank You Preach! 
Your explanation is crystal clear and I would not have guessed that alone, thank you so much!

Now just need to find where the reference hulls for Hexen II are defined (I'm mapping for H2) and I'm done. :-) 
Have you tried looking at the Hell Knight code? I think he does what you're asking for - just spread out over multiple frames instead of all at the same time... 
Yes Preach, that makes sense.
It don't has to be a simillar shot, although it would look fine. 
First | Previous | Next | Last
Post A Reply:
Website copyright © 2002-2021 John Fitzgibbons. All posts are copyright their respective authors.