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
Stubborn Fox 
Thanks for that bit of code, Sock.
Comes in handy for the RocketJumper I made.

I'm still experimenting with the amphibian.
I made a new model for it, but the code still won't work well.

http://members.home.nl/gimli/dwell.gif

I know it's rather a high catch to invite a monster in Quake
that runs also on land as swimming in water.

For so far I managed it to stand on land and run for the player,
follow it in water turning into a swim pose.
The pitty edge is to get it back into its walk state.
Now it jumps back on land in its swim pose, only turns back into the walk frames after it has bin shot.

The reason for this is that I made an addition in the Fight.Qc

float() HarpCheckAttack =
{
local vector spot1, spot2;
local entity targ;
local float chance;

//check we are in the water and also standing
if (self.waterlevel > 0 && self.th_stand == h_stand1)
{
dprint("standing on ground \n");
h_jive1();
harpi_to_harpo();
return TRUE;
}

//check we are in the water and also swimming
if (self.waterlevel < 2 && self.th_stand == h_dwell1)
{
dprint("shallow enough to stand\n");
h_mour1();
harpo_to_harpi();
return TRUE;
}


The first statement gives it a stand attitude on land :
if (self.waterlevel > 0
If I use another number, 2feet 3 chest 4 eyes, the monster won't go back up the land.

The impulse to do so comes in with
harpi_to_harpo();

The second statement gives it a swim pose in water :
if (self.waterlevel < 2

This impulse comes with
harpo_to_harpi();

harpi is in water
harpo is on land

So far it is clear to me.

I try to figure out what's going on when the monster comes out of the water and don't start the stand position. 
 
it's difficult to see what to change without seeing more (or all) of the code.

you could try also adding the same checks you have into the first frame of the running sequence.

so what I would do is this:

make the state check it's own function
void() HarpCheckState =
{
//check we are in the water and also standing
if (self.waterlevel > 0 && self.th_stand == h_stand1)
{
dprint("standing on ground \n");
h_jive1();
harpi_to_harpo();
return;
}

//check we are in the water and also swimming
if (self.waterlevel < 2 && self.th_stand == h_dwell1)
{
dprint("shallow enough to stand\n");
h_mour1();
harpo_to_harpi();
return;
}


then add a call to it in the first run frame:
void() harp_run1 =[ $run1, harp_run2 ] {ai_run();HarpCheckState()};

the first run frame is called whenever monsters switch targets or wake up, so it should be more reliable than waiting for it to try to attack. 
 
Right, in addition the corredsponding file only files that matter

There are two modelposes in one file.
The land state and the swim state.
Both are switched in the djive go-in-water and mour come-on-land poses.

harpio.qc


frames$

void() h_jive1 =[ $djive1, h_jive2 ] {harpi_to_harpo();};
...
void() h_jive10 =[ $djive10, h_swim1 ] {};

void() h_mour1 =[ $mour1, h_mour2 ] {harpo_to_harpi();};
...
void() h_mour10 =[ $mour10, h_run1 ] {};


void() harpo_to_harpi =
{
self.th_stand = h_stand1;
self.th_walk = h_walk1;
self.th_run = h_run1;
self.th_die = harpio_die;
self.th_pain = harpio_pain;
self.th_missile = h_attack1;
self.th_melee = harpi_melee;
self.flags = self.flags - (self.flags & FL_SWIM);
};

void() monster_harpio =
{
if (deathmatch)
{
remove(self);
return;
}
precache_model2 ("progs/harpio.mdl");
precache_model2 ("progs/slmbal.mdl");
precache_model2 ("progs/h_model.mdl");
precache_sound2 ("player/death2.wav");
precache_sound2 ("fish/bite.wav");
precache_sound2 ("fish/death.wav");
precache_sound2 ("harpi/sight.wav");
precache_sound2 ("enforcer/enfstop.wav");
precache_sound2 ("enforcer/enfire.wav");
precache_sound2 ("knight/khurt.wav");
precache_sound2 ("harpi/idle.wav");

self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_STEP;

setmodel (self, "progs/harpio.mdl");

setsize (self, '-16 -16 -24', '16 16 24');
self.health = 200;
harpo_to_harpi ();
walkmonster_start ();
};

void() harpi_to_harpo =
{
self.th_stand = h_dwell1;
self.th_walk = h_swim1;
self.th_run = h_crawl1;
self.th_die = h_die1;
self.th_pain = newharpio_pain;
self.th_melee = harpo_melee;
self.th_missile = h_harp1;
self.flags = self.flags | FL_SWIM;
};



The reason it won't go back to its land state might be the start scene with harpo_to_harpi statement.

So as soon it reaches

void() h_mour10 =[ $mour10, h_run1 ] {};

its original state reminds to harpo_to_harpi
before the walk_monster_start in void()monster_harpio.(?)

I'll try the HarpCheckState(), but doesn't it need more addition to the Harp_Check_Attack? 
Madfox 
Add a line to each of the of the h_mour functions where you send out a debug message like so
void() h_mour1 =[ $mour1, h_mour2 ] {harpo_to_harpi();
bprint("I am in h_mour1! \n");
};

Then see how far through the animation sequence it gets. This should help you work out where the problem is. 
 
I don't get any messages in game although I have the bprint in calculated.
protocol 666? 
Falling Through 
It looks as if the standing on ground and shallow enough to stand cross over each other.

http://members.home.nl/gimli/frmcount.jpg 
 
if you are using Bprint then the messages should always appear. If you are using Dprint, then you need to have 'developer 1' set.

Regarding the monster itself, the one major problem you are having has to do with how swimming is handled in quake.

Walking monsters are able to move into water but swimming monsters are never allowed to move out of water, so no matter where you check, it is impossible for the check to succeed and switch back to land movement.

There are ways to get around that of course, but they are all (at least what I am thinking about in my head) somewhat complex.

The first idea I'm thinking about is changing the land->water check from self.waterlevel > 0 to something like self.waterlevel > 1
This would make it switch when it's much deeper in the water.
Next for the water->land check, I would check the distance to the ground from the monster's 4 bottom corners of the boundingbox to see if there is ground close to it's feet.
Then I would check waterlevel <= 1 and if it checks out, transition water->land.
There might need to be a cooldown timer to prevent it from switching back and forth too quickly too.

The second option would be to use FLY instead of SWIM and then manually stop the monster to rising out of the water.
The best way to do that would be to make a wrapper on the monster's movetogoal calls so that it moves to a helper entity which is set to the player's horizontal position, but who's vertical position is set in such a way to keep the monster under the water.
Using fly would give you more freedom to getting the monster to move OUT of the water, and then you original checks might work out.

Both those options would need a fair bit of code rewriting, unfortunately. :( 
Bprint 
I've started using bprint instead of dprint for debugging messages relating to coding, so that there's no way I can forget to remove them!

One way to make the monster can leave the water might be to use the ideas in this tutorial, a hybrid between movetogoal (which won't leave the water) and velocity (which will)
http://www.quaddicted.com/webarchive/minion.planetquake.gamespy.com/tutorial/speed.htm 
More Stubborn Monster 
Thanks for the advice!

I have to read the tutorial, but parms like move to goal and velocity are lucide to me.
Not that I don't understand them but the referring code doesn't fit with my knowhow.

It is almost a jack-in-the-box to me how to define a working statement.

As soon as I change the parms the monster works alright,it only comes out swimming on land and I just have to shoot it back in its walk pose.
This works and for sofar I should be glad.

That it is not the bugfree method is something I'm trying to overcome. 
Practical Problem 
OK, here's a genuine issue faced when creating the next version of Quoth. A mapper who I will not name has released a Quoth map which uses some entity hacks. In particular they've created a backpack model using the modelindex hack. The new patch precaches fewer models, and so changes which model appears for the modelindex which the hack uses. This breaks the map (from a visual point of view).

Which approach would you choose?

a) Let this entity-hack remain broken to discourage future hacks

b) Insert a piece of code which detects this particular map and fixes the models within it

c) Reorder the remaining precaches so that the backpack occupies the same precache slot in this map

d) Revert the model precache savings, as they are incompatible with existing maps


Remember, there are no right answers. Only wrong ones... 
 
create a lookup table that matches the old precache numbers to the new ones?

haha that would be painful to do. :P 
 
name it quothX.Y and tell people to state the tested quoth version(s) in their readme from now on. consider all existing maps requiring quoth2. 
Not Really Related But A Selfmade Problem: 
releasing quoth2 as quoth was annoying already (from a quaddicted viewpoint). I really do not want to replace it again and pretend comments and ratings are for the new version.

I guess one would need to add an dependency option of 'provides', so eg quoth2 provides/fulfills the dependency 'quoth'.

or how about calling them "quoth_pak1", "quoth_pak2", etc. 
Look-up Sir, Arrgggh! 
That's more or less what option c) is, except you only match this particular model to the index it once had. If you're precaching fewer models, it's obvious that you can't do that for every model, so the solution would not be sustainable if this hack was common.

I thought the backpack would be reasonably easy to fix like this because it's in that big list of guaranteed precaches in world.qc. You'd just look at the list and move the backpack precache down as many precaches as it takes. On looking at it, this might not work; unfortunately the backpack is one of the last things to be precached. The number we'd have to give it would belong to the "variable precaches region" which changes depending on which entities the map includes.

You could try to add a wrapper to the precaching function which counts the number of calls, and then precaches the backpack after the right number of entries. There's two problems: First you need to filter out multiple calls to precache the same file (which is hard given QC's lack of support for arrays). This can be done with some effort though, because we know exactly how many precaches we need to remember - the number between the guaranteed precaches and the desired precache value for the backpack.

Then you need some way of dealing with the possibility that not enough models get precached, and so the backpack is never precached either. In QC you don't have any way of telling how many more entities there are to spawn, and when the last spawn function has run, you no longer have the ability to precache models. So you can't predict ahead of time you're in the state where the backpack won't get precached. Any solution for this case would need to be based on the idea of working round the backpack model missing its precache, which is actively detrimental.

So the only proper way to get this trick to work is to sniff which map is being loaded by some other means, and fix it up then. At this stage b) is probably more attractive. 
Spirit 
There are lots of enhancments in new versions of a mod that benefit existing maps - like the rebalancing of annoying monsters, or the fixing of occasionally occuring bugs. So we need backwards compatibility. 
 
