ScratchCSQC?
Posted: Tue Apr 07, 2015 11:56 pm
I was wondering how nice would it be to have a project like ScratchQC, but aimed at CSQC features and modern engines. Specially when dealing with MP stuff, like vweaps. Any guru up to it? 
Great guy, Shpuld!EDIT: also worth mentioning, since it's from scratch, the GPL doesn't apply to it, so I decided to put it under MIT, which should be much more attractive to people who might want to work on more commercial projects and open QC isn't a good option.
But I guess that .worldtype, being related to world entity, instead of self.entity, it won't work.The main way to add a stat is with this builtin:
void(float num, float type, .__variant fld) clientstat = #232;
Which is typically invoked from worldspawn using something like:
clientstat(STAT_MYSUPERSTAT, EV_FLOAT, mysuperstat);
where mysuperstat was defined in defs.qc or whereever as:
.float mysuperstat;
And, as noted above, is read with getstatf(STAT_MYSUPERSTAT)
You'll want to share the STAT_FOO defines between ssqc+csqc.
Code: Select all
void(float num, float type, string name) globalstat = #233; /*
Specifies what data to use in order to send various stats, in a non-client-specific way. num and type are as in clientstat, name however, is the name of the global to read in the form of a string (pass "foo"). */Code: Select all
if(self.mouse1){
SendWorldType();
}
Code: Select all
void SendWorldType()
{
msg_entity = self;
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, PE_WORLDTYPE);
WriteByte(MSG_MULTICAST, world.worldtype);
multicast(self.origin, MULTICAST_ALL);//Or MULTICAST_ONE. That depends to how many audience the messange needs to reach
}
Code: Select all
noref void() CSQC_Parse_Event =
{
local float rb = readbyte();
if(rb == PE_WORLDTYPE){
yourCSQCWorldTypeVar = readbute();//et voila'!Worldtype is saved in your yourCSQCWorldTypeVar
}
}
Code: Select all
if (yourCSQCWorldTypeVar == 0){
cprint("You're in medieval environment\n");
}
else if(yourCSQCWorldTypeVar == 1){
cprint("You're in metalenvironment\n");
}
//and so on..
Code: Select all
float PE_WORLDTYPE=1;Code: Select all
.float this_is_the_worldtype_value;Code: Select all
self.this_is_the_worldtype_value = world.worldtype;Code: Select all
self.SendEntity = send_value_to_csqc;Code: Select all
float()send_value_to_csqc =
{
WriteCoord(MSG_ENTITY, self.this_is_the_worldtype_value);
return TRUE;
};Code: Select all
float worldtype;Code: Select all
worldtype = self.this_is_the_worldtype_value; Code: Select all
If (worldtype == 2)
… use this icon
else if (worldtype == 1)
… use that iconCode: Select all
#define EV_FLOAT 2
void(float num, float type, .__variant fld) clientstat = #232;
void() worldspawn = {
...
clientstat(32, EV_FLOAT, worldtype); //tell the server that stat[32] is a float, and should be sourced from player.worldtype
};
void() PutClientInServer = {
...
self.worldtype = world.worldtype; //make sure that player.worldtype is actually correct.
};
Code: Select all
void(float w,float h, float inmenu) CSQC_UpdateView=
{
float theworldtype = getstatf(32);
if (theworldtype == 2)
… use this icon
else if (theworldtype == 1)
… use that icon
};
Code: Select all
enum
{
et_foo,
et_bar
};
Code: Select all
//system stuff
.float(entity playerent, float changedflags) SendEntity;
.float SendFlags;
float(entity playerent, float changedflags) mysend =
{
writebyte(MSG_ENTITY, et_foo); //lead byte so the csqc can distinguish ent types
writebyte(MSG_ENTITY, changedflags&255); //flags value, so the csqc knows what changed.
if (changedflags & 1)
{
writecoord(MSG_ENTITY, self.origin_x);
writecoord(MSG_ENTITY, self.origin_y);
writecoord(MSG_ENTITY, self.origin_z);
}
if (changedflags & 2)
writebyte(MSG_ENTITY, world.worldtype);
return TRUE;
};
void() somethink =
{
self.nextthink=time+0.1;
setorigin(self, self.origin + '0 0 1'); //this is just an example of an entity moving around.
self.SendFlags |= 1; //flag the origin field as having changed
};
entity(vector pos) spawnsomething =
{
entity e = spawn();
setmodel(e, "progs/player.mdl"); //noone will see it, but dp mandates that a model is set.
e.think = somethink;
self.nextthink=time+0.1;
e.SendEntity = mysend;
e.SendFlags = ~0; //mark all flags as dirty. note that this is implied per-player when an entity first becomes visible to said player.
setorigin(e, pos);
return e;
};
Code: Select all
float theworldtype; //ho hum
void() CSQC_Ent_Remove =
{
//clean up, because the engine won't (this allows the csqc to keep things flying across the room despite being removed from the server - think gib spawn events).
remove(self);
};
void(float isnew) CSQC_Ent_Update =
{
float lead = readbyte();
switch(lead)
{
case et_foo:
if (isnew) //this is the first time we've seen it. note that this MUST NOT affect the reads.
{
setmodel(self, "progs/somethingscary.mdl"); //you precached this, yes?
self.drawmask = 1; //make sure addentities picks us up.
//self.predraw = foo; //put your interpolation in here.
}
float flags = readbyte();
if (flags & 1)
{
self.origin_x = readcoord();
self.origin_y = readcoord();
self.origin_z = readcoord();
setorigin(self, self.origin); //make sure we're relinked, because just writing to origin is bad practise.
}
if (flags & 2)
theworldtype = readbyte(); //oh look. the worldtype changed... more likely it just spawned.
break;
case et_bar:
someothertypethatImincludingasanexamplethatyouwillneedtostripoutorsomething();
break;
default:
error(sprintf("unknown lead byte in entity: %g\n", leadbyte));
break;
}
};
Code: Select all
compiling world.qc
in function worldspawn (line 175),
world.qc:652: error: type mismatch on parm 3 - (.float should be .__variant)
defs.qc:671: clientstat is defined hereCode: Select all
float theworldtype = getstatf(32);Code: Select all
float theworldtype;
theworldtype = getstatf(32);Code: Select all
print(strcat(ftos(theworldtype),"\n"));Code: Select all
float PE_WORLDTYPE = 1;//if you have more of just one parsed events, change 1 with the next free number after the last one - for example, if your last parsed event is PE_WEAPONRELOAD = 5, set this to 6
Code: Select all
.float worldType;
float SECONDSYOUWANT = 5;//it works with 2 sec too on my installation, but, if you want to be super sure...
Code: Select all
void SendWorldType()
{
local float wt;
switch(world.worldType){
case 1:
wt = 1;
break;
case 2:
wt = 2;
break;
case 3:
wt = 3;
break;
default:
wt = 0;//that means error
break;
}
msg_entity = self;
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, PE_WORLDTYPE);
WriteByte(MSG_MULTICAST, world.worldType);
multicast(world.origin, MULTICAST_ALL);
}
//entities find in editor
void worldspawn()
{
//first leaf of every map
self.think=SendWorldType;
self.nextthink = time + SECONDSYOUWANT;//launch SendWorldType after X sec, so we're sure you'll send it
}
Code: Select all
float wType;//no need to be a field. Printing a world.field will make fte craaaaaaaaash!!:)
Code: Select all
noref void() CSQC_Parse_Event =
{
local float rb = readbyte();
if(rb == PE_WORLDTYPE){
local float w = readbyte();//I always found that FTE is happier if you store your readvalues in a tempvar first
wType = w;
}
}
void CSQC_UpdateView(float vwidth, float vheight, float notmenu)
{
// a lot of stuff here to render screen bla bla
cprint(ftos(wType));
}
Believe me, CSQC is not simply for anyone, except for Spike, of course!I guess csqc is simply not for me![]()
Yeah, Spike, I forgot to tell you that last version of win64-fteqccgui.exe on http://triptohell.info/moodles/ gives a strange errorUnfortunately I am forced to use your older version of fteqcc from 2012 (maybe that is the culprit ?),
because the 2015 version gives an error after compiling 90% (independent to the current csqc trial):
Code: Select all
************ ERROR ************
Compile hunk was filled