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
Who Is Pushing 
I think you misunderstand MOVETYPE_PUSH. It's not to make a thing be pushable, it's designed for things like doors and platforms that do the pushing. Don't make corpses MOVETYPE_PUSH, or anything else that isn't a BSP object for that matter.

Yes, the teleport train is MOVETYPE_PUSH without being a BSP object, but that's why it sometimes crashes! It was a bad idea, probably done in a hurry to get Quake out of the door.

You can read some more on the issue here, but bear in mind that the fix discussed on the page is an engine-level fix. If you're writing a mod that doesn't prescribe which engine to use, you can't benefit from this.
https://www.quake-info-pool.net/q1/qfix.htm#movetype_push 
Proximity Mine Help (based Off SoA Prox Launcher Code) 
Basically it's overall working but
the key issues are
it never seems to stick on world (it otherwise behaves properly more or less), and thus the arming and stick sounds never play. Also even if it doesn't stick the arming sound never plays

besides that it properly triggers on enemies, bounces off doors & enemies etc, and works more or less...

I've been working on this for 9+h and can't figure it out!

void() ProximityBomb =
{
local entity head;
local float blowup;

if (vlen(self.spawnmaster.velocity)>0)
{
ProximityGrenadeExplode();
self.think();
return;
}
if (time > self.delay)
{
mine_disarm();
self.think();
return;
}


self.touch = SUB_Null; //new
self.owner = world;
self.takedamage = DAMAGE_YES;
head = findradius(self.origin, PROX_MINE_RADIUS); //sensor radius
blowup = 0;

while (head) //what to look for
{

// Don't detonate on players or other mines
if ((head != self) && (head.health > 0) && (head.flags & (FL_CLIENT|FL_MONSTER)) && (head.classname != self.classname) && (head != self.lastvictim)) //(head.classname != "player"))
{
blowup = 1;
}


traceline(self.origin,head.origin,TRUE,self);
if (trace_fraction != 1.0)
blowup = 0;


if (blowup==1)
{

ProximityGrenadeExplode();
self.nextthink = time + 0.5;
return;
}
head = head.chain;
}
self.nextthink = time + 0.25;
}; 
 
void() ProximityArmed = //new
{
sound(self, CHAN_WEAPON, "weapons/proxarmed.wav", 1, ATTN_NORM);
self.think = ProximityBomb;
self.nextthink = time + 0.25;
};



void() ProximityGrenadeTouch =
{
if (other == self || other == self.owner) //|| other == self.owner
{
sound (self, CHAN_WEAPON, "weapons/proxbounce.wav", 1, ATTN_NORM); // bounce sound
return;
}

if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
// Don't collide with other mines
if (other.classname == self.classname)
{
sound (self, CHAN_WEAPON, "weapons/proxbounce.wav", 1, ATTN_NORM); // bounce sound
self.movetype = MOVETYPE_BOUNCE; // Add this line
return;
}


// Check if it's a brush entity (like doors)
if (other.movetype == MOVETYPE_PUSH) //|| other.solid == SOLID_BSP
{
sound(self, CHAN_WEAPON, "weapons/proxbounce.wav", 1, ATTN_NORM); // bounce sound
self.movetype = MOVETYPE_BOUNCE; // Add this line
return;
}

if (other.flags & FL_CLIENT) //user disarm mine
{
//self.solid = SOLID_NOT;
mine_disarm();
//remove(self);
return;
}

if ((other.takedamage == DAMAGE_AIM || other.solid == SOLID_TRIGGER || other.flags & FL_MONSTER )) //don't det on monsters || other.flags & FL_CLIENT
{
sound(self, CHAN_WEAPON, "weapons/proxbounce.wav", 1, ATTN_NORM);
//self.movetype = MOVETYPE_BOUNCE;
T_Damage(other, self, self.owner, 1);
//self.think();
return;
}


self.movetype = MOVETYPE_TOSS;
if (self.state == 1)
return;

if (vlen(other.velocity) > 0)
{
ProximityGrenadeExplode();
self.think();
return;
}

else
{

sound (self, CHAN_WEAPON, "weapons/proxstick.wav", 1, ATTN_NORM); // bounce sound
self.movetype = MOVETYPE_NONE;
setsize (self, '-5 -5 -5', '5 5 5');
self.state = 1;
self.spawnmaster = other;

self.velocity = '0 0 0';

// Start arming sequence
self.think = ProximityArmed;
self.nextthink = time + 2;

self.touch = SUB_Null; //new
self.solid = SOLID_NOT; //new
}
}; 
 
