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 icon
Code: 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 here
Code: 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! You need to test,retest,retest, and again and again, and after that, when you think to give up, some little result will come up to make you happy!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