Said mapper may also have included two versions of the hack to make it work on both Quoth 1 and 2, so if a new release were to address compatibility issues, it would probably need to take care of two modelindex shifts (unless Quoth 1 didn't change anything about it). 
Yes 
I noticed that, and wondered if that might have been a hint to whoever it was not to indulge in that kind of behaviour. For the record, using a mapobject_custom is a much easier way to get the model you want (they aren't static entities by default). That would only require the hacky version in quoth 1, and then using a designed entity for other versions will be forward compatible. 
Preach 
Rebalancing monsters IS breaking backwards compatibility!

(Aaaaahh change!) 
True 
There should have been an item_custom entity to begin with.... Which new model does it display anyway?

Btw, since you're working on a new version of Quoth, do you have a list of desirable features mentioned over the years or something like that? Obvious things that Quoth is missing for no good reason. Not going for a public feature request discussion, just interested. 
The List 
To make clear, the current patch is limited in scope, and the specific limit I am sticking to is no new entities. I do have other ideas for what might go into a future version of Quoth, custom items is not on it though...It currently displays a head gib with a very weird skin.

Spirit, backwards compatibility is not the same as identical behaviour, else fixing bugs is prohibited because the new patch doesn't crash to the console. For gameplay, I take backwards compatibility to be: from any map or set of circumstances that a player could complete a map in the previous patch, they still can in the new patch with no more difficulty. As someone pointed out in the Quoth 2 thread, making monsters weaker does not affect that. Obviously there are other measures of backwards compatibility that have to be considered, and visual fidelity is one. 
 
Is the protocol 15 precache limit really that big of a problem in 2012? 
Steam 
I'd hazard a guess that the majority of people with quake installed right now use protocol 15, because they bought it bundled on Steam and don't know anything about custom engines. I'm not imagining that every mapper will create maps that run on all engines. Still, if some mappers might want to, the mod should do all it can to enable that. 
 
That's true, but if they know about custom maps in the first place, then knowing about custom engines is just a few inches away.

Unless it's not possible to run a custom engine with Quake on Steam? 
Barriers 
I think you can, but each extra barrier to running the map is gonna turn away some fraction of your audience. 
Follow-up 
If you did want to design a mod where it was clear to mappers what they were free to touch and what you were reserving for future modification, then you might be able to use some of the tricks in an article I've just posted:
http://tomeofpreach.wordpress.com/2012/12/01/whats-in-a-name/

For people who think that it's all a bit crazy and worry for the future of Quoth, don't. Firstly it's too late to do all of this for Quoth, you'd need to have done it before you release the first version and people start making maps. Secondly, Quoth probably doesn't need it because it's fairly slow moving. The private fields stuff would be more useful when you're releasing new versions each month or something, keeping new features private while you're messing with the design, like an "under construction" gif.

If you still think it's a bit paranoid, hold on, because there's a much more interesting use of these field name tricks coming up. 
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.