void() ThrowProxMine =
{
float x;

// Check if enough time has passed since last throw
if (self.last_mine_time > time - 1.5)
return;

// Check if player has enough ammo
if (self.ammo_rockets2 < 1)



local entity missile; //, mpuff;

self.currentammo = self.ammo_rockets2 = self.ammo_rockets2 - 1;
self.last_mine_time = time; // Update last throw time

sound (self, CHAN_BODY, "zombie/z_shot1.wav", 0.8, ATTN_STATIC);

self.punchangle_x = -2;

missile = spawn ();
missile.owner = self;
missile.lastvictim = self;
missile.movetype = MOVETYPE_TOSS;// MOVETYPE_BOUNCE;
missile.solid = SOLID_BBOX;
missile.classname = "proximity_mine";
missile.takedamage = DAMAGE_YES; //DAMAGE_NO;
missile.health = 2;
missile.state = 0; //not armed

// set missile speed
makevectors (self.v_angle);


if (self.v_angle_x)
missile.velocity = v_forward*400 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
else
{
missile.velocity = aim(self, 10000);
missile.velocity = missile.velocity * 400;
missile.velocity_z = 200;
}
missile.avelocity = '100 400 100';


missile.angles = vectoangles(missile.velocity);

missile.touch = ProximityGrenadeTouch;
// set missile duration
missile.nextthink = time + 2; //min time until mine can explode from enemy
missile.think = ProximityBomb; //arm
missile.th_die = ProximityGrenadeExplode;
missile.delay = time + 90; // time until mine auto disarms

setmodel (missile, "progs/proxmine.mdl");
setorigin (missile, (self.origin) + (v_forward * 0) + (v_right * -17) + '0 0 10');

setsize (missile, '-4 -4 -4', '4 4 4');

}; 
Debugging 
The difficult part with your ProximityGrenadeTouch function is there are so many return statements which MIGHT end the function, and the bit of code that makes it stick to the wall is at the very end.

I would recommend you add some dprint statements to the function after each "checkpoint" - each place where the function has avoided a branch that contains a return. Then you can check how far execution gets through the function when you throw one against a wall, and deduce which exit is being taken unexpectedly. Two tips
a) pull down the console as soon as the bomb hits a wall for the first time, as you'll get a huge pile of debug messages if you let it bounce all over the shop first
b) remove the debug statements once you have solved the mystery, or they will be a pain in future 
I See, Thanks! 
Another issue is... is it possible to dynamically spawn monsters real time via impulse? (like half life's impulse 76)

I tried adding the monster's model precache to void () worldspawn, void () StartFrame , but i keep getting "host error pf precache can only be done in spawn functions?" 
StartFrame Timing 
StartFrame runs every frame! If you put a precache in there, you will hit the error for a late precache just about as fast as it's possible to hit it. Stick to worldspawn and you'll have a better time.

But as long as you time the precaches correctly (always on frame 0, and never afterwards), you can spawn monsters dynamically, in essentially the same way as creating a rocket or grenade. One small catch is that you can't update the total_monsters count after the first frame - so your monster kills can go over 100% unless you ensure that dynamically spawned monsters don't count for the kill count.

Another tricky wrinkle to deal with is where to place the monster so that it isn't stuck. Usually that's the responsibility of the mapper! One thing's for sure, you'll have to come up a compromise, and here's the proof: imagine that we make a map that's just a box 8 units larger than the player. It's physically impossible to successfully spawn a monster into that map. 
Fixed Precaches 
One other thing to warn you - don't ever randomise your precaches! Imagine you had some plan to randomly select one monster which your impulse spawns for the duration of the map, and you make the selection in frame 0 then precache just the assets for the selected monster. This exposes you to an interesting bug!

The bug arises when you save and load the game. In particular when you load the game, the engine:
1) Runs the first few frames of the map as if you had started from scratch
2) Reads the entity states from the save file and shuffles everything around to match it
The point of 1) is mainly to precache everything again. But second time round you might roll a different number on the random monster table and precache different models. Things may start showing up with the wrong models, or if you are less lucky the whole thing just crashes.

