CSQC Standards: Lets bridge the Great Divide

Discuss anything not covered by any of the other categories.
Post Reply
avirox
Posts: 137
Joined: Wed Aug 16, 2006 3:25 pm

CSQC Standards: Lets bridge the Great Divide

Post by avirox »

Hi everyone,

As a quake modder, I was thrilled as to learn a few years back that popular quake engines would finally get a client-side counterpart to the server-based game VM (progs.dat). Client-Side QuakeC (CSQC) has become the sine qua non of modern quake total conversions such as Nexuiz and Steel Storm. However, its implementation remains divided between the two major engines supporting it - FTE and Darkplaces (DP). The incompatibility of CSQC csprogs.dat between these two engines has caused confusion in the community as to the proper way to implement it, leading to many people giving up on the idea of client-side mods altogether.

At the behest of LordHavoc, I am creating a thread here to discuss and iron out the differences - and hopefully create some semblance of a standard - for CSQC implementation in FTE, DP, and any future project supporting such.

It is the aim of this thread to point out differences in the implementation of CSQC which lead to conflict across engines. This thread is not here to point fingers at anybody or to play the blame game. I believe, with some discussion and cooperation, we can revive CSQC and regain the community's interest in the medium.

Although this might fall under the purview of Urre's Quake Standards Base project, I feel that CSQC deserves a consideration of its own. Listed below are some of the differences that I have noted in my CSQC modding. I urge the rest of the community to post any other differences which you may have encountered. Please also let me know if there are any changes that have now fixed or resolved the incompatibilities/inconsistencies listed below:
(this post will be updated periodically..)


trailparticles (ext 336) arguments inconsistent
in FTE:
wrapper used:
//DP got the arguments the wrong way around...
void(entity ent, float effectnum, vector start, vector end) trailparticles_dp = #336; // (EXT_CSQC),
void(float effectnum, entity ent, vector start, vector end) trailparticles =
{
trailparticles_dp(ent, effectnum, start, end);
};

project (ext 311) and unproject (ext 310) are incompatible
in FTE:
(un)project(vector v): v_z is inferred from farclip (1.0)
in DP:
(un)project(vector v): v_z distance must be specified

CSQC_InputEvent does not pick up mouse movements
in FTE:
Mouse movement is handled in CSQC_InputEvent through

Code: Select all

if (eventtype == 2) {}
in DP:
If I want CSQC_InputEvent to handle mouse inputs, it must be called with a wrapper after renderscene(), IE:

Code: Select all

		mousemoves = getmousepos();
		if (mousemoves)
			CSQC_InputEvent( 2, mousemoves_x, mousemoves_y );
Getting player origin
in FTE:
Must utilize deltalisten() to ascertain player's position
in DP:
pmove_org is set to player origin

drawstring (extension 321)
in FTE:
void(vector position, string text, vector scale, vector rgb, float alpha, ...) drawrawstring = #321;
in DP:
void(vector pos, string text, vector sizee, vector rgb, float alphaa, float flags) drawstring_dp = #321;

drawpic (extension 322)
in FTE:
void(vector position, string pic, vector size, vector rgb, float alpha, ...) drawpic = #322;
in DP:
void(vector pos, string picname, vector sizee, vector rgb, float alphaa, float flags) drawpic_dp = #322;

CSQC over QW protocol
This is a bit of a nit-pick, but as there has been an increase in DP users among the QuakeWorld (QW) community, this has become somewhat more pertinent.
in FTE:
CSQC progs loaded on both NQ (regular quake) and QW (QuakeWorld) servers
in DP:
CSQC progs only works on NQ servers
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

Raw polygons:
void(string shadername) BeginPolygon = #306; (FTE)
void(string texturename, float flags [, float draw2d]) BeginPolygon = #306; (DP)
DP doesn't support shaders in polygons. FTE requires them if you want to disable mipmapping or enable blending. 2d stuff is an extra extension supported only by DP that I only just discovered. Other stuff is the same.
Side note: This also applies for drawpic and the extra argument that DP mandates, although FTE does attempt to honour that flags argument.

Querying scene/view settings:
vector/float(float property) getview = #309; (FTE)
vector/float(float property) getview = #303; (DP)
(original spec had no query as an aid to cheat prevention - no aimbots if you don't know where the player is).

Stats:
Using ev_integer for floats is suboptimal in FTE, but the only way in DP.
Using strings, DP is limited to 15 chars. FTE permits much longer strings. Also, FTE string stats use a different namespace.
DP uses stats 2??-255 for various movement cvars on the server (eg: sv_maxspeed). FTE provides such cvars only through the serverkey builtin.
Meant to be otherwise compatible.

Temp ents:
Just.... just don't go there. Use stats, serverinfo, ents, or stuffcmds. Using tempents is an almost guarenteed way to break both saved games and protocol agnosticism. FTE servers will generate lots of warnings if you try, due to the whole protocol thing.
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

While we're at it, could we have better failure behaviour? FTE appears to be pretty promiscuous with it's csprogs, and will accept almost anything. You could probably feed it a two-week-old bit of toast and it would find a way of working with it. DP - not so. OK, I get the reason why DP might be more strict, but last time I checked it threw a Great Big Dirty Sys_Error. How about just not using the csprogs instead? With maybe a console message for developers?
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
TimeServ
Posts: 38
Joined: Wed Jun 08, 2005 4:02 pm

Post by TimeServ »

float(string effectname) particleeffectnum = #335;
Returns 0 in FTE for a non-existent effect, but -1 in DarkPlaces.
mh wrote:FTE appears to be pretty promiscuous with it's csprogs, and will accept almost anything.
I looked at the DarkPlaces repo and I think the latest revisions are more forgiving of system defs. I think if we're making any big changes we should probably consider making empty system fields/globals be the default.
goldenboy
Posts: 924
Joined: Fri Sep 05, 2008 11:04 pm
Location: Kiel
Contact:

Post by goldenboy »

mh wrote:While we're at it, could we have better failure behaviour? FTE appears to be pretty promiscuous with it's csprogs, and will accept almost anything. You could probably feed it a two-week-old bit of toast and it would find a way of working with it. DP - not so. OK, I get the reason why DP might be more strict, but last time I checked it threw a Great Big Dirty Sys_Error. How about just not using the csprogs instead? With maybe a console message for developers?
I asked LH for the same thing, and it didn't happen.
LordHavoc
Posts: 322
Joined: Fri Nov 05, 2004 3:12 am
Location: western Oregon, USA
Contact:

Post by LordHavoc »

implemented CSQC_InputEvent(2,x,y) and a cvar to enable it (which defaults to 1), this broke GAME_STEELSTORM, GAME_XONOTIC and possibly GAME_NEXUIZ, but the xonotic team have promptly fixed their code, the cvar defaults to 0 in GAME_STEELSTORM to avoid bugs for now.

Added CSQC_InputEvent(3,x,y) for moves with setcursormode(TRUE) where only absolute mouse position is known, not relative movement.

For now I recommend continuing to use getcursorpos() instead as the posted stable version of darkplaces does not have this fix obviously.
LordHavoc
Posts: 322
Joined: Fri Nov 05, 2004 3:12 am
Location: western Oregon, USA
Contact:

Post by LordHavoc »

added getproperty builtin #309 (same code as R_SetView).

Not sure why setproperty/getproperty are called that, the DP one was always called R_SetView...
LordHavoc
Posts: 322
Joined: Fri Nov 05, 2004 3:12 am
Location: western Oregon, USA
Contact:

Post by LordHavoc »

Now allowing drawpic and drawstring without flag parameter.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

Auto interpolation:
Neither engine interpolates anything automatically once inside csqc.

addentities:

Code: Select all

DP:
foreachent(self)
{
  if (self.nextthink && self.nextthink < time)
  {
    self.nextthink = 0;
    think();
  }
  if (self.predraw)
    self.predraw();
  if (self.drawmask & arg_drawmask)
    addentity(self);
}
FTE:
foreachent(self)
{
  if (self.drawmask & arg_drawmask)
  {
    if (self.predraw)
      self.predraw();
    addentity(self);
  }
}
DP calls predraw even if the drawmask doesn't match. FTE calls predraw only on a match (not much point telling it that its going to be drawn if it isn't going to be drawn/added).
DP calls think functions, and in a way incompatible with movetype_push. FTE never calls think functions as its still waiting for an extension which enables all movetypes properly within csqc.

Time:
Ah yes, time, that fundamental constant... Well, its less constant than perhaps it could be.
In FTE, local time is provided in a 'cltime' global (number of seconds the client has been running the map). In DP it must be accessed via the 'gettime' builtin.
(edit: what I previously wrote here was wrong)

offtopic:
setproperty/setview was originally dubbed setviewflag (FTE dropped the 'flag' as it wasn't just flags but also values). setview is a redundant name considering it now sets client properties rather than just view properties (like [515]'s added angles). Call it what you want (which is why builtin numbers are useful!).
Last edited by Spike on Wed Aug 17, 2011 4:03 pm, edited 1 time in total.
LordHavoc
Posts: 322
Joined: Fri Nov 05, 2004 3:12 am
Location: western Oregon, USA
Contact:

Post by LordHavoc »

DarkPlaces csqc does not interpolate anything, frame blends must be explicitly animated (as per EXT_CSQC spec), similarly movement...
Post Reply