Inside3D!
     

Question regarding making a "CSQC-game"
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming
View previous topic :: View next topic  
Author Message
Urre



Joined: 05 Nov 2004
Posts: 1073
Location: Sweden

PostPosted: Sun Jan 24, 2010 9:30 pm    Post subject: Question regarding making a "CSQC-game" Reply with quote

I was going to ask this on IRC, but I think it'd be good reference for others as well.

What's the minimum SVQC I need to do in order to create a singleplayer game entirely in CSQC?

Can CSQC read map objects and spawn them like SVQC?

Does PVS work the same in CSQC?

What about savegames?

Am I missing some important points regarding making a singleplayer game using as little SVQC and as much CSQC as possible?
_________________
Look out for Twigboy
Back to top
View user's profile Send private message Visit poster's website
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Mon Jan 25, 2010 12:46 am    Post subject: Re: Question regarding making a "CSQC-game" Reply with quote

- What's the minimum SVQC I need to do in order to create a singleplayer game entirely in CSQC?

You need a compatible progs. All it needs to do is sit there and do nothing, basically. System functions need to be stubs. You probably want to stub the spawn functions too. Just empty functions.

- Can CSQC read map objects and spawn them like SVQC?

FTE yes, DP no.
The csprogs does the parsing itself.

- Does PVS work the same in CSQC?

Not entirely sure in what regard.
PVS is technically an optimisation rather than a specific feature.
Only pvs-visible ents are sent to clients, unless its set to send all ents. So yes, you can get ents removed and readded as the player moves around.
inside the csprogs, pvs is invisible to the csprogs. The engine just doesn't draw stuff that cannot be visible.

- What about savegames?

csqc doesn't save games.
The data needs to be fully replicatable. Stats and visible ents. Newly visible ents can have specific flags to send stuff if needed.

- Am I missing some important points regarding making a singleplayer game using as little SVQC and as much CSQC as possible?

You will need to implement movetypes yourself. Other than that, there's no reason that you cannot.
You cannot save the game in csqc unless you make your own save game function, or if you replicate the data to the server to. You can make your own save function though.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
Urre



Joined: 05 Nov 2004
Posts: 1073
Location: Sweden

PostPosted: Mon Jan 25, 2010 2:03 am    Post subject: Reply with quote

What about reading input for movement? How crazy complicated is it? I'm guessing this is kind of tying in with clientside prediction of movement Razz

I actually meant pvs like monsters seeing you or not, gameplay related stuff basicly.

Bmodels are collideable and can push stuff?
_________________
Look out for Twigboy
Back to top
View user's profile Send private message Visit poster's website
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Mon Jan 25, 2010 2:11 am    Post subject: Reply with quote

- What about reading input for movement? How crazy complicated is it? I'm guessing this is kind of tying in with clientside prediction of movement :P

Prediction works thusly: The client generates input frames in a list. Its a ring buffer, basically. You grab the frames from 'acknowledged' to 'current' and apply those input packets to the state of the player. The result is your predicted player.
In a server-less environment you can use the same builtin, but go from 'last frame' to 'current', then save off current as last frame so as to avoid duplicates. (normally acknowleged increases in jumps or so).


- I actually meant pvs like monsters seeing you or not, gameplay related stuff basicly.

There's an fte extension builtin which will give a quick pvs success/fail result if really needed. Its not specifically csqc.
monster's sight is traditionally implemented using tracelines, not pvs.

- Bmodels are collideable and can push stuff?