The only way to avoid this problem is to make the precache sequence entirely deterministic. If you're married to the random spawnable monster idea, you might have to precache the models for all the options, even if only one is ever used at a time.

And there are other more subtle ways to hit this error. Imagine you have an entity which you only allow a 50% chance of manifesting, randomised on each map load. Even if you have so many of this entity that one spawns every time, random variation might change the order in which models are first precached, as the first manifestation may occur before or after other fixed entities. Changing the order of precache messes up which models appear after a save is reloaded. 
I'm Confused... 
can you give example code?

I keep getting the "host error pf precache can only be done in spawn functions?"

regardless of where I put the monster's precache ? 
On A Side Note - For Dynamically Spawned Monster Placement We Can Try 
spawny.origin_x = (0.5 - random())* 2 * 5000; //It's origin is randomized
spawny.origin_y = (0.5 - random())* 2 * 5000;
spawny.origin_z = (0.5 - random())* 2 * 5000;

while((pointcontents(spawny.origin) != CONTENT_EMPTY) && (spawny.aflag < 75))
{
//If the pointcontents of the monster origin is not empty, reset it To a more suitable space. If no space can be found within 75 loops,
//Leave it where it last was placed.
spawny.origin_x = (0.5 - random())* 2 * 5000;
spawny.origin_y = (0.5 - random())* 2 * 5000;
spawny.origin_z = (0.5 - random())* 2 * 5000;

spawny.aflag = spawny.aflag + 1;
Jazz Is About All The Notes He's NOT Playing 
The important part is not where you put the precaches, but REMOVING them from everywhere except worldspawn. If you are really struggling, remove all the precaches of the model until you start getting a different error about a resource NOT being precached. Then add one precache to worldspawn and you should be set. 
WOW Thanks! It's Almost Fixed! 
I didn't realize it was so simple! weird... i swore i did that before and it didn't work...

Ok so I can spawn the monster now and i can see the monster in front of me for a few sec, but then game crashes with "host error pr execute program null function" 
Also 
what controls how high or low a monster can step up/down?

seems they have trouble with stairs & small ledges? 
Units 
Best measure is 16 units,might be 15.
In a turnine stair it is better to keep the steplength more than 16, aproxemate 24. 
Step Height 
Look up #define STEPSIZE here

https://github.com/id-Software/Quake/blob/master/WinQuake/sv_move.c

The height for climbing a step is applied equally for both players and monsters. But one of the differences is how smoothly the movement is applied. A player moving at 360 units per second on a modern computer would have that movement split up into 72 segments of length 5. Each movement can climb one step, so the player can comfortably manage many steps close together.

In contrast, a monster moving forwards at 360 units per second would move in just 10 segments of 36 units each. And the movement is all or nothing - if the monster would need to climb TWO steps to reach the end point, it will collide with the second step and the entire movement is aborted.

So putting more horizontal spaces between the steps will help a lot. Monsters will also never go off a ledge with drop a of more than 1 step using walkmove or movetogoal - you have to give them velocity movement if you want them to really fall. Be careful, it's easy to turn see that feature turn into an exploit as your monsters can now be lured into pit traps and completely bypassed. 
Smoothing 
Another alternative is to split up the navigation into small segments within a frame, for example replacing movetogoal(20) with movetogoal(10); movetogoal(10); It's not always a 1 to 1 equivalence, like with lots of Quake AI it's a thing to experiment with and tune. 
Host Error Pr Execute Program Null Function 
This error means that you've forgotten to set something, but the error message doesn't tell you which something it is. Some possibilities are

th_stand - the AI for an idle monster
th_run - the AI for a newly alerted monster
th_pain - the AI for a pain animation
th_die - the AI for a death animation
think - the next function to run after a timer.

To try and diagnose, add this line to the START of your monster spawn function

th_stand = SUB_Null;

If that fixes the error, you know that you've forgotten th_stand - and NOW you need to fix that by giving the monster the AI, this is a diagnostic tool only. If that doesn't help, add another line

th_run = SUB_Null;

Repeat until adding a line avoids the crash, then develop a fix. 
Step Height 
soo... you're saying it cannot be changed via mod? it's engine based? 
No Change 
Yeah, #define means it's hard-coded when the engine is compiled. 
 
ok i resolved the null bug - was missing the think/nextthink... i was using custom entity so walk monster start wasn't working 
Monster AI (II) 
It's sorta working (thanks for the findNextMonster Preach!) (monsters sometimes attack other faction monsters) but very unreliable - vs the player whom they always attack instantly on sight?

the 2 main issues I'm still trying to solve is:

1 - monsters find a new enemy after killing the current hostile faction monster; (currently they just sit there, even if new enemy monster enters their LOS)

2 - monsters commonly do not fight enemy faction monsters on sight, only sometimes?

so how can i solve these 2? do you need to see my "FindTarget" again? or? 
Hint 
Ask yourself this question: why do monsters stop attacking a target when it dies? Unless there's some code that checks whether the target dies, they ought to just continue attacking a dead target in the same way they attack a living one. Your first mission is to find that location.

After that, you need to add some code into that path to make sure that your monsters find an enemy. If you think you already have code there that does so, add some dprint statements to it, to check whether your code is not running, or if it's running but not detecting a viable monster target. Come back with that more precise intel on your problem. 
I Figured It Out! 
it's to do with FindTarget in AI.qc and strangely ai_stand(); in the monster animations

FUCK this - man took 5h to fix thru line by line trial & error

makes me wanna stop coding/modding quake forever LOL............ 
 
I am defo NOT a programmer LOL

dunno how you guys can do this professionally as careers

maybe cause i don't got any former training/edu in programming, but i cannot do this "back & forth" debugging for 40h a week, will 100% die lol 
Need Help With Flickering Lighting Effects On The QSS Engine 
Hello everyone!

I have a wonderful modification of "TribalFX" for «QuakeSpasm Spiked» engine. In this modification the author used additional light sources for monsters attack, grenades, rockets, objects, flashlight, etc. Tribal replaced all these effects with standard commands, for example, "EF_MUZZLEFLASH" with the commands "particleeffectnum" and added their description to the file "effectinfo.txt ". But when you turn on the game with a frame rate of more than 72 FPS, there is an unbearable flickering of these additional lighting effects. It's like a strobe light effect.
In early January 2025, @Tribalquake provided me with the source files and I saw that the whole point of the problem was in the file "effectinfo.txt ". I'm not a programmer and at first glance everything looks right. Where can this flicker bug hide depending on the frame rate? All his works are similar to the modification of "AD", but made from scratch.
All files are there, including "effectinfo.txt " and the source files"*.qc". I informed the author about this problem three years ago, but Tribal abandoned it for family reasons.
Can someone help fix this bug? I just don't understand what text command needs to be added to the file "effectinfo.txt " to synchronize with the frame rate of the game.

Here is a link to a video demonstrating this flickering effect (ver.01Ufix). Comparison at frame rates of 72 fps and 144 fps:
https://drive.google.com/file/d/1V8BQy3yWHYezQ98ie8UzX10iqKowQqTo/view?usp=sharing

Here is a link to versions 01T and 01U. They are very different from each other. Wonderful new effects have been added in version 01U, but the flickering of the light spoils everything:
https://drive.google.com/file/d/18wRTcNkRXpQVvrk8-s5WO4GXOiKEIRV5/view?usp=sharing
https://drive.google.com/file/d/1r2MDg_YzPSvBctJvLVP1_243NdJxQH0h/view?usp=sharing

My email: ashalunov1980@gmail.com 
First | Previous | Next | Last
You must be logged in to post in this thread.
Website copyright © 2002-2025 John Fitzgibbons. All posts are copyright their respective authors.