This example affects three extensions from Darkplaces, but can be usable with all other. One of it's general benefits - you don't need to check for extension in work-code, only in this file. And you always work with extension function, even if it is really a QC stub (many of missing extensions, like str_replace, findchainflags can be replaced with QC alternative, much slower but working).
This code requires a compiler with function pointers support (a 'var' keyword) - FTEQCC, FrikQCC also has function pointers, but it is not tested yet (maybe someone do?)
Code: Select all
/*
========================================
DP_QC_RANDOMVEC
========================================
*/
vector() ext_randomvec = #91;
vector() qc_randomvec =
{
vector tVec;
tVec_x = random()*2-1;
tVec_y = random()*2-1;
tVec_z = random()*2-1;
return normalize(tVec)*random();
}
var vector() randomvec = qc_randomvec;
void() DP_QC_RANDOMVEC =
{
randomvec = ext_randomvec;
}
/*
========================================
DP_QC_STRING_CASE_FUNCTIONS
========================================
*/
string(string s) ext_strtolower = #480;
string(string s) ext_strtoupper = #481;
string(string s) qc_strtolower = { return s; }
string(string s) qc_strtoupper = { return s; }
var string(string s) strtolower = qc_strtolower;
var string(string s) strtoupper = qc_strtoupper;
void() DP_QC_STRING_CASE_FUNCTIONS =
{
strtolower = ext_strtolower;
strtoupper = ext_strtoupper;
}
/*
========================================
DP_TE_QUADEFFECTS1
========================================
*/
void(vector org) ext_gunshotquad = #412;
void(vector org) ext_spikequad = #413;
void(vector org) ext_superspikequad = #414;
void(vector org) ext_explosionquad = #415;
var void(vector org) te_gunshotquad = te_gunshot;
var void(vector org) te_spikequad = te_spike;
var void(vector org) te_superspikequad = te_superspike;
var void(vector org) te_explosionquad = te_explosion;
void() DP_TE_QUADEFFECTS1 =
{
te_gunshotquad = ext_gunshotquad;
te_spikequad = ext_spikequad;
te_superspikequad = ext_superspikequad;
te_explosionquad = ext_explosionquad;
}
void RegisterExtension(string tExtName, void() tRegister)
{
if (checkextension(tExtName))
tRegister();
}
void() RegisterExtensions =
{
if (!cvar("pr_checkextension"))
error("Engine does not support QSG Extensions\n");
RegisterExtension("DP_QC_RANDOMVEC", DP_QC_RANDOMVEC);
RegisterExtension("DP_QC_STRING_CASE_FUNCTIONS", DP_QC_STRING_CASE_FUNCTIONS);
RegisterExtension("DP_TE_QUADEFFECTS1", DP_TE_QUADEFFECTS1);
}
And this is code for new FIND* extension, tested on FTEQCC
You can find them in Arcade Quake sourcecodes
Code: Select all
/*
========================================
DP_QC_FINDCHAIN
DP_QC_FINDCHAINFLAGS
DP_QC_FINDCHAINFLOAT
DP_QC_FINDFLAGS
DP_QC_FINDFLOAT
========================================
*/
entity(.string fld, string match) ext_findchain = #402;
entity(.float fld, float match) ext_findchainflags = #450;
entity(.entity fld, entity match) ext_findchainentity = #403;
entity(.float fld, float match) ext_findchainfloat = #403;
entity(entity start, .float fld, float match) ext_findflags = #449;
entity(entity start, .entity fld, entity match) ext_findentity = #98;
entity(entity start, .float fld, float match) ext_findfloat = #98;
#define findChainDef(f,m) entity tE;entity tLE;tE=world;tLE=world;for(tE=nextent(tE);tE;tE=nextent(tE)){if(tE.f == m){if (tLE)tLE.chain=tE;tLE=tE;tLE.chain=world;}}return tLE;
#define findChainDefAnd(f,m) entity tE;entity tLE;tE=world;tLE=world;for(tE=nextent(tE);tE;tE=nextent(tE)){if(tE.f & m){if (tLE)tLE.chain=tE;tLE=tE;tLE.chain=world;}}return tLE;
entity(.string tField, string tMatch) qc_findchain = { findChainDef(tField, tMatch) }
entity(.float tField, float tMatch) qc_findchainflags = { findChainDefAnd(tField, tMatch) }
entity(.float tField, float tMatch) qc_findchainfloat = { findChainDef(tField, tMatch) }
entity(.entity tField, entity tMatch) qc_findchainentity = { findChainDef(tField, tMatch) }
#undef findChainDef
#undef findChainDefAnd
entity(entity tE, .float tField, float tMatch) qc_findflags = { for(tE=nextent(tE);tE;tE=nextent(tE)) if (tE.tField & tMatch) return tE; return world; }
entity(entity tE, .float tField, float tMatch) qc_findfloat = { for(tE=nextent(tE);tE;tE=nextent(tE)) if (tE.tField == tMatch) return tE; return world; }
entity(entity tE, .entity tField, entity tMatch) qc_findentity = { for(tE=nextent(tE);tE;tE=nextent(tE)) if (tE.tField == tMatch) return tE; return world; }
var entity(.string fld, string match) findchain = qc_findchain;
var entity(.float fld, float match) findchainflags = qc_findchainflags;
var entity(.entity fld, entity match) findchainentity = qc_findchainentity;
var entity(.float fld, float match) findchainfloat = qc_findchainfloat;
var entity(entity start, .float fld, float match) findflags = qc_findflags;
var entity(entity start, .entity fld, entity match) findentity = qc_findentity;
var entity(entity start, .float fld, float match) findfloat = qc_findfloat;
void() DP_QC_FINDCHAIN =
{
findchain = ext_findchain;
}
void() DP_QC_FINDCHAINFLAGS =
{
findchainflags = ext_findchainflags;
}
void() DP_QC_FINDCHAINFLOAT =
{
findchainfloat = ext_findchainfloat;
findchainentity = ext_findchainentity;
}
void() DP_QC_FINDFLAGS =
{
findflags = ext_findflags;
}
void() DP_QC_FINDFLOAT =
{
findfloat = ext_findfloat;
findentity = ext_findentity;
}