bmodels are solid, but in the base csqc spec they do not push (this is because there is no .movetype support in the base csqc spec - and thus no think/nextthink either, although that's not always an issue - it was meant to be a followup extension as the engine needs a lot of code, and I wanted a spec that was remotely plausable without rewriting the entire engine from scratch straight off).
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
LordHavoc



Joined: 05 Nov 2004
Posts: 243
Location: western Oregon, USA

PostPosted: Mon Jan 25, 2010 3:22 am    Post subject: Reply with quote

Spike wrote:
- Bmodels are collideable and can push stuff?

bmodels are solid, but in the base csqc spec they do not push (this is because there is no .movetype support in the base csqc spec - and thus no think/nextthink either, although that's not always an issue - it was meant to be a followup extension as the engine needs a lot of code, and I wanted a spec that was remotely plausable without rewriting the entire engine from scratch straight off).


In DP there is .nextthink in CSQC.

Note however that it is triggered by the same code that calls .Predraw so an entity that is filtered out will never call think... I always thought this was part of the CSQC spec because it seemed so odd, but now I guess I know it's [515]'s doing Razz
Back to top
View user's profile Send private message Visit poster's website
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Mon Jan 25, 2010 3:32 am    Post subject: Reply with quote

movetype_push has slightly different nextthink semantics from other movetypes. and without movetypes, those semantics cannot be fully honoured, hence no thinks.
but yeah, you can emulate it in predraw just fine, even if its never drawn, so I never saw this as a major issue.
DP supporting it might be, but mneh, better to get on with full movetypes support.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
Urre



Joined: 05 Nov 2004
Posts: 1073
Location: Sweden

PostPosted: Mon Jan 25, 2010 3:36 am    Post subject: Reply with quote

Checking pvs before doing a traceline can be a useful optimization, just saying.

But yes, I'm not entirely sure how to interpret the pusher-stuff. Can I or can I not have doors and lifts? Is it done somehow different from SSQC?

DP really should add the ability to load mapobjects.
_________________
Look out for Twigboy
Back to top
View user's profile Send private message Visit poster's website
LordHavoc



Joined: 05 Nov 2004
Posts: 243
Location: western Oregon, USA

PostPosted: Mon Jan 25, 2010 11:22 am    Post subject: Reply with quote

Urre wrote:
Checking pvs before doing a traceline can be a useful optimization, just saying.

But yes, I'm not entirely sure how to interpret the pusher-stuff. Can I or can I not have doors and lifts? Is it done somehow different from SSQC?

DP really should add the ability to load mapobjects.


mapobjects? Please clarify what you mean by that?

It can load .bsp files if that is what you mean (as can all quake engines, the ammo boxes were .bsp).
Back to top
View user's profile Send private message Visit poster's website
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Mon Jan 25, 2010 11:49 am    Post subject: Reply with quote

as in parse entities out of the map clientside.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
LordHavoc



Joined: 05 Nov 2004
Posts: 243
Location: western Oregon, USA

PostPosted: Mon Jan 25, 2010 11:49 am    Post subject: Reply with quote

Spike wrote:
movetype_push has slightly different nextthink semantics from other movetypes. and without movetypes, those semantics cannot be fully honoured, hence no thinks.
but yeah, you can emulate it in predraw just fine, even if its never drawn, so I never saw this as a major issue.
DP supporting it might be, but mneh, better to get on with full movetypes support.


Not sure whether it is better to do thinks from Predraw or not, it's probably higher performance to do it from the engine (as it is in DP), but it's not very consistent with the server movetypes where think can happen differently based on movetype (at least for MOVETYPE_PUSH as you indicated).

Supporting the real movetypes would not be particularly hard but I always wanted to go the other way and get rid of the server movetypes, as behaviors have never been particularly good in the engine logic...

The most troublesome Quake movetypes are also the most frequently used, for example MOVETYPE_TOSS, MOVETYPE_BOUNCE, MOVETYPE_FLY, MOVETYPE_FLYMISSILE, MOVETYPE_BOUNCEMISSILE have multiple cvars affecting their behavior (multiple bounces per frame feature, multiple thinks per frame feature, delay projectiles, bounce down slopes bugfix) and some qc callbacks (water transition) and other fields (.bouncefactor, .bouncestop, .gravity) that are also important for some of those movetypes, what makes this particularly problematic is the fact that mods/games often want even more features from these core movetypes and thus they never really settle, where as custom qc movetypes avoids the issue.

However the physics engine support really wants a MOVETYPE_PHYSICS so that is a consideration even in csqc...
Back to top
View user's profile Send private message Visit poster's website
LordHavoc



Joined: 05 Nov 2004
Posts: 243
Location: western Oregon, USA

PostPosted: Mon Jan 25, 2010 11:50 am    Post subject: Reply with quote

Spike wrote:
as in parse entities out of the map clientside.


Not sure if the edict loading builtins are mapped to numbers in the clvm_cmds.c in DP, the menu has the ability to load edicts files... But being able to parse them seems better than spawning the entire set of entities in a .ent file on the csqc side.

Actually, for consistency it would probably be best to make csqc automatically spawn entities whose spawnfunc_ function can be found in the csqc, it would make rain and other particle emitters very easy to handle, and of course spawnfunc_worldspawn would be able to deal with the fog, sky, and other settings present in the worldspawn entity, this would match the ssqc logic except for the omission of support for non-spawnfunc_ classnames.
Back to top
View user's profile Send private message Visit poster's website
Urre



Joined: 05 Nov 2004
Posts: 1073
Location: Sweden

PostPosted: Mon Jan 25, 2010 12:03 pm    Post subject: Reply with quote

LordHavoc wrote:
Actually, for consistency it would probably be best to make csqc automatically spawn entities whose spawnfunc_ function can be found in the csqc, it would make rain and other particle emitters very easy to handle, and of course spawnfunc_worldspawn would be able to deal with the fog, sky, and other settings present in the worldspawn entity, this would match the ssqc logic except for the omission of support for non-spawnfunc_ classnames.


I'm liking the sound of that for sure.

Re-reading the posts regarding pushers in CSQC, how could I possibly emulate it on my own? Confused My physics-brain starts tindling, and I'm actually getting ideas... Care to share some thoughts on how you'd recomend doing it? And what's this about it not being visible?
_________________
Look out for Twigboy
Back to top
View user's profile Send private message Visit poster's website
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Mon Jan 25, 2010 12:41 pm    Post subject: Reply with quote

regarding movetypes in csqc, my prefered method would be a runphysics(entity ent) builtin that handles the think/movetype/touches inside.
ideally, things like rockets and nails will be sent a start pos+time by the server, so shouldn't actually need/use proper physics, just linear projection.
I've no idea how that would interact with movetype_physics type stuff (imho, movetype_physics seems to be fairly memcpy heavy).

if you really want your own movetype_push in csqc then you're kinda screwed. you would need to do a lot of traceboxes for every entity in the new region, detect ents sitting on top, rotate them so they remain on top and move everything on top at the same time as the pusher itself. you would then hope that you know the server's current position of both the pusher and the item, and you need to be able to revert the push if things got blocked.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
LordHavoc



Joined: 05 Nov 2004
Posts: 243
Location: western Oregon, USA

PostPosted: Mon Jan 25, 2010 12:46 pm    Post subject: Reply with quote

Urre wrote:
LordHavoc wrote:
Actually, for consistency it would probably be best to make csqc automatically spawn entities whose spawnfunc_ function can be found in the csqc, it would make rain and other particle emitters very easy to handle, and of course spawnfunc_worldspawn would be able to deal with the fog, sky, and other settings present in the worldspawn entity, this would match the ssqc logic except for the omission of support for non-spawnfunc_ classnames.


I'm liking the sound of that for sure.

Re-reading the posts regarding pushers in CSQC, how could I possibly emulate it on my own? Confused My physics-brain starts tindling, and I'm actually getting ideas... Care to share some thoughts on how you'd recomend doing it? And what's this about it not being visible?


More or less this is what MOVETYPE_PUSH does, you can do this in Predraw:
Code:

newltime = self.ltime + frametime;
if (newltime > self.nextthink)
{
  time = newltime = self.ltime = self.nextthink;
  self.think();
  if (wasfreed(self))
    return;
}
pushsolid = self.solid;
// move to the destination
oldorigin = self.origin;
oldangles = self.angles;
move = self.velocity * frametime;
turn = self.avelocity * frametime;
self.angles = self.angles + turn;
setorigin(self, self.origin + move);
pushmin = self.absmin;
pushmax = self.absmax;
pushcenter = (pushmin + pushmax) * 0.5;
pushradius = (pushmax - pushcenter) * (pushmax - pushcenter);
pushentities = pushent = findradius(pushcenter, pushradius);
// add our own chain to the entities so that they can do radius damage and AI code without messing up our list (but they should not remove themselves!)
while (pushent)
{
  pushent.pushchain = pushent.chain;
  pushent = pushent.chain;
}
// check if each entity is in solid at the destination
pushent = pushentities;
while (pushent)
{
  pushent.pushed = FALSE;
  if (pushent.solid == SOLID_SLIDEBOX || pushent.solid == SOLID_BBOX)
  if (pushent.movetype != MOVETYPE_NONE)
  if (pushent.movetype != MOVETYPE_PUSH)
  if (pushent.movetype != MOVETYPE_NOCLIP)
  if (pushent.movetype != MOVETYPE_FOLLOW)
  if (pushent.movetype != MOVETYPE_FAKEPUSH)
  if (pushent.absmin_x > pushmax_x)
  if (pushent.absmin_y > pushmax_y)
  if (pushent.absmin_z > pushmax_z)
  if (pushent.absmax_x < pushmin_x)
  if (pushent.absmax_y < pushmin_y)
  if (pushent.absmax_z < pushmin_z)
  {
    tracebox(pushent.origin, pushent.mins, pushent.maxs, pushent.origin, MOVE_NOMONSTERS, pushent);
    if (trace_startsolid)
    {
      pushent.solid = SOLID_NOT;
      tracebox(pushent.origin, pushent.mins, pushent.maxs, pushent.origin, MOVE_NOMONSTERS, pushent);
      if (!trace_startsolid)
      {
        // we know that this object is in the way of the pusher, so move it
        pushent.pushed = TRUE;
        pushent.pusholdorigin = pushent.origin;
        pushent.pusholdangles = pushent.angles;
        // calculate local origin (position of entity in the pusher's local coordinate system)
        relativeorigin = pushent.origin - oldorigin;
        localorigin_x = relativeorigin * pushstartforward;
        localorigin_y = relativeorigin * pushstartleft;
        localorigin_z = relativeorigin * pushstartup;
        // calculate world origin of post-push entity
        setorigin(pushent, self.origin + localorigin_x * pushendforward + localorigin_y * pushendleft + localorigin_z * pushendup);
        pushent.angles_y = pushent.angles_y + turn_y;
        tracebox(pushent.origin, pushent.mins, pushent.maxs, pushent.origin, MOVE_NOMONSTERS, pushent);
        if (trace_startsolid)
        {
          // we pushed the entity into a wall, this entity is blocking our movement...  fail the move
          other = pushent;
          // roll back all the entities
          pushent = pushentities;
          while (pushent)
          {
            if (pushent.pushed)
            {
              pushent.angles = pushent.pusholdangles;
              setorigin(pushent, pushent.pusholdorigin);
            }
            pushent = pushent.pushchain;
          }
          self.angles = oldangles;
          setorigin(self, oldorigin);
          // we already set other for this call
          self.blocked();
          break;
        }
      }
      self.solid = pushsolid;
    }
  }
  pushent = pushent.pushchain;
}
self.solid = pushsolid;


That code is incomplete (for example no variables are declared and the pushstartforward and such variables are not being set), but it's the basic concept.

Known bugs in what I typed up:
the pushent can not simply be teleported, it must be a proper tracebox move so that if it hits a wall while riding a moving platform it will not move (or will slide along the wall), because if the pushed entity moves or not, it does not matter, as long as it is not in the way of the pusher at the end position.
the pushent should be pushed if ((pushent.flags & FL_ONGROUND) && pushent.groundentity == self)), even if it is not "colliding" with the pusher at any moment, this means that the tracebox checks must be skipped in this case.

Probably some other bugs I forgot to mention, it was just a quick write-up to explain the concept.
Back to top
View user's profile Send private message Visit poster's website
Urre



Joined: 05 Nov 2004
Posts: 1073
Location: Sweden

PostPosted: Mon Jan 25, 2010 10:32 pm    Post subject: Reply with quote

Looks very, very interesting, although it seems to me like the rotational pushing is either incomplete or I'm missing something? I'm having trouble following how pushstartforward and those actually work, and am suspecting those do the magic, really. You say they're not being set, and I don't really see how they'd be set, making this code hard for me to base anything on. Otherwise awesome stuff!
_________________
Look out for Twigboy